- Implemented 10 sub-systems (Economy, Pathfinding, Combat, Selection, Network, Map, Entity/Building/ControlPoint state machines, Orchestrator) - Refactored Custom_Entity.js → Unit.js with 5 components (health, owner, inventory, movement, combat) - Added Jest test suite with 100+ tests (EconomySystem 100%, EntityStateMachine 100%, PathfindingSystem 99%, Unit.js 72%) - All webpack builds pass (0 errors) - BMAD-auto team-respawn flow: 10 parallel sub-agents implemented systems Architecture: Phaser 3 + XState + socket.io + EasyStar Mode: team-respawn Model: custom/ollama-cloud-pro
115 lines
3.5 KiB
JavaScript
115 lines
3.5 KiB
JavaScript
/**
|
|
* CombatComponent — weapon range, damage, fire rate for a Unit.
|
|
*/
|
|
import CONSTANTS from 'PhaserClasses/CustomConstants';
|
|
|
|
export default class CombatComponent {
|
|
/**
|
|
* @param {import('../Unit').default} unit
|
|
* @param {Object} [config]
|
|
* @param {number} [config.range=150] - weapon range in px
|
|
* @param {number} [config.damage=10] - base damage per hit
|
|
* @param {number} [config.fireRate=1000] - ms between shots
|
|
* @param {string} [config.damageType='rifle'] - key into CombatSystem modifiers
|
|
* @param {number} [config.accuracy=1.0] - 0.0 to 1.0 hit probability
|
|
*/
|
|
constructor(unit, config = {}) {
|
|
this.unit = unit;
|
|
|
|
/** @type {number} */
|
|
this._range = config.range ?? CONSTANTS.RIFLE.RANGE;
|
|
|
|
/** @type {number} */
|
|
this._damage = config.damage ?? CONSTANTS.RIFLE.DAMAGE;
|
|
|
|
/** @type {number} */
|
|
this._fireRate = config.fireRate ?? 1000;
|
|
|
|
/** @type {string} */
|
|
this._damageType = config.damageType ?? 'rifle';
|
|
|
|
/** @type {number} */
|
|
this._accuracy = config.accuracy ?? 1.0;
|
|
|
|
/** @type {number} */
|
|
this._lastFireTime = 0;
|
|
|
|
/** @type {import('../Unit').default|null} */
|
|
this._target = null;
|
|
}
|
|
|
|
// ── Accessors ─────────────────────────────────────────────────
|
|
|
|
/** @returns {number} */ get range() { return this._range; }
|
|
/** @returns {number} */ get damage() { return this._damage; }
|
|
/** @returns {number} */ get fireRate() { return this._fireRate; }
|
|
/** @returns {string} */ get damageType() { return this._damageType; }
|
|
/** @returns {number} */ get accuracy() { return this._accuracy; }
|
|
/** @returns {number} */ get lastFireTime() { return this._lastFireTime; }
|
|
/** @returns {import('../Unit').default|null} */ get target() { return this._target; }
|
|
|
|
/** @param {number} val */
|
|
set range(val) { this._range = val; }
|
|
|
|
/** @param {number} val */
|
|
set damage(val) { this._damage = val; }
|
|
|
|
/** @param {number} val */
|
|
set fireRate(val) { this._fireRate = val; }
|
|
|
|
/** @param {import('../Unit').default|null} val */
|
|
set target(val) { this._target = val; }
|
|
|
|
// ── Public API ────────────────────────────────────────────────
|
|
|
|
/**
|
|
* Check if the weapon can fire (cooldown elapsed).
|
|
* @param {number} currentTime - scene time in ms
|
|
* @returns {boolean}
|
|
*/
|
|
canFire(currentTime) {
|
|
return (currentTime - this._lastFireTime) >= this._fireRate;
|
|
}
|
|
|
|
/**
|
|
* Record a shot fired at the given time.
|
|
* @param {number} time - scene time in ms
|
|
*/
|
|
recordFire(time) {
|
|
this._lastFireTime = time;
|
|
}
|
|
|
|
/**
|
|
* Check if this unit can hit a target based on range.
|
|
* @param {import('../Unit').default} target
|
|
* @returns {boolean}
|
|
*/
|
|
canHitBody(target) {
|
|
if (!target || !target.body || !this.unit || !this.unit.body) return false;
|
|
const pointA = this.unit.body.center;
|
|
const pointB = target.body.center;
|
|
return Phaser.Math.Distance.BetweenPoints(pointA, pointB) < this._range;
|
|
}
|
|
|
|
/**
|
|
* Check if a shot connects (accuracy roll).
|
|
* @returns {boolean}
|
|
*/
|
|
accuracyCheck() {
|
|
return Math.random() < this._accuracy;
|
|
}
|
|
|
|
/**
|
|
* Serialize for network sync.
|
|
*/
|
|
serialize() {
|
|
return {
|
|
range: this._range,
|
|
damage: this._damage,
|
|
fireRate: this._fireRate,
|
|
damageType: this._damageType,
|
|
accuracy: this._accuracy,
|
|
};
|
|
}
|
|
}
|