import { LitElement, html, css } from "lit"; export class TeamBuilder extends LitElement { static get styles() { return css` :host { display: block; position: absolute; top: 0; left: 0; width: 100%; height: 100%; font-family: "Courier New", monospace; /* Placeholder for Voxel Font */ color: white; pointer-events: none; /* Let clicks pass through to 3D scene where empty */ z-index: 10; } .container { display: grid; grid-template-columns: 250px 1fr 250px; grid-template-rows: 1fr 80px; height: 100%; width: 100%; pointer-events: auto; background: rgba(0, 0, 0, 0.4); /* Dim background */ } /* --- LEFT PANEL: ROSTER --- */ .roster-panel { background: rgba(20, 20, 30, 0.9); border-right: 2px solid #555; padding: 1rem; overflow-y: auto; } .class-card { background: #333; border: 2px solid #555; padding: 10px; margin-bottom: 10px; cursor: pointer; transition: all 0.2s; display: flex; align-items: center; gap: 10px; } .class-card:hover { border-color: #00ffff; background: #444; } .class-card.locked { opacity: 0.5; pointer-events: none; filter: grayscale(1); } /* --- CENTER PANEL: SLOTS --- */ .squad-panel { display: flex; justify-content: center; align-items: flex-end; padding-bottom: 2rem; gap: 20px; } .squad-slot { width: 120px; height: 150px; background: rgba(0, 0, 0, 0.6); border: 2px dashed #666; display: flex; flex-direction: column; align-items: center; justify-content: center; cursor: pointer; position: relative; } .squad-slot.filled { border: 2px solid #00ff00; background: rgba(0, 50, 0, 0.6); } .squad-slot.selected { border-color: #00ffff; box-shadow: 0 0 10px #00ffff; } .remove-btn { position: absolute; top: -10px; right: -10px; background: red; border: none; color: white; width: 24px; height: 24px; border-radius: 50%; cursor: pointer; font-weight: bold; } /* --- RIGHT PANEL: DETAILS --- */ .details-panel { background: rgba(20, 20, 30, 0.9); border-left: 2px solid #555; padding: 1rem; } /* --- FOOTER --- */ .footer { grid-column: 1 / -1; display: flex; justify-content: center; align-items: center; background: rgba(10, 10, 20, 0.95); border-top: 2px solid #555; } .embark-btn { padding: 15px 40px; font-size: 1.5rem; background: #008800; color: white; border: 2px solid #00ff00; cursor: pointer; text-transform: uppercase; font-weight: bold; } .embark-btn:disabled { background: #333; border-color: #555; color: #777; cursor: not-allowed; } `; } static get properties() { return { availableClasses: { type: Array }, // Input: List of class definition objects squad: { type: Array }, // Internal State: The 4 slots selectedSlotIndex: { type: Number }, hoveredClass: { type: Object }, }; } constructor() { super(); this.squad = [null, null, null, null]; this.selectedSlotIndex = 0; // Default to first slot this.availableClasses = []; // Passed in by parent this.hoveredClass = null; } render() { const isSquadValid = this.squad.some((u) => u !== null); return html`

Roster

${this.availableClasses.map( (cls) => html`
${cls.icon || "⚔️"}
${cls.name}
${cls.role}
` )}
${this.squad.map( (unit, index) => html`
${unit ? html`
${unit.icon || "🛡️"}
${unit.name} ` : html`Slot ${index + 1}
Select Class
`}
` )}
${this.hoveredClass ? html`

${this.hoveredClass.name}

${this.hoveredClass.role}


${this.hoveredClass.description || "No description available."}

Base Stats

` : html`

Hover over a class to see details.

`}
`; } // --- LOGIC --- _selectSlot(index) { this.selectedSlotIndex = index; } _assignClass(classDef) { if (!classDef.unlocked) return; // 1. Create a lightweight manifest for the slot const unitManifest = { classId: classDef.id, name: classDef.name, // In real app, auto-generate name icon: classDef.icon, }; // 2. Update State (Trigger Re-render) const newSquad = [...this.squad]; newSquad[this.selectedSlotIndex] = unitManifest; this.squad = newSquad; // 3. Auto-advance selection if (this.selectedSlotIndex < 3) { this.selectedSlotIndex++; } // 4. Dispatch Event (For 3D Scene to show model) this.dispatchEvent( new CustomEvent("squad-update", { detail: { slot: this.selectedSlotIndex, unit: unitManifest }, bubbles: true, composed: true, }) ); } _removeUnit(e, index) { e.stopPropagation(); // Prevent slot selection const newSquad = [...this.squad]; newSquad[index] = null; this.squad = newSquad; this.selectedSlotIndex = index; // Select the empty slot // Dispatch Event (To clear 3D model) this.dispatchEvent( new CustomEvent("squad-update", { detail: { slot: index, unit: null }, bubbles: true, composed: true, }) ); } _handleEmbark() { const manifest = this.squad.filter((u) => u !== null); this.dispatchEvent( new CustomEvent("embark", { detail: { squad: manifest }, bubbles: true, composed: true, }) ); } } customElements.define("team-builder", TeamBuilder);