feat: add tactical command officer cut-ins
This commit is contained in:
@@ -2613,17 +2613,88 @@ async function activateSortieOrderCommand(page, role) {
|
||||
await page.mouse.click(rolePoint.x, rolePoint.y);
|
||||
await page.waitForFunction(
|
||||
(expectedRole) => {
|
||||
const order = window.__HEROS_DEBUG__?.battle()?.sortieOperationOrder;
|
||||
const state = window.__HEROS_DEBUG__?.battle();
|
||||
const order = state?.sortieOperationOrder;
|
||||
return (
|
||||
order?.commandPanelOpen === false &&
|
||||
order?.live?.commandUsed === true &&
|
||||
order?.live?.command?.role === expectedRole
|
||||
order?.live?.command?.role === expectedRole &&
|
||||
state?.tacticalInitiative?.cutIn?.active === true
|
||||
);
|
||||
},
|
||||
role,
|
||||
{ timeout: 30000 }
|
||||
);
|
||||
return page.evaluate(() => window.__HEROS_DEBUG__?.battle()?.sortieOperationOrder);
|
||||
await page.waitForTimeout(180);
|
||||
|
||||
const activeCutInProbe = await page.evaluate(() => {
|
||||
const scene = window.__HEROS_GAME__?.scene.getScene('BattleScene');
|
||||
const state = window.__HEROS_DEBUG__?.battle();
|
||||
return {
|
||||
cutIn: state?.tacticalInitiative?.cutIn ?? null,
|
||||
command: state?.sortieOperationOrder?.live?.command ?? null,
|
||||
sceneBounds: scene
|
||||
? { x: 0, y: 0, width: scene.scale.width, height: scene.scale.height }
|
||||
: null
|
||||
};
|
||||
});
|
||||
assert(
|
||||
activeCutInProbe.cutIn?.active === true &&
|
||||
activeCutInProbe.cutIn.count === 1 &&
|
||||
activeCutInProbe.cutIn.last?.source === 'sortie-order' &&
|
||||
activeCutInProbe.cutIn.last?.role === role &&
|
||||
typeof activeCutInProbe.cutIn.last?.actorId === 'string' &&
|
||||
activeCutInProbe.cutIn.last.actorId.length > 0 &&
|
||||
activeCutInProbe.cutIn.last.actorId === activeCutInProbe.command?.actorId &&
|
||||
activeCutInProbe.cutIn.last?.label === '\uC7AC\uC815\uBE44' &&
|
||||
isFiniteBounds(activeCutInProbe.cutIn.bounds) &&
|
||||
isFiniteBounds(activeCutInProbe.cutIn.last?.bounds) &&
|
||||
isFiniteBounds(activeCutInProbe.sceneBounds) &&
|
||||
boundsInside(activeCutInProbe.cutIn.bounds, activeCutInProbe.sceneBounds) &&
|
||||
boundsInside(activeCutInProbe.cutIn.last.bounds, activeCutInProbe.sceneBounds),
|
||||
`Expected the selected order command to show one bounded in-scene cut-in with its source, role, actor, and label: ${JSON.stringify(activeCutInProbe)}`
|
||||
);
|
||||
await page.screenshot({ path: `${screenshotDir}/rc-first-battle-order-command-cutin.png`, fullPage: true });
|
||||
await assertCanvasPainted(page, 'first battle order command cut-in');
|
||||
|
||||
await page.waitForFunction(
|
||||
(expectedRole) => {
|
||||
const state = window.__HEROS_DEBUG__?.battle();
|
||||
const order = state?.sortieOperationOrder;
|
||||
const cutIn = state?.tacticalInitiative?.cutIn;
|
||||
return (
|
||||
cutIn?.active === false &&
|
||||
cutIn.count === 1 &&
|
||||
cutIn.last?.source === 'sortie-order' &&
|
||||
cutIn.last?.role === expectedRole &&
|
||||
order?.live?.command?.role === expectedRole &&
|
||||
order.live.command.effectPending === false &&
|
||||
order.live.command.effectValue > 0
|
||||
);
|
||||
},
|
||||
role,
|
||||
{ timeout: 30000 }
|
||||
);
|
||||
const settledProbe = await page.evaluate(() => {
|
||||
const state = window.__HEROS_DEBUG__?.battle();
|
||||
return {
|
||||
order: state?.sortieOperationOrder ?? null,
|
||||
cutIn: state?.tacticalInitiative?.cutIn ?? null
|
||||
};
|
||||
});
|
||||
assert(
|
||||
settledProbe.cutIn?.active === false &&
|
||||
settledProbe.cutIn.count === 1 &&
|
||||
settledProbe.cutIn.last?.source === 'sortie-order' &&
|
||||
settledProbe.cutIn.last?.role === role &&
|
||||
settledProbe.cutIn.last?.actorId === settledProbe.order?.live?.command?.actorId &&
|
||||
settledProbe.cutIn.last?.label === '\uC7AC\uC815\uBE44' &&
|
||||
isFiniteBounds(settledProbe.cutIn.last?.bounds) &&
|
||||
settledProbe.order?.live?.command?.effectPending === false &&
|
||||
settledProbe.order?.live?.command?.effectValue > 0,
|
||||
`Expected the cut-in to finish once while retaining its last payload before resolving the support effect: ${JSON.stringify(settledProbe)}`
|
||||
);
|
||||
return settledProbe.order;
|
||||
}
|
||||
|
||||
async function readBattleOrderCommandControlPoint(page, control, role) {
|
||||
|
||||
@@ -1641,6 +1641,14 @@ type IntentCounterplayActionOutcome = {
|
||||
type TacticalInitiativeRole = BattleSaveTacticalCommandRole;
|
||||
type TacticalCommandSource = NonNullable<BattleSaveTacticalCommandState['source']>;
|
||||
|
||||
type TacticalCommandCutInSnapshot = {
|
||||
source: TacticalCommandSource;
|
||||
role: TacticalInitiativeRole;
|
||||
actorId: string;
|
||||
label: string;
|
||||
bounds: SortieOrderHudBounds;
|
||||
};
|
||||
|
||||
type TacticalInitiativeCombatEffect = {
|
||||
role?: TacticalInitiativeRole;
|
||||
damageBonus: number;
|
||||
@@ -3257,6 +3265,11 @@ export class BattleScene extends Phaser.Scene {
|
||||
private battleSpeedControlObjects: Phaser.GameObjects.GameObject[] = [];
|
||||
private tacticalInitiativeChipObjects: Phaser.GameObjects.GameObject[] = [];
|
||||
private tacticalInitiativePanelObjects: Phaser.GameObjects.GameObject[] = [];
|
||||
private tacticalCommandCutInObjects: Phaser.GameObjects.GameObject[] = [];
|
||||
private tacticalCommandCutInBounds?: SortieOrderHudBounds;
|
||||
private tacticalCommandCutInCount = 0;
|
||||
private tacticalCommandCutInLast?: TacticalCommandCutInSnapshot;
|
||||
private tacticalCommandCutInToken = 0;
|
||||
private sortieOrderHudObjects: Phaser.GameObjects.GameObject[] = [];
|
||||
private sortieOrderHudStampObjects: Phaser.GameObjects.GameObject[] = [];
|
||||
private sortieOrderHudBounds?: SortieOrderHudBounds;
|
||||
@@ -3360,6 +3373,10 @@ export class BattleScene extends Phaser.Scene {
|
||||
|
||||
create() {
|
||||
this.hideBattleResult();
|
||||
this.hideTacticalCommandCutIn();
|
||||
this.tacticalCommandCutInCount = 0;
|
||||
this.tacticalCommandCutInLast = undefined;
|
||||
this.events.once(Phaser.Scenes.Events.SHUTDOWN, () => this.hideTacticalCommandCutIn());
|
||||
this.resultFormationReviewVisible = false;
|
||||
this.resultFormationReviewFeedback = '';
|
||||
this.resultPresetOverwriteConfirmId = undefined;
|
||||
@@ -3422,6 +3439,9 @@ export class BattleScene extends Phaser.Scene {
|
||||
});
|
||||
this.input.on('pointermove', (pointer: Phaser.Input.Pointer) => this.updatePointerFeedback(pointer));
|
||||
this.input.keyboard?.on('keydown-ENTER', () => {
|
||||
if (this.tacticalCommandCutInObjects.length > 0) {
|
||||
return;
|
||||
}
|
||||
if (this.tacticalInitiativePanelObjects.length > 0) {
|
||||
return;
|
||||
}
|
||||
@@ -3433,6 +3453,9 @@ export class BattleScene extends Phaser.Scene {
|
||||
this.confirmLockedTargetPreview();
|
||||
});
|
||||
this.input.keyboard?.on('keydown-ESC', () => {
|
||||
if (this.tacticalCommandCutInObjects.length > 0) {
|
||||
return;
|
||||
}
|
||||
if (this.resultSortieOrderVisible) {
|
||||
soundDirector.playSelect();
|
||||
this.hideResultSortieOrder();
|
||||
@@ -3511,7 +3534,7 @@ export class BattleScene extends Phaser.Scene {
|
||||
this.renderBattleSpeedControl();
|
||||
});
|
||||
this.input.keyboard?.on('keydown-PERIOD', () => {
|
||||
if (this.tacticalInitiativePanelObjects.length > 0) {
|
||||
if (this.tacticalInitiativePanelObjects.length > 0 || this.tacticalCommandCutInObjects.length > 0) {
|
||||
return;
|
||||
}
|
||||
this.cycleBattleSpeed();
|
||||
@@ -4797,6 +4820,7 @@ export class BattleScene extends Phaser.Scene {
|
||||
this.alertObjects.length === 0 &&
|
||||
this.battleEventObjects.length === 0 &&
|
||||
this.combatCutInObjects.length === 0 &&
|
||||
this.tacticalCommandCutInObjects.length === 0 &&
|
||||
this.resultObjects.length === 0;
|
||||
|
||||
const highlighted = ready || pending;
|
||||
@@ -4839,6 +4863,7 @@ export class BattleScene extends Phaser.Scene {
|
||||
this.alertObjects.length > 0 ||
|
||||
this.battleEventObjects.length > 0 ||
|
||||
this.combatCutInObjects.length > 0 ||
|
||||
this.tacticalCommandCutInObjects.length > 0 ||
|
||||
this.resultObjects.length > 0 ||
|
||||
this.battleOutcome
|
||||
) {
|
||||
@@ -5042,7 +5067,7 @@ export class BattleScene extends Phaser.Scene {
|
||||
if (available) {
|
||||
const select = () => {
|
||||
this.suppressNextLeftClick = true;
|
||||
this.activateTacticalInitiativeCommand(role);
|
||||
void this.activateTacticalInitiativeCommand(role);
|
||||
};
|
||||
bg.setInteractive({ useHandCursor: true });
|
||||
bg.on('pointerover', () => bg.setFillStyle(0x254451, 1));
|
||||
@@ -5053,7 +5078,7 @@ export class BattleScene extends Phaser.Scene {
|
||||
}
|
||||
}
|
||||
|
||||
private activateTacticalInitiativeCommand(role: TacticalInitiativeRole) {
|
||||
private async activateTacticalInitiativeCommand(role: TacticalInitiativeRole) {
|
||||
const actor = this.tacticalInitiativeActor(role);
|
||||
if (!actor || !this.canUseTacticalInitiativeCommand(role)) {
|
||||
return;
|
||||
@@ -5063,8 +5088,9 @@ export class BattleScene extends Phaser.Scene {
|
||||
return;
|
||||
}
|
||||
|
||||
const source = this.tacticalCommandSource() ?? this.tacticalCommandPanelSource();
|
||||
this.tacticalCommand = {
|
||||
source: this.tacticalCommandSource() ?? this.tacticalCommandPanelSource(),
|
||||
source,
|
||||
role,
|
||||
actorId: actor.id,
|
||||
usedTurn: this.turnNumber,
|
||||
@@ -5088,38 +5114,244 @@ export class BattleScene extends Phaser.Scene {
|
||||
const healText = healAmount > 0 ? `병력 +${healAmount}` : '';
|
||||
const statusText = statusesCleared > 0 ? `상태 ${statusesCleared}개 해제` : '';
|
||||
effectText = `${supportTarget.name} · ${[healText, statusText].filter(Boolean).join(' · ')}`;
|
||||
this.showMapResultPopup(
|
||||
supportTarget,
|
||||
[healAmount > 0 ? `재정비 +${healAmount}` : '재정비', statusesCleared > 0 ? `상태 해제 ${statusesCleared}` : ''],
|
||||
'#a8ffd0',
|
||||
'#071623',
|
||||
18,
|
||||
34
|
||||
);
|
||||
} else {
|
||||
this.showMapResultPopup(
|
||||
actor,
|
||||
[this.tacticalInitiativeCommandLabel(role), role === 'front' ? '적 일반 공격 방호' : '다음 공격 강화'],
|
||||
'#ffdf7b',
|
||||
'#2b1606',
|
||||
18,
|
||||
34
|
||||
);
|
||||
}
|
||||
|
||||
const sourceLabel = this.tacticalCommand.source === 'sortie-order' ? '군령 발동' : '전술 주도권';
|
||||
const sourceLabel = source === 'sortie-order' ? '군령 발동' : '전술 주도권';
|
||||
const message = `${sourceLabel} · ${this.tacticalInitiativeCommandLabel(role)} · ${actor.name}\n${effectText}`;
|
||||
const previousPhase: BattlePhase = this.phase === 'moving' ? 'moving' : 'idle';
|
||||
this.phase = 'animating';
|
||||
this.hideTacticalInitiativePanel();
|
||||
soundDirector.playStrategyPulse();
|
||||
this.pushBattleLog(message);
|
||||
this.renderTacticalInitiativeChip();
|
||||
this.renderSortieOrderHud();
|
||||
this.refreshEnemyIntentForecast();
|
||||
if (this.phase === 'moving' && this.selectedUnit) {
|
||||
if (previousPhase === 'moving' && this.selectedUnit) {
|
||||
this.renderUnitDetail(this.selectedUnit, `${message}\n이동할 파란 칸을 선택하세요.`);
|
||||
} else {
|
||||
this.renderSituationPanel(message);
|
||||
}
|
||||
|
||||
try {
|
||||
const completed = await this.playTacticalCommandCutIn(source, role, actor, effectText);
|
||||
if (!completed || this.battleOutcome) {
|
||||
return;
|
||||
}
|
||||
if (role === 'support' && supportTarget) {
|
||||
const healAmount = this.tacticalCommand.effectValue;
|
||||
const statusesCleared = this.tacticalCommand.statusesCleared;
|
||||
this.showMapResultPopup(
|
||||
supportTarget,
|
||||
[healAmount > 0 ? `재정비 +${healAmount}` : '재정비', statusesCleared > 0 ? `상태 해제 ${statusesCleared}` : ''],
|
||||
'#a8ffd0',
|
||||
'#071623',
|
||||
18,
|
||||
34
|
||||
);
|
||||
} else {
|
||||
this.showMapResultPopup(
|
||||
actor,
|
||||
[this.tacticalInitiativeCommandLabel(role), role === 'front' ? '적 일반 공격 방호' : '다음 공격 강화'],
|
||||
'#ffdf7b',
|
||||
'#2b1606',
|
||||
18,
|
||||
34
|
||||
);
|
||||
}
|
||||
} finally {
|
||||
if (!this.battleOutcome && this.phase === 'animating') {
|
||||
this.phase = previousPhase;
|
||||
this.refreshEnemyIntentForecast();
|
||||
this.renderTacticalInitiativeChip();
|
||||
this.renderSortieOrderHud();
|
||||
if (previousPhase === 'moving' && this.selectedUnit) {
|
||||
this.renderUnitDetail(this.selectedUnit, `${message}\n이동할 파란 칸을 선택하세요.`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async playTacticalCommandCutIn(
|
||||
source: TacticalCommandSource,
|
||||
role: TacticalInitiativeRole,
|
||||
actor: UnitData,
|
||||
effectText: string
|
||||
) {
|
||||
this.hideTacticalCommandCutIn();
|
||||
const token = this.tacticalCommandCutInToken;
|
||||
const width = Math.min(900, Math.max(560, this.scale.width - 120));
|
||||
const height = 206;
|
||||
const left = Math.floor((this.scale.width - width) / 2);
|
||||
const top = Math.floor((this.scale.height - height) / 2);
|
||||
const bounds = { x: left, y: top, width, height };
|
||||
const definition = sortieRoleEffects[role];
|
||||
const roleTone = definition?.tone ?? palette.gold;
|
||||
const sourceTone = source === 'sortie-order' ? palette.gold : palette.blue;
|
||||
const sourceLabel = source === 'sortie-order' ? '군령 발동' : '전술 주도권';
|
||||
const commandLabel = this.tacticalInitiativeCommandLabel(role);
|
||||
const depth = 92;
|
||||
|
||||
this.tacticalCommandCutInBounds = bounds;
|
||||
this.tacticalCommandCutInCount += 1;
|
||||
this.tacticalCommandCutInLast = {
|
||||
source,
|
||||
role,
|
||||
actorId: actor.id,
|
||||
label: commandLabel,
|
||||
bounds: { ...bounds }
|
||||
};
|
||||
|
||||
const dim = this.trackTacticalCommandCutInObject(
|
||||
this.add.rectangle(0, 0, this.scale.width, this.scale.height, 0x020406, 0.7)
|
||||
);
|
||||
dim.setOrigin(0);
|
||||
dim.setDepth(depth);
|
||||
dim.setInteractive();
|
||||
|
||||
const banner = this.trackTacticalCommandCutInObject(this.add.container(left, top));
|
||||
banner.setDepth(depth + 1);
|
||||
const shadow = this.add.rectangle(8, 10, width, height, 0x020406, 0.72);
|
||||
shadow.setOrigin(0);
|
||||
const panel = this.add.rectangle(0, 0, width, height, palette.panelDark, 0.99);
|
||||
panel.setOrigin(0);
|
||||
panel.setStrokeStyle(3, sourceTone, 0.96);
|
||||
const roleBand = this.add.rectangle(0, 0, 12, height, roleTone, 0.96);
|
||||
roleBand.setOrigin(0);
|
||||
const topRule = this.add.rectangle(12, 0, width - 12, 5, sourceTone, 0.82);
|
||||
topRule.setOrigin(0);
|
||||
|
||||
const portraitFrame = this.add.rectangle(92, height / 2, 144, 178, 0x0a0f14, 0.98);
|
||||
portraitFrame.setStrokeStyle(2, roleTone, 0.86);
|
||||
const portraitKey = this.combatPortraitKey(actor);
|
||||
const portrait = portraitKey && this.textures.exists(portraitKey)
|
||||
? this.add.image(92, height / 2, portraitKey).setDisplaySize(132, 166)
|
||||
: this.add.sprite(92, height / 2, this.unitActionTexture(actor), this.unitActionFrameIndex('south', 'strategy'))
|
||||
.setDisplaySize(132, 132);
|
||||
|
||||
const iconFrame = this.add.rectangle(202, 42, 54, 54, 0x0a0f14, 0.96);
|
||||
iconFrame.setStrokeStyle(1, roleTone, 0.82);
|
||||
const icon = this.createBattleUiIcon(202, 42, definition?.icon ?? 'leadership', 46);
|
||||
const sourceText = this.add.text(242, 17, sourceLabel, {
|
||||
fontFamily: '"Malgun Gothic", "Noto Sans KR", sans-serif',
|
||||
fontSize: '14px',
|
||||
color: source === 'sortie-order' ? '#f4dfad' : '#d9f1ff',
|
||||
fontStyle: '700',
|
||||
letterSpacing: 2
|
||||
});
|
||||
const commandText = this.add.text(242, 39, commandLabel, {
|
||||
fontFamily: '"Malgun Gothic", "Noto Sans KR", sans-serif',
|
||||
fontSize: '34px',
|
||||
color: '#fff2b8',
|
||||
fontStyle: '700',
|
||||
stroke: '#05070a',
|
||||
strokeThickness: 4
|
||||
});
|
||||
const actorText = this.add.text(178, 92, `${actor.name} · ${definition?.label ?? this.deploymentRoleLabel(role)}`, {
|
||||
fontFamily: '"Malgun Gothic", "Noto Sans KR", sans-serif',
|
||||
fontSize: '18px',
|
||||
color: '#f2e3bf',
|
||||
fontStyle: '700'
|
||||
});
|
||||
const divider = this.add.rectangle(178, 124, width - 204, 1, roleTone, 0.54);
|
||||
divider.setOrigin(0);
|
||||
const detailText = this.add.text(178, 139, effectText, {
|
||||
fontFamily: '"Malgun Gothic", "Noto Sans KR", sans-serif',
|
||||
fontSize: '15px',
|
||||
color: '#c8d2dd',
|
||||
fontStyle: '700',
|
||||
wordWrap: { width: width - 208, useAdvancedWrap: true },
|
||||
maxLines: 2,
|
||||
lineSpacing: 3
|
||||
});
|
||||
const roleMark = this.add.text(width - 24, 20, this.deploymentRoleLabel(role), {
|
||||
fontFamily: '"Malgun Gothic", "Noto Sans KR", sans-serif',
|
||||
fontSize: '13px',
|
||||
color: '#9fb0bf',
|
||||
fontStyle: '700'
|
||||
});
|
||||
roleMark.setOrigin(1, 0);
|
||||
|
||||
banner.add([
|
||||
shadow,
|
||||
panel,
|
||||
roleBand,
|
||||
topRule,
|
||||
portraitFrame,
|
||||
portrait,
|
||||
iconFrame,
|
||||
icon,
|
||||
sourceText,
|
||||
commandText,
|
||||
actorText,
|
||||
divider,
|
||||
detailText,
|
||||
roleMark
|
||||
]);
|
||||
|
||||
const reducedMotion = typeof window !== 'undefined' &&
|
||||
typeof window.matchMedia === 'function' &&
|
||||
window.matchMedia('(prefers-reduced-motion: reduce)').matches;
|
||||
const enterDuration = this.scaledBattleDuration(150, 100);
|
||||
const exitAt = this.scaledBattleDuration(700, 500);
|
||||
const totalDuration = this.scaledBattleDuration(880, 650);
|
||||
if (!reducedMotion) {
|
||||
banner.setX(left + 28);
|
||||
banner.setAlpha(0);
|
||||
banner.setScale(0.985);
|
||||
this.tweens.add({
|
||||
targets: banner,
|
||||
x: left,
|
||||
alpha: 1,
|
||||
scale: 1,
|
||||
duration: enterDuration,
|
||||
ease: 'Cubic.easeOut'
|
||||
});
|
||||
this.time.delayedCall(exitAt, () => {
|
||||
if (token !== this.tacticalCommandCutInToken || !banner.active) {
|
||||
return;
|
||||
}
|
||||
this.tweens.add({
|
||||
targets: banner,
|
||||
x: left - 18,
|
||||
alpha: 0,
|
||||
duration: enterDuration,
|
||||
ease: 'Cubic.easeIn'
|
||||
});
|
||||
this.tweens.add({ targets: dim, alpha: 0, duration: enterDuration, ease: 'Sine.easeIn' });
|
||||
});
|
||||
} else {
|
||||
this.time.delayedCall(Math.max(0, totalDuration - 90), () => {
|
||||
if (token !== this.tacticalCommandCutInToken || !banner.active) {
|
||||
return;
|
||||
}
|
||||
this.tweens.add({ targets: [banner, dim], alpha: 0, duration: 90, ease: 'Sine.easeIn' });
|
||||
});
|
||||
}
|
||||
|
||||
await new Promise<void>((resolve) => {
|
||||
this.time.delayedCall(totalDuration, resolve);
|
||||
});
|
||||
if (token !== this.tacticalCommandCutInToken) {
|
||||
return false;
|
||||
}
|
||||
this.hideTacticalCommandCutIn();
|
||||
return true;
|
||||
}
|
||||
|
||||
private trackTacticalCommandCutInObject<T extends Phaser.GameObjects.GameObject>(object: T) {
|
||||
this.tacticalCommandCutInObjects.push(object);
|
||||
return object;
|
||||
}
|
||||
|
||||
private hideTacticalCommandCutIn() {
|
||||
this.tacticalCommandCutInToken += 1;
|
||||
this.tacticalCommandCutInObjects.forEach((object) => {
|
||||
this.tweens?.killTweensOf(object);
|
||||
if (object.active) {
|
||||
object.destroy();
|
||||
}
|
||||
});
|
||||
this.tacticalCommandCutInObjects = [];
|
||||
this.tacticalCommandCutInBounds = undefined;
|
||||
}
|
||||
|
||||
private hideTacticalInitiativePanel() {
|
||||
@@ -5135,6 +5367,9 @@ export class BattleScene extends Phaser.Scene {
|
||||
}
|
||||
|
||||
private handleTacticalInitiativeKey(event: KeyboardEvent) {
|
||||
if (this.phase === 'animating' || this.tacticalCommandCutInObjects.length > 0) {
|
||||
return false;
|
||||
}
|
||||
if (this.tacticalInitiativePanelObjects.length > 0) {
|
||||
const role = ({ '1': 'front', '2': 'flank', '3': 'support' } as const)[event.key as '1' | '2' | '3'];
|
||||
if (!role) {
|
||||
@@ -5142,7 +5377,7 @@ export class BattleScene extends Phaser.Scene {
|
||||
}
|
||||
event.preventDefault();
|
||||
if (this.canUseTacticalInitiativeCommand(role)) {
|
||||
this.activateTacticalInitiativeCommand(role);
|
||||
void this.activateTacticalInitiativeCommand(role);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -7792,6 +8027,17 @@ export class BattleScene extends Phaser.Scene {
|
||||
command: this.tacticalCommand ? { ...this.tacticalCommand } : null,
|
||||
panelOpen: this.tacticalInitiativePanelObjects.length > 0,
|
||||
panelBounds: this.tacticalInitiativePanelBounds ? { ...this.tacticalInitiativePanelBounds } : null,
|
||||
cutIn: {
|
||||
active: this.tacticalCommandCutInObjects.length > 0,
|
||||
count: this.tacticalCommandCutInCount,
|
||||
bounds: this.tacticalCommandCutInBounds ? { ...this.tacticalCommandCutInBounds } : null,
|
||||
last: this.tacticalCommandCutInLast
|
||||
? {
|
||||
...this.tacticalCommandCutInLast,
|
||||
bounds: { ...this.tacticalCommandCutInLast.bounds }
|
||||
}
|
||||
: null
|
||||
},
|
||||
cards
|
||||
};
|
||||
}
|
||||
@@ -10668,6 +10914,7 @@ export class BattleScene extends Phaser.Scene {
|
||||
this.hideMapMenu();
|
||||
this.hideTurnEndPrompt();
|
||||
this.hideTacticalInitiativePanel();
|
||||
this.hideTacticalCommandCutIn();
|
||||
this.tacticalInitiativeChipObjects.forEach((object) => object.destroy());
|
||||
this.tacticalInitiativeChipObjects = [];
|
||||
this.hideBattleAlert();
|
||||
@@ -14814,6 +15061,7 @@ export class BattleScene extends Phaser.Scene {
|
||||
this.hideCommandMenu();
|
||||
this.hideTurnEndPrompt();
|
||||
this.hideTacticalInitiativePanel();
|
||||
this.hideTacticalCommandCutIn();
|
||||
this.hideCombatCutIn();
|
||||
this.hideBattleResult();
|
||||
this.resetSortieOrderHudState();
|
||||
|
||||
Reference in New Issue
Block a user