diff --git a/index.html b/index.html
index f83331c..9973398 100644
--- a/index.html
+++ b/index.html
@@ -140,7 +140,7 @@
@@ -172,7 +172,7 @@
-
+
Hearts
diff --git a/js/game.js b/js/game.js
index c747d9c..ced121f 100644
--- a/js/game.js
+++ b/js/game.js
@@ -412,7 +412,6 @@ export class Level extends LevelInterface {
// global clock which doesn't get reset between levels (!).
this.step_parity = 5;
- this.hint_shown = null;
// TODO in lynx/steam, this carries over between levels; in tile world, you can set it manually
this.force_floor_direction = 'north';
// PRNG is initialized to zero
@@ -668,9 +667,6 @@ export class Level extends LevelInterface {
if (tile.type.on_ready) {
tile.type.on_ready(tile, this);
}
- if (cell === this.player.cell && tile.type.is_hint) {
- this.hint_shown = tile.hint_text ?? this.stored_level.hint;
- }
}
}
// Erase undo, in case any on_ready added to it (we don't want to undo initialization!)
@@ -760,7 +756,7 @@ export class Level extends LevelInterface {
for (let key of [
'_rng1', '_rng2', '_blob_modifier', 'force_floor_direction',
'tic_counter', 'time_remaining', 'timer_paused',
- 'chips_remaining', 'bonus_points', 'hint_shown', 'state',
+ 'chips_remaining', 'bonus_points', 'state',
'remaining_players', 'player',
]) {
this.pending_undo.level_props[key] = this[key];
@@ -1547,17 +1543,6 @@ export class Level extends LevelInterface {
}
}
- // Check for a couple effects that always apply immediately
- if (actor === this.player) {
- this.hint_shown = null;
- }
- for (let tile of goal_cell) {
- // FIXME this could go in on_approach now
- if (tile && actor === this.player && tile.type.is_hint) {
- this.hint_shown = tile.hint_text ?? this.stored_level.hint;
- }
- }
-
// Announce we're approaching. Slide mode is set here, since it's about the tile we're
// moving towards and needs to last through our next decision
this.make_slide(actor, null);
@@ -1760,7 +1745,9 @@ export class Level extends LevelInterface {
this.set_actor_direction(actor, direction);
this.spawn_animation(actor.cell, 'teleport_flash');
- this.spawn_animation(dest.cell, 'teleport_flash');
+ if (dest.cell !== actor.cell) {
+ this.spawn_animation(dest.cell, 'teleport_flash');
+ }
// Now physically move the actor, but their movement waits until next decision phase
this.remove_tile(actor);
diff --git a/js/main.js b/js/main.js
index 760a3d5..9c0d5af 100644
--- a/js/main.js
+++ b/js/main.js
@@ -296,7 +296,7 @@ class Player extends PrimaryView {
this.root.style.setProperty('--tile-height', `${this.conductor.tileset.size_y}px`);
this.level_el = this.root.querySelector('.level');
this.overlay_message_el = this.root.querySelector('.overlay-message');
- this.message_el = this.root.querySelector('.message');
+ this.hint_el = this.root.querySelector('.player-hint');
this.chips_el = this.root.querySelector('.chips output');
this.time_el = this.root.querySelector('.time output');
this.bonus_el = this.root.querySelector('.bonus output');
@@ -1061,6 +1061,7 @@ class Player extends PrimaryView {
this.last_advance = 0;
this.current_keyring = {};
this.current_toolbelt = [];
+ this.previous_hint_tile = null;
this.chips_el.classList.remove('--done');
this.time_el.classList.remove('--frozen');
@@ -1350,7 +1351,38 @@ class Player extends PrimaryView {
if (this.level.bonus_points > 0) {
this.root.classList.add('--bonus-visible');
}
- this.message_el.textContent = this.level.hint_shown ?? "";
+
+ // Check for the player standing on a hint tile; this is slightly invasive but lets us
+ // notice exactly when it changes (and anyway it's a UI thing, not gameplay)
+ let terrain = this.level.player.cell.get_terrain();
+ let hint_tile = null;
+ if (terrain.type.is_hint) {
+ hint_tile = terrain;
+ }
+ if (hint_tile !== this.previous_hint_tile) {
+ this.previous_hint_tile = hint_tile;
+ this.hint_el.textContent = '';
+ if (hint_tile) {
+ // Parse out %X sequences and replace them with elements
+ let hint_text = hint_tile.hint_text ?? this.level.stored_level.hint;
+ for (let [i, chunk] of hint_text.split(/%(\w)/).entries()) {
+ if (i % 2 === 0) {
+ this.hint_el.append(chunk);
+ }
+ else {
+ // TODO better place to get these?
+ // TODO 1 through 7 are player 2's inputs in split-screen mode
+ let key = {
+ // up, down, left, right
+ U: 'W', D: 'S', L: 'A', R: 'D',
+ // drop, cycle, swap
+ P: 'Q', C: 'E', S: 'C',
+ }[chunk] ?? "?";
+ this.hint_el.append(mk('kbd', key));
+ }
+ }
+ }
+ }
this.renderer.set_active_player(this.level.remaining_players > 1 ? this.level.player : null);
diff --git a/style.css b/style.css
index 41c97a9..9719da4 100644
--- a/style.css
+++ b/style.css
@@ -125,6 +125,14 @@ pre {
code {
color: #c0c0e0;
}
+kbd {
+ padding: 0 0.25em;
+ border: 1px solid currentColor;
+ border-radius: 0.25em;
+ box-shadow: 0 2px 0 currentColor;
+ text-align: center;
+ text-transform: uppercase;
+}
a {
color: #c0c0c0;
@@ -931,7 +939,7 @@ ol.packtest-summary > li {
"level chips" min-content
"level time" min-content
"level bonus" min-content
- "level message" 1fr
+ "level hint" 1fr
"level inventory" min-content
/* Need explicit min-content to force the hint to wrap */
/ min-content min-content
@@ -1093,8 +1101,8 @@ dl.score-chart .-sum {
display: flex;
}
-.message {
- grid-area: message;
+#player-game-area > .player-hint {
+ grid-area: hint;
align-self: stretch;
font-size: calc(var(--tile-height) * var(--scale) / 3);
@@ -1105,10 +1113,10 @@ dl.score-chart .-sum {
background: #080808;
border: 1px inset #202020;
- /* FIXME find a way to enforce that the message never makes the grid get bigger */
+ /* FIXME find a way to enforce that the hint never makes the grid get bigger */
overflow: auto;
}
-.message:empty {
+#player-game-area > .player-hint:empty {
display: none;
}
@@ -1186,14 +1194,8 @@ dl.score-chart .-sum {
left: 0;
right: 0;
top: -2em;
- width: 1em;
margin: auto;
color: #404040;
- border: 1px solid #202020;
- border-radius: 0.25em;
- box-shadow: 0 2px 0 #202020;
- text-align: center;
- text-transform: uppercase;
}
#player button:disabled .keyhint {
display: none;
@@ -1422,7 +1424,7 @@ body.--debug #player-debug {
/* stick me in the center right */
place-self: center end;
}
- #player .message {
+ #player > .player-hint {
/* Overlay hints on the inventory area */
grid-row: chips / bonus;
grid-column: level;