Add ShipStatus system with automatic gauge updates and fuel consumption
All checks were successful
Build / build (push) Successful in 1m26s
All checks were successful
Build / build (push) Successful in 1m26s
Implemented a comprehensive ship status management system with event-driven gauge updates and integrated fuel consumption for both linear and angular thrust. **New File: src/shipStatus.ts** - ShipStatus class with Observable pattern for status change events - Manages fuel, hull, and ammo values with automatic clamping (0-1 range) - Configurable max values for each resource type - Public getters: fuel, hull, ammo, getValues() - Setter methods: setFuel(), setHull(), setAmmo() with automatic event firing - Convenience methods: addFuel(), consumeFuel(), damageHull(), repairHull(), addAmmo(), consumeAmmo() - Status check methods: isFuelEmpty(), isDestroyed(), isAmmoEmpty() - Utility methods: reset(), setMaxValues(), dispose() - ShipStatusChangeEvent interface with statusType, oldValue, newValue, delta fields **Modified: src/scoreboard.ts** - Integrated ShipStatus instance as private _shipStatus - Constructor subscribes to ShipStatus.onStatusChanged observable - Added public shipStatus getter to expose status manager - Created createGaugesDisplay() method with 3 bar gauges (FUEL, HULL, AMMO) - Created createGaugeBar() helper for individual gauge construction - Added getBarColor() with smooth RGB gradient: green (1.0) -> yellow (0.5) -> red (0.0) - Renamed public methods to private: updateFuelBar(), updateHullBar(), updateAmmoBar() - Observable subscription automatically updates gauge visuals when status changes - Added dispose() method for cleanup of ShipStatus and observables - Updated initialize() to retrieve and setup screen/gauges meshes from GLB - Set initial test values to full (1.0) for all gauges **Modified: src/shipPhysics.ts** - Added ShipStatus import and private _shipStatus property - Added setShipStatus() method to connect status manager - Modified applyForces() to check fuel availability before applying linear force - Linear thrust fuel consumption: linearMagnitude (0-1) * 0.005 per frame - Added fuel check and consumption for angular thrust (rotation) - Angular thrust fuel consumption: normalized angularMagnitude (0-1) * 0.005 per frame - Forces only applied when fuel > 0 **Modified: src/ship.ts** - Connected ShipPhysics to Scoreboard's ShipStatus via setShipStatus() - Called immediately after physics initialization (line 148) This creates a fully integrated system where: 1. Ship movement (linear and angular) consumes fuel proportional to thrust 2. Fuel depletion prevents further thrust application 3. Gauge displays automatically update via observable events with color coding 4. Other systems can monitor/modify ship status through the same interface 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
2e1c8ad725
commit
65e7c496b7
@ -1,12 +1,14 @@
|
||||
import {AdvancedDynamicTexture, Control, StackPanel, TextBlock} from "@babylonjs/gui";
|
||||
import {AdvancedDynamicTexture, Control, StackPanel, TextBlock, Rectangle, Container} from "@babylonjs/gui";
|
||||
import {DefaultScene} from "./defaultScene";
|
||||
import {
|
||||
AbstractMesh, Mesh,
|
||||
Mesh,
|
||||
MeshBuilder,
|
||||
Observable, StandardMaterial,
|
||||
Observable,
|
||||
Vector3,
|
||||
} from "@babylonjs/core";
|
||||
import debugLog from './debug';
|
||||
import { ShipStatus } from './shipStatus';
|
||||
|
||||
export type ScoreEvent = {
|
||||
score: number,
|
||||
message: string,
|
||||
@ -21,8 +23,32 @@ export class Scoreboard {
|
||||
private _active = false;
|
||||
private _done = false;
|
||||
public readonly onScoreObservable: Observable<ScoreEvent> = new Observable<ScoreEvent>();
|
||||
constructor() {
|
||||
|
||||
// Gauge bar fill rectangles
|
||||
private _fuelBar: Rectangle | null = null;
|
||||
private _hullBar: Rectangle | null = null;
|
||||
private _ammoBar: Rectangle | null = null;
|
||||
|
||||
// Ship status manager
|
||||
private _shipStatus: ShipStatus;
|
||||
|
||||
constructor() {
|
||||
this._shipStatus = new ShipStatus();
|
||||
|
||||
// Subscribe to status changes to automatically update gauges
|
||||
this._shipStatus.onStatusChanged.add((event) => {
|
||||
switch (event.statusType) {
|
||||
case 'fuel':
|
||||
this.updateFuelBar(event.newValue);
|
||||
break;
|
||||
case 'hull':
|
||||
this.updateHullBar(event.newValue);
|
||||
break;
|
||||
case 'ammo':
|
||||
this.updateAmmoBar(event.newValue);
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
public get done() {
|
||||
return this._done;
|
||||
@ -30,26 +56,60 @@ export class Scoreboard {
|
||||
public set done(value: boolean) {
|
||||
this._done = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the ship status manager
|
||||
*/
|
||||
public get shipStatus(): ShipStatus {
|
||||
return this._shipStatus;
|
||||
}
|
||||
|
||||
public setRemainingCount(count: number) {
|
||||
this._remaining = count;
|
||||
}
|
||||
public initialize(baseMesh: Mesh) {
|
||||
public initialize(): void {
|
||||
const scene = DefaultScene.MainScene;
|
||||
|
||||
const parent = scene.getNodeById('ship');
|
||||
debugLog('Scoreboard parent:', parent);
|
||||
debugLog('Initializing scoreboard');
|
||||
let scoreboard = null;
|
||||
let scoreboard: Mesh | null = null;
|
||||
|
||||
if (baseMesh) {
|
||||
scoreboard = baseMesh;
|
||||
// Retrieve and setup screen mesh from the loaded GLB
|
||||
const screen = scene.getMaterialById("Screen")?.getBindedMeshes()[0] as Mesh;
|
||||
|
||||
if (screen) {
|
||||
// Setup screen mesh: adjust pivot point and rotation
|
||||
const oldParent = screen.parent;
|
||||
screen.setParent(null);
|
||||
screen.setPivotPoint(screen.getBoundingInfo().boundingSphere.center);
|
||||
screen.setParent(oldParent);
|
||||
screen.rotation.y = Math.PI;
|
||||
|
||||
scoreboard = screen;
|
||||
scoreboard.material.dispose();
|
||||
//scoreboard.material = new StandardMaterial("scoreboard", scene);
|
||||
}
|
||||
|
||||
} else {
|
||||
// Retrieve and setup gauges mesh from the loaded GLB
|
||||
const gauges = scene.getMaterialById("Gauges")?.getBindedMeshes()[0] as Mesh;
|
||||
|
||||
if (gauges) {
|
||||
// Setup gauges mesh: adjust pivot point and rotation
|
||||
const oldParent = gauges.parent;
|
||||
gauges.setParent(null);
|
||||
gauges.setPivotPoint(gauges.getBoundingInfo().boundingSphere.center);
|
||||
gauges.setParent(oldParent);
|
||||
//gauges.rotation.z = Math.PI;
|
||||
|
||||
// Create gauges display
|
||||
this.createGaugesDisplay(gauges);
|
||||
}
|
||||
|
||||
// Fallback: create a plane if screen mesh not found
|
||||
if (!scoreboard) {
|
||||
console.error('Screen mesh not found, creating fallback plane');
|
||||
scoreboard = MeshBuilder.CreatePlane("scoreboard", {width: 1, height: 1}, scene);
|
||||
scoreboard.parent =parent;
|
||||
scoreboard.parent = parent;
|
||||
|
||||
scoreboard.position.y = 1.05;
|
||||
scoreboard.position.z = 2.1;
|
||||
@ -66,7 +126,7 @@ export class Scoreboard {
|
||||
|
||||
|
||||
const advancedTexture = AdvancedDynamicTexture.CreateForMesh(scoreboard, 512, 512);
|
||||
advancedTexture.background = "green";
|
||||
advancedTexture.background = "black";
|
||||
advancedTexture.hasAlpha = false;
|
||||
const scoreText = this.createText();
|
||||
|
||||
@ -122,4 +182,171 @@ export class Scoreboard {
|
||||
private calculateScore() {
|
||||
return Math.floor(this._score);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the gauges display with 3 bar gauges (Fuel, Hull, Ammo)
|
||||
*/
|
||||
private createGaugesDisplay(gaugesMesh: Mesh): void {
|
||||
// Store reference to old material to dispose after new one is created
|
||||
const oldMaterial = gaugesMesh.material;
|
||||
|
||||
// Create AdvancedDynamicTexture for the gauges mesh
|
||||
// This creates a new StandardMaterial and assigns it to the mesh
|
||||
const gaugesTexture = AdvancedDynamicTexture.CreateForMesh(gaugesMesh, 512, 512);
|
||||
gaugesTexture.coordinatesIndex = 2;
|
||||
|
||||
|
||||
|
||||
gaugesTexture.background = "#444444";
|
||||
gaugesTexture.hasAlpha = false;
|
||||
|
||||
// Now dispose the old material after the new one is assigned
|
||||
if (oldMaterial) {
|
||||
oldMaterial.dispose(true, true);
|
||||
}
|
||||
|
||||
debugLog('Gauges texture created, material:', gaugesMesh.material?.name);
|
||||
|
||||
// Create a vertical stack panel for the gauges
|
||||
const panel = new StackPanel('GaugesPanel');
|
||||
panel.rotation = Math.PI;
|
||||
panel.isVertical = true;
|
||||
panel.width = "100%";
|
||||
panel.height = "100%";
|
||||
|
||||
// Create the three gauges
|
||||
this._fuelBar = this.createGaugeBar("FUEL", "#00FF00", panel);
|
||||
this._hullBar = this.createGaugeBar("HULL", "#00FF00", panel);
|
||||
this._ammoBar = this.createGaugeBar("AMMO", "#00FF00", panel);
|
||||
|
||||
gaugesTexture.addControl(panel);
|
||||
|
||||
let i = 0;
|
||||
// Force the texture to update
|
||||
//gaugesTexture.markAsDirty();
|
||||
|
||||
// Set initial values to full (for testing visibility)
|
||||
this._shipStatus.setFuel(1);
|
||||
this._shipStatus.setHull(1);
|
||||
this._shipStatus.setAmmo(1);
|
||||
|
||||
debugLog('Gauges display created with initial test values');
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a single gauge bar with label
|
||||
*/
|
||||
private createGaugeBar(label: string, color: string, parent: Container): Rectangle {
|
||||
// Container for this gauge (label + bar)
|
||||
const gaugeContainer = new StackPanel();
|
||||
gaugeContainer.isVertical = true;
|
||||
gaugeContainer.height = "140px";
|
||||
gaugeContainer.width = "100%";
|
||||
gaugeContainer.paddingBottom = "15px";
|
||||
|
||||
// Label text
|
||||
const labelText = new TextBlock();
|
||||
labelText.text = label;
|
||||
labelText.color = "#FFFFFF";
|
||||
labelText.fontSize = "60px";
|
||||
labelText.height = "70px";
|
||||
labelText.textHorizontalAlignment = Control.HORIZONTAL_ALIGNMENT_LEFT;
|
||||
gaugeContainer.addControl(labelText);
|
||||
|
||||
// Bar background (border and empty space)
|
||||
const barBackground = new Rectangle();
|
||||
barBackground.height = "50px";
|
||||
barBackground.width = "100%";
|
||||
barBackground.thickness = 3;
|
||||
barBackground.color = "#FFFFFF";
|
||||
barBackground.background = "#333333";
|
||||
barBackground.cornerRadius = 5;
|
||||
|
||||
// Bar fill (the actual gauge)
|
||||
const barFill = new Rectangle();
|
||||
barFill.height = "100%";
|
||||
barFill.width = "100%"; // Will be updated dynamically
|
||||
barFill.thickness = 0;
|
||||
barFill.background = color;
|
||||
barFill.horizontalAlignment = Control.HORIZONTAL_ALIGNMENT_LEFT;
|
||||
barFill.cornerRadius = 3;
|
||||
|
||||
barBackground.addControl(barFill);
|
||||
gaugeContainer.addControl(barBackground);
|
||||
|
||||
parent.addControl(gaugeContainer);
|
||||
|
||||
return barFill;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get bar color based on value with smooth gradient
|
||||
* Green (1.0) -> Yellow (0.5) -> Red (0.0)
|
||||
*/
|
||||
private getBarColor(value: number): string {
|
||||
// Clamp value between 0 and 1
|
||||
value = Math.max(0, Math.min(1, value));
|
||||
|
||||
let red: number, green: number;
|
||||
|
||||
if (value >= 0.5) {
|
||||
// Interpolate from yellow (0.5) to green (1.0)
|
||||
// At 0.5: RGB(255, 255, 0) yellow
|
||||
// At 1.0: RGB(0, 255, 0) green
|
||||
const t = (value - 0.5) * 2; // 0 to 1 range
|
||||
red = Math.round(255 * (1 - t));
|
||||
green = 255;
|
||||
} else {
|
||||
// Interpolate from red (0.0) to yellow (0.5)
|
||||
// At 0.0: RGB(255, 0, 0) red
|
||||
// At 0.5: RGB(255, 255, 0) yellow
|
||||
const t = value * 2; // 0 to 1 range
|
||||
red = 255;
|
||||
green = Math.round(255 * t);
|
||||
}
|
||||
|
||||
// Convert to hex
|
||||
const redHex = red.toString(16).padStart(2, '0');
|
||||
const greenHex = green.toString(16).padStart(2, '0');
|
||||
return `#${redHex}${greenHex}00`;
|
||||
}
|
||||
/**
|
||||
* Internal method to update fuel gauge bar
|
||||
*/
|
||||
private updateFuelBar(value: number): void {
|
||||
if (this._fuelBar) {
|
||||
this._fuelBar.width = `${value * 100}%`;
|
||||
this._fuelBar.background = this.getBarColor(value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal method to update hull gauge bar
|
||||
*/
|
||||
private updateHullBar(value: number): void {
|
||||
if (this._hullBar) {
|
||||
this._hullBar.width = `${value * 100}%`;
|
||||
this._hullBar.background = this.getBarColor(value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal method to update ammo gauge bar
|
||||
*/
|
||||
private updateAmmoBar(value: number): void {
|
||||
if (this._ammoBar) {
|
||||
this._ammoBar.width = `${value * 100}%`;
|
||||
this._ammoBar.background = this.getBarColor(value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispose of scoreboard resources
|
||||
*/
|
||||
public dispose(): void {
|
||||
if (this._shipStatus) {
|
||||
this._shipStatus.dispose();
|
||||
}
|
||||
this.onScoreObservable.clear();
|
||||
}
|
||||
}
|
||||
18
src/ship.ts
18
src/ship.ts
@ -145,6 +145,7 @@ export class Ship {
|
||||
|
||||
// Initialize physics controller
|
||||
this._physics = new ShipPhysics();
|
||||
this._physics.setShipStatus(this._scoreboard.shipStatus);
|
||||
|
||||
// Setup physics update loop (every 10 frames)
|
||||
DefaultScene.MainScene.onAfterRenderObservable.add(() => {
|
||||
@ -174,21 +175,8 @@ export class Ship {
|
||||
centerGap: 0.5,
|
||||
});
|
||||
|
||||
// Setup scoreboard on screen
|
||||
console.log(data.meshes.get("Screen"));
|
||||
const screen = DefaultScene.MainScene
|
||||
.getMaterialById("Screen")
|
||||
.getBindedMeshes()[0] as AbstractMesh;
|
||||
console.log(screen);
|
||||
const old = screen.parent;
|
||||
screen.setParent(null);
|
||||
screen.setPivotPoint(screen.getBoundingInfo().boundingSphere.center);
|
||||
screen.setParent(old);
|
||||
screen.rotation.y = Math.PI;
|
||||
console.log(screen.rotation);
|
||||
console.log(screen.scaling);
|
||||
|
||||
this._scoreboard.initialize(screen as any);
|
||||
// Initialize scoreboard (it will retrieve and setup its own screen mesh)
|
||||
this._scoreboard.initialize();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import { PhysicsBody, TransformNode, Vector2, Vector3 } from "@babylonjs/core";
|
||||
import { GameConfig } from "./gameConfig";
|
||||
import { ShipStatus } from "./shipStatus";
|
||||
|
||||
export interface InputState {
|
||||
leftStick: Vector2;
|
||||
@ -16,6 +17,14 @@ export interface ForceApplicationResult {
|
||||
* Reads physics parameters from GameConfig for runtime tuning
|
||||
*/
|
||||
export class ShipPhysics {
|
||||
private _shipStatus: ShipStatus | null = null;
|
||||
|
||||
/**
|
||||
* Set the ship status instance for fuel consumption tracking
|
||||
*/
|
||||
public setShipStatus(shipStatus: ShipStatus): void {
|
||||
this._shipStatus = shipStatus;
|
||||
}
|
||||
/**
|
||||
* Apply forces to the ship based on input state
|
||||
* @param inputState - Current input state (stick positions)
|
||||
@ -49,6 +58,8 @@ export class ShipPhysics {
|
||||
if (Math.abs(leftStick.y) > 0.1) {
|
||||
linearMagnitude = Math.abs(leftStick.y);
|
||||
|
||||
// Check if we have fuel before applying force
|
||||
if (this._shipStatus && this._shipStatus.fuel > 0) {
|
||||
// Only apply force if we haven't reached max velocity
|
||||
if (currentSpeed < config.maxLinearVelocity) {
|
||||
// Get local direction (Z-axis for forward/backward thrust)
|
||||
@ -67,6 +78,11 @@ export class ShipPhysics {
|
||||
);
|
||||
|
||||
physicsBody.applyForce(force, thrustPoint);
|
||||
|
||||
// Consume fuel: normalized magnitude (0-1) * 0.01 = max consumption of 0.01 per frame
|
||||
const fuelConsumption = linearMagnitude * 0.005;
|
||||
this._shipStatus.consumeFuel(fuelConsumption);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -78,6 +94,8 @@ export class ShipPhysics {
|
||||
|
||||
// Apply angular forces if any stick has significant rotation input
|
||||
if (angularMagnitude > 0.1) {
|
||||
// Check if we have fuel before applying torque
|
||||
if (this._shipStatus && this._shipStatus.fuel > 0) {
|
||||
const currentAngularSpeed = currentAngularVelocity.length();
|
||||
|
||||
// Only apply torque if we haven't reached max angular velocity
|
||||
@ -96,6 +114,12 @@ export class ShipPhysics {
|
||||
);
|
||||
|
||||
physicsBody.applyAngularImpulse(worldTorque);
|
||||
|
||||
// Consume fuel: normalized magnitude (0-3 max) / 3 * 0.01 = max consumption of 0.01 per frame
|
||||
const normalizedAngularMagnitude = Math.min(angularMagnitude / 3.0, 1.0);
|
||||
const fuelConsumption = normalizedAngularMagnitude * 0.005;
|
||||
this._shipStatus.consumeFuel(fuelConsumption);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
210
src/shipStatus.ts
Normal file
210
src/shipStatus.ts
Normal file
@ -0,0 +1,210 @@
|
||||
import { Observable } from "@babylonjs/core";
|
||||
|
||||
/**
|
||||
* Event data for ship status changes
|
||||
*/
|
||||
export interface ShipStatusChangeEvent {
|
||||
statusType: "fuel" | "hull" | "ammo";
|
||||
oldValue: number;
|
||||
newValue: number;
|
||||
delta: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ship status values container
|
||||
*/
|
||||
export interface ShipStatusValues {
|
||||
fuel: number;
|
||||
hull: number;
|
||||
ammo: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Manages ship status values (fuel, hull integrity, ammo)
|
||||
* Provides observable events for changes and automatic clamping to 0-1 range
|
||||
*/
|
||||
export class ShipStatus {
|
||||
private _fuel: number = 1.0;
|
||||
private _hull: number = 1.0;
|
||||
private _ammo: number = 1.0;
|
||||
|
||||
// Maximum values for each resource
|
||||
private _maxFuel: number = 1.0;
|
||||
private _maxHull: number = 1.0;
|
||||
private _maxAmmo: number = 1.0;
|
||||
|
||||
// Observable for status changes
|
||||
public readonly onStatusChanged: Observable<ShipStatusChangeEvent> =
|
||||
new Observable<ShipStatusChangeEvent>();
|
||||
|
||||
/**
|
||||
* Get current fuel level (0-1)
|
||||
*/
|
||||
public get fuel(): number {
|
||||
return this._fuel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current hull integrity (0-1)
|
||||
*/
|
||||
public get hull(): number {
|
||||
return this._hull;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current ammo level (0-1)
|
||||
*/
|
||||
public get ammo(): number {
|
||||
return this._ammo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all status values
|
||||
*/
|
||||
public getValues(): ShipStatusValues {
|
||||
return {
|
||||
fuel: this._fuel,
|
||||
hull: this._hull,
|
||||
ammo: this._ammo,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Set fuel level directly (clamped to 0-1)
|
||||
*/
|
||||
public setFuel(value: number): void {
|
||||
const oldValue = this._fuel;
|
||||
this._fuel = Math.max(0, Math.min(this._maxFuel, value));
|
||||
|
||||
if (oldValue !== this._fuel) {
|
||||
this.onStatusChanged.notifyObservers({
|
||||
statusType: "fuel",
|
||||
oldValue,
|
||||
newValue: this._fuel,
|
||||
delta: this._fuel - oldValue,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set hull integrity directly (clamped to 0-1)
|
||||
*/
|
||||
public setHull(value: number): void {
|
||||
const oldValue = this._hull;
|
||||
this._hull = Math.max(0, Math.min(this._maxHull, value));
|
||||
|
||||
if (oldValue !== this._hull) {
|
||||
this.onStatusChanged.notifyObservers({
|
||||
statusType: "hull",
|
||||
oldValue,
|
||||
newValue: this._hull,
|
||||
delta: this._hull - oldValue,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set ammo level directly (clamped to 0-1)
|
||||
*/
|
||||
public setAmmo(value: number): void {
|
||||
const oldValue = this._ammo;
|
||||
this._ammo = Math.max(0, Math.min(this._maxAmmo, value));
|
||||
|
||||
if (oldValue !== this._ammo) {
|
||||
this.onStatusChanged.notifyObservers({
|
||||
statusType: "ammo",
|
||||
oldValue,
|
||||
newValue: this._ammo,
|
||||
delta: this._ammo - oldValue,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Increment fuel by delta amount
|
||||
*/
|
||||
public addFuel(delta: number): void {
|
||||
this.setFuel(this._fuel + delta);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrement fuel by delta amount
|
||||
*/
|
||||
public consumeFuel(delta: number): void {
|
||||
this.setFuel(this._fuel - delta);
|
||||
}
|
||||
|
||||
/**
|
||||
* Damage hull by delta amount
|
||||
*/
|
||||
public damageHull(delta: number): void {
|
||||
this.setHull(this._hull - delta);
|
||||
}
|
||||
|
||||
/**
|
||||
* Repair hull by delta amount
|
||||
*/
|
||||
public repairHull(delta: number): void {
|
||||
this.setHull(this._hull + delta);
|
||||
}
|
||||
|
||||
/**
|
||||
* Increment ammo by delta amount
|
||||
*/
|
||||
public addAmmo(delta: number): void {
|
||||
this.setAmmo(this._ammo + delta);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrement ammo by delta amount (fire weapon)
|
||||
*/
|
||||
public consumeAmmo(delta: number): void {
|
||||
this.setAmmo(this._ammo - delta);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if fuel is depleted
|
||||
*/
|
||||
public isFuelEmpty(): boolean {
|
||||
return this._fuel <= 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if hull is destroyed
|
||||
*/
|
||||
public isDestroyed(): boolean {
|
||||
return this._hull <= 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if ammo is depleted
|
||||
*/
|
||||
public isAmmoEmpty(): boolean {
|
||||
return this._ammo <= 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset all values to full
|
||||
*/
|
||||
public reset(): void {
|
||||
this.setFuel(this._maxFuel);
|
||||
this.setHull(this._maxHull);
|
||||
this.setAmmo(this._maxAmmo);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set maximum values for resources
|
||||
*/
|
||||
public setMaxValues(fuel?: number, hull?: number, ammo?: number): void {
|
||||
if (fuel !== undefined) this._maxFuel = fuel;
|
||||
if (hull !== undefined) this._maxHull = hull;
|
||||
if (ammo !== undefined) this._maxAmmo = ammo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispose observables
|
||||
*/
|
||||
public dispose(): void {
|
||||
this.onStatusChanged.clear();
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user