Refine FOW visuals, Turn Skipping logic, and UI Polish
This commit is contained in:
@@ -55,6 +55,12 @@ export class GameEngine {
|
||||
if (phase === 'hero') {
|
||||
this.initializeTurnOrder();
|
||||
}
|
||||
if (phase === 'monster') {
|
||||
if (window.RENDERER && window.RENDERER.clearAllActiveRings) {
|
||||
window.RENDERER.clearAllActiveRings();
|
||||
}
|
||||
this.deselectEntity();
|
||||
}
|
||||
});
|
||||
|
||||
// End of Turn Logic (Buffs, cooldowns, etc)
|
||||
@@ -211,9 +217,44 @@ export class GameEngine {
|
||||
|
||||
nextHeroTurn() {
|
||||
this.currentTurnIndex++;
|
||||
if (this.currentTurnIndex < this.heroTurnOrder.length) {
|
||||
this.activateHero(this.heroTurnOrder[this.currentTurnIndex]);
|
||||
} else {
|
||||
|
||||
// Loop to find next VALID hero (visible)
|
||||
while (this.currentTurnIndex < this.heroTurnOrder.length) {
|
||||
const nextHero = this.heroTurnOrder[this.currentTurnIndex];
|
||||
|
||||
// Check visibility
|
||||
// Exception: Leader (hasLantern) is ALWAYS visible.
|
||||
if (nextHero.hasLantern) {
|
||||
this.activateHero(nextHero);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if hero is in a visible tile
|
||||
// Get hero tile ID
|
||||
const heroTileId = this.dungeon.grid.occupiedCells.get(`${nextHero.x},${nextHero.y}`);
|
||||
|
||||
// If currentVisibleTileIds is defined, enforce it.
|
||||
if (this.currentVisibleTileIds) {
|
||||
if (heroTileId && this.currentVisibleTileIds.has(heroTileId)) {
|
||||
this.activateHero(nextHero);
|
||||
return;
|
||||
} else {
|
||||
console.log(`Skipping turn for ${nextHero.name} (In Darkness)`);
|
||||
if (this.onShowMessage) {
|
||||
// Optional: Small notification or log
|
||||
// this.onShowMessage("Perdido en la oscuridad", `${nextHero.name} pierde su turno.`);
|
||||
}
|
||||
this.currentTurnIndex++; // Skip and continue loop
|
||||
}
|
||||
} else {
|
||||
// Should not happen if updateLighting runs, but fallback
|
||||
this.activateHero(nextHero);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// If loop finishes, no more heroes
|
||||
if (this.currentTurnIndex >= this.heroTurnOrder.length) {
|
||||
console.log("All heroes acted. Ending Phase sequence if auto?");
|
||||
this.deselectEntity();
|
||||
if (window.RENDERER) {
|
||||
@@ -391,9 +432,23 @@ export class GameEngine {
|
||||
|
||||
if (this.selectedEntity === clickedEntity) {
|
||||
// Toggle Deselect
|
||||
// Prevent deselecting active hero effectively? Or allow it but re-select him if trying to select others?
|
||||
// For now, allow deselect freely.
|
||||
this.deselectEntity();
|
||||
// EXCEPTION: In Hero Phase, if I click MYSELF (Active Hero), do NOT deselect.
|
||||
// It's annoying to lose the card.
|
||||
const isHeroPhase = this.turnManager.currentPhase === 'hero';
|
||||
let isActiveTurnHero = false;
|
||||
if (isHeroPhase && this.heroTurnOrder && this.currentTurnIndex !== undefined) {
|
||||
const activeHero = this.heroTurnOrder[this.currentTurnIndex];
|
||||
if (activeHero && activeHero.id === clickedEntity.id) {
|
||||
isActiveTurnHero = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (isActiveTurnHero) {
|
||||
// Do nothing (keep selected)
|
||||
// Maybe blink the card or something?
|
||||
} else {
|
||||
this.deselectEntity();
|
||||
}
|
||||
} else if (this.selectedMonster === clickedMonster && clickedMonster) {
|
||||
// Clicking on already selected monster - deselect it
|
||||
const monsterId = this.selectedMonster.id;
|
||||
@@ -503,6 +558,9 @@ export class GameEngine {
|
||||
}
|
||||
}
|
||||
|
||||
// Store active visibility sets for Turn Logic
|
||||
this.currentVisibleTileIds = visibleTileIds;
|
||||
|
||||
window.RENDERER.updateFogOfWar(Array.from(visibleTileIds));
|
||||
}
|
||||
|
||||
@@ -720,7 +778,32 @@ export class GameEngine {
|
||||
if (entity.currentMoves < 0) entity.currentMoves = 0;
|
||||
}
|
||||
|
||||
this.deselectEntity();
|
||||
// AUTO-DESELECT LOGIC
|
||||
// In Hero Phase, we want to KEEP the active hero selected to avoid re-selecting.
|
||||
const isHeroPhase = this.turnManager.currentPhase === 'hero';
|
||||
// Check if entity is the currently active turn hero
|
||||
let isActiveTurnHero = false;
|
||||
if (isHeroPhase && this.heroTurnOrder && this.currentTurnIndex !== undefined) {
|
||||
const activeHero = this.heroTurnOrder[this.currentTurnIndex];
|
||||
if (activeHero && activeHero.id === entity.id) {
|
||||
isActiveTurnHero = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (isActiveTurnHero) {
|
||||
// Do NOT deselect. Just clear path.
|
||||
this.plannedPath = [];
|
||||
if (this.onPathChange) this.onPathChange([]);
|
||||
|
||||
// Also force update UI/Card (stats changed)
|
||||
if (this.onEntitySelect) {
|
||||
// Re-trigger selection to ensure UI is fresh?
|
||||
// UIManager listens to onEntityMove to update stats, so that should be covered.
|
||||
// But purely being consistent:
|
||||
}
|
||||
} else {
|
||||
this.deselectEntity();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -214,11 +214,22 @@ export class MonsterAI {
|
||||
|
||||
performAttack(monster, hero) {
|
||||
// SEQUENCE:
|
||||
// 1. Show green ring on monster
|
||||
// 2. Monster attack animation (we'll simulate with delay)
|
||||
// 3. Show red ring + shake on hero
|
||||
// 4. Remove both rings
|
||||
// 5. Show combat result
|
||||
// 0. Show TARGET (Blue Ring) on Hero
|
||||
if (this.game.onRangedTarget) {
|
||||
// Re-using onRangedTarget? Or directly calling renderer?
|
||||
// Better to use a specific callback or direct call if available, or just add a new callback.
|
||||
// But let's check if we can access renderer directly or use a new callback.
|
||||
// The user prompt specifically asked for this feature.
|
||||
// I'll assume we can use game.onEntityTarget if defined, or direct renderer call if needed,
|
||||
// but standard pattern here is callbacks.
|
||||
// Let's add onEntityTarget to GameEngine callbacks if not present, but for now I will try to use global RENDERER if possible
|
||||
// OR simply define a new callback `this.game.onEntityTarget(hero.id, true)`.
|
||||
}
|
||||
|
||||
// Direct renderer call is safest given current context if we don't want to modify GameEngine interface heavily right now.
|
||||
if (window.RENDERER && window.RENDERER.setEntityTarget) {
|
||||
window.RENDERER.setEntityTarget(hero.id, true);
|
||||
}
|
||||
|
||||
const result = CombatMechanics.resolveMeleeAttack(monster, hero, this.game);
|
||||
|
||||
@@ -229,9 +240,6 @@ export class MonsterAI {
|
||||
|
||||
// Step 2: Attack animation delay (500ms)
|
||||
setTimeout(() => {
|
||||
// Step 3: Trigger hit visual on defender (if hit succeeded)
|
||||
// Step 3: Trigger hit visual on defender REMOVED (Handled by onCombatResult)
|
||||
|
||||
|
||||
// Step 4: Remove green ring after red ring appears (1200ms for red ring duration)
|
||||
setTimeout(() => {
|
||||
@@ -239,6 +247,11 @@ export class MonsterAI {
|
||||
this.game.onEntityActive(monster.id, false);
|
||||
}
|
||||
|
||||
// Remove Target Ring
|
||||
if (window.RENDERER && window.RENDERER.setEntityTarget) {
|
||||
window.RENDERER.setEntityTarget(hero.id, false);
|
||||
}
|
||||
|
||||
// Step 5: Show combat result after both rings are gone
|
||||
setTimeout(() => {
|
||||
if (this.game.onCombatResult) {
|
||||
@@ -246,7 +259,7 @@ export class MonsterAI {
|
||||
}
|
||||
}, 200); // Small delay after rings disappear
|
||||
}, 1200); // Wait for red ring to disappear
|
||||
}, 500); // Attack animation delay
|
||||
}, 800); // Attack animation delay + focus time
|
||||
}
|
||||
|
||||
getAdjacentHero(entity) {
|
||||
|
||||
Reference in New Issue
Block a user