2025-12-16 23:52:58 +00:00
|
|
|
import { LitElement, html, css } from "lit";
|
2025-12-19 23:07:36 +00:00
|
|
|
import { gameStateManager } from "../core/GameStateManager.js";
|
|
|
|
|
import { GameLoop } from "../core/GameLoop.js";
|
2025-12-16 23:52:58 +00:00
|
|
|
|
2025-12-21 05:04:44 +00:00
|
|
|
import "./deployment-hud.js";
|
2025-12-22 05:20:33 +00:00
|
|
|
import "./dialogue-overlay.js";
|
|
|
|
|
import "./combat-hud.js";
|
2025-12-21 05:04:44 +00:00
|
|
|
|
2025-12-16 23:52:58 +00:00
|
|
|
export class GameViewport extends LitElement {
|
2025-12-16 23:14:39 +00:00
|
|
|
static styles = css`
|
|
|
|
|
:host {
|
|
|
|
|
display: block;
|
|
|
|
|
width: 100%;
|
|
|
|
|
height: 100%;
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
}
|
2025-12-16 23:52:58 +00:00
|
|
|
#canvas-container {
|
2025-12-16 23:14:39 +00:00
|
|
|
width: 100%;
|
|
|
|
|
height: 100%;
|
|
|
|
|
}
|
|
|
|
|
`;
|
|
|
|
|
|
2025-12-21 05:04:44 +00:00
|
|
|
static get properties() {
|
|
|
|
|
return {
|
|
|
|
|
squad: { type: Array },
|
2025-12-22 04:40:48 +00:00
|
|
|
deployedIds: { type: Array },
|
2025-12-22 22:34:43 +00:00
|
|
|
combatState: { type: Object },
|
2025-12-28 00:54:03 +00:00
|
|
|
missionDef: { type: Object },
|
2025-12-21 05:04:44 +00:00
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
2025-12-16 23:52:58 +00:00
|
|
|
constructor() {
|
|
|
|
|
super();
|
2025-12-21 05:04:44 +00:00
|
|
|
this.squad = [];
|
2025-12-22 04:40:48 +00:00
|
|
|
this.deployedIds = [];
|
2025-12-22 22:34:43 +00:00
|
|
|
this.combatState = null;
|
2025-12-28 00:54:03 +00:00
|
|
|
this.missionDef = null;
|
2025-12-21 05:04:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#handleUnitSelected(event) {
|
2025-12-22 04:40:48 +00:00
|
|
|
const unit = event.detail.unit;
|
|
|
|
|
const index = this.squad.indexOf(unit);
|
2025-12-21 05:04:44 +00:00
|
|
|
gameStateManager.gameLoop.selectDeploymentUnit(index);
|
2025-12-16 23:52:58 +00:00
|
|
|
}
|
|
|
|
|
|
2025-12-22 05:20:33 +00:00
|
|
|
#handleStartBattle() {
|
|
|
|
|
if (gameStateManager.gameLoop) {
|
|
|
|
|
gameStateManager.gameLoop.finalizeDeployment();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-12-24 00:22:32 +00:00
|
|
|
#handleEndTurn() {
|
|
|
|
|
if (gameStateManager.gameLoop) {
|
|
|
|
|
gameStateManager.gameLoop.endTurn();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-12-24 05:01:54 +00:00
|
|
|
#handleSkillClick(event) {
|
|
|
|
|
const { skillId } = event.detail;
|
|
|
|
|
if (gameStateManager.gameLoop) {
|
|
|
|
|
gameStateManager.gameLoop.onSkillClicked(skillId);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-12-17 19:26:42 +00:00
|
|
|
async firstUpdated() {
|
2025-12-16 23:14:39 +00:00
|
|
|
const container = this.shadowRoot.getElementById("canvas-container");
|
2025-12-19 23:07:36 +00:00
|
|
|
const loop = new GameLoop();
|
|
|
|
|
loop.init(container);
|
|
|
|
|
gameStateManager.setGameLoop(loop);
|
2025-12-28 00:54:03 +00:00
|
|
|
|
|
|
|
|
// Don't set squad from rosterLoaded - that's the full roster, not the current mission squad
|
|
|
|
|
// Squad will be set from activeRunData when transitioning to deployment state
|
|
|
|
|
|
|
|
|
|
// Get mission definition for deployment hints
|
|
|
|
|
this.missionDef =
|
|
|
|
|
gameStateManager.missionManager?.getActiveMission() || null;
|
2025-12-22 22:34:43 +00:00
|
|
|
|
|
|
|
|
// Set up combat state updates
|
|
|
|
|
this.#setupCombatStateUpdates();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#setupCombatStateUpdates() {
|
|
|
|
|
// Listen for combat state changes
|
|
|
|
|
window.addEventListener("combat-state-changed", (e) => {
|
|
|
|
|
this.combatState = e.detail.combatState;
|
|
|
|
|
});
|
|
|
|
|
|
2025-12-28 00:54:03 +00:00
|
|
|
// Listen for game state changes to update combat state
|
2025-12-22 22:34:43 +00:00
|
|
|
window.addEventListener("gamestate-changed", () => {
|
|
|
|
|
this.#updateCombatState();
|
|
|
|
|
});
|
|
|
|
|
|
2025-12-28 00:54:03 +00:00
|
|
|
// Listen for run data updates to get the current mission squad
|
|
|
|
|
window.addEventListener("run-data-updated", (e) => {
|
|
|
|
|
if (e.detail.runData?.squad) {
|
|
|
|
|
this.squad = e.detail.runData.squad;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Initial updates
|
2025-12-22 22:34:43 +00:00
|
|
|
this.#updateCombatState();
|
2025-12-28 00:54:03 +00:00
|
|
|
this.#updateSquad();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#updateSquad() {
|
|
|
|
|
// Update squad from activeRunData if available (current mission squad, not full roster)
|
|
|
|
|
if (gameStateManager.activeRunData?.squad) {
|
|
|
|
|
this.squad = gameStateManager.activeRunData.squad;
|
|
|
|
|
}
|
2025-12-22 22:34:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#updateCombatState() {
|
|
|
|
|
// Get combat state from GameStateManager
|
|
|
|
|
this.combatState = gameStateManager.getCombatState();
|
2025-12-16 23:14:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
render() {
|
2025-12-21 05:04:44 +00:00
|
|
|
return html`<div id="canvas-container"></div>
|
|
|
|
|
<deployment-hud
|
2025-12-22 04:40:48 +00:00
|
|
|
.squad=${this.squad}
|
|
|
|
|
.deployedIds=${this.deployedIds}
|
2025-12-28 00:54:03 +00:00
|
|
|
.missionDef=${this.missionDef}
|
2025-12-21 05:04:44 +00:00
|
|
|
@unit-selected=${this.#handleUnitSelected}
|
2025-12-22 05:20:33 +00:00
|
|
|
@start-battle=${this.#handleStartBattle}
|
|
|
|
|
></deployment-hud>
|
2025-12-24 00:22:32 +00:00
|
|
|
<combat-hud
|
|
|
|
|
.combatState=${this.combatState}
|
|
|
|
|
@end-turn=${this.#handleEndTurn}
|
2025-12-24 05:01:54 +00:00
|
|
|
@skill-click=${this.#handleSkillClick}
|
2025-12-24 00:22:32 +00:00
|
|
|
></combat-hud>
|
2025-12-22 05:20:33 +00:00
|
|
|
<dialogue-overlay></dialogue-overlay>`;
|
2025-12-16 23:14:39 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
customElements.define("game-viewport", GameViewport);
|