Files
tankwar_proj/js/managers/BuffManager.js
2026-04-10 22:59:39 +08:00

218 lines
5.5 KiB
JavaScript

/**
* BuffManager.js
* Manages pre-game buff purchases and activation.
* Buffs are one-time per round: Shield (100g) and Double Fire (150g).
*/
/** Buff type definitions. */
const BUFF_TYPE = {
SHIELD: 'SHIELD',
DOUBLE_FIRE: 'DOUBLE_FIRE',
};
/** Buff cost in gold. */
const BUFF_COST = {
[BUFF_TYPE.SHIELD]: 100,
[BUFF_TYPE.DOUBLE_FIRE]: 150,
};
/** Double fire duration in seconds. */
const DOUBLE_FIRE_DURATION = 10;
class BuffManager {
constructor() {
/** @type {Set<string>} Active buffs for the current round. */
this._activeBuffs = new Set();
/** @type {number} Remaining double fire time in seconds. */
this._doubleFireTimer = 0;
/** @type {boolean} Whether shield is currently active. */
this._shieldActive = false;
}
// ============================================================
// Purchase
// ============================================================
/**
* Purchase a buff for the upcoming round.
* Deducts gold via CurrencyManager.
* @param {string} buffType - One of BUFF_TYPE values.
* @returns {{ success: boolean, error?: string }}
*/
purchaseBuff(buffType) {
const cost = BUFF_COST[buffType];
if (cost === undefined) {
return { success: false, error: 'Invalid buff type' };
}
if (this._activeBuffs.has(buffType)) {
return { success: false, error: 'Already purchased' };
}
const cm = GameGlobal.currencyManager;
if (!cm || !cm.hasGold(cost)) {
return { success: false, error: 'Insufficient gold' };
}
const spent = cm.spendGold(cost);
if (!spent) {
return { success: false, error: 'Insufficient gold' };
}
this._activeBuffs.add(buffType);
console.log(`[BuffManager] Purchased buff: ${buffType} for ${cost} gold`);
// Emit event
try {
if (GameGlobal.eventBus) {
GameGlobal.eventBus.emit('buff:purchased', { type: buffType, cost });
}
} catch (e) {}
return { success: true };
}
// ============================================================
// Activation & Game Logic
// ============================================================
/**
* Check if a buff was purchased for this round.
* @param {string} buffType
* @returns {boolean}
*/
hasBuff(buffType) {
return this._activeBuffs.has(buffType);
}
/**
* Get all active buffs for this round.
* @returns {string[]}
*/
getActiveBuffs() {
return Array.from(this._activeBuffs);
}
/**
* Activate buffs at the start of a round.
* Should be called when the game scene initializes.
* @param {object} playerTank - The player tank instance.
*/
activateBuffs(playerTank) {
if (!playerTank) return;
// Shield buff: add a shield layer to the player tank
if (this._activeBuffs.has(BUFF_TYPE.SHIELD)) {
this._shieldActive = true;
playerTank._buffShield = true;
console.log('[BuffManager] Shield buff activated');
}
// Double fire buff: start the timer
if (this._activeBuffs.has(BUFF_TYPE.DOUBLE_FIRE)) {
this._doubleFireTimer = DOUBLE_FIRE_DURATION;
playerTank._buffDoubleFire = true;
console.log('[BuffManager] Double fire buff activated');
}
}
/**
* Update buff timers. Called every frame from GameScene.
* @param {number} dt - Delta time in seconds.
* @param {object} playerTank - The player tank instance.
*/
update(dt, playerTank) {
if (!playerTank) return;
// Double fire timer countdown
if (this._doubleFireTimer > 0) {
this._doubleFireTimer -= dt;
if (this._doubleFireTimer <= 0) {
this._doubleFireTimer = 0;
playerTank._buffDoubleFire = false;
console.log('[BuffManager] Double fire buff expired');
}
}
}
/**
* Consume the shield buff (called when player takes damage).
* @param {object} playerTank - The player tank instance.
* @returns {boolean} True if shield was consumed (damage absorbed).
*/
consumeShield(playerTank) {
if (this._shieldActive && playerTank && playerTank._buffShield) {
this._shieldActive = false;
playerTank._buffShield = false;
console.log('[BuffManager] Shield buff consumed');
// Emit event for visual feedback
try {
if (GameGlobal.eventBus) {
GameGlobal.eventBus.emit('buff:shield:consumed');
}
} catch (e) {}
return true;
}
return false;
}
/**
* Check if double fire is currently active.
* @returns {boolean}
*/
isDoubleFireActive() {
return this._doubleFireTimer > 0;
}
/**
* Get remaining double fire time in seconds.
* @returns {number}
*/
getDoubleFireRemaining() {
return Math.max(0, this._doubleFireTimer);
}
/**
* Check if shield buff is still active (not yet consumed).
* @returns {boolean}
*/
isShieldActive() {
return this._shieldActive;
}
// ============================================================
// Round Lifecycle
// ============================================================
/**
* Clear all buffs at the end of a round.
* Must be called when the game ends (win or lose).
*/
clearBuffs() {
this._activeBuffs.clear();
this._doubleFireTimer = 0;
this._shieldActive = false;
console.log('[BuffManager] All buffs cleared');
}
/**
* Get buff cost.
* @param {string} buffType
* @returns {number}
*/
getBuffCost(buffType) {
return BUFF_COST[buffType] || 0;
}
}
// Export constants
BuffManager.BUFF_TYPE = BUFF_TYPE;
BuffManager.BUFF_COST = BUFF_COST;
BuffManager.DOUBLE_FIRE_DURATION = DOUBLE_FIRE_DURATION;
module.exports = BuffManager;