home · contact · privacy
Make CHATFACE trigger screen refresh.
[plomrogue2] / rogue_chat.html
index c871b6a8f48eba02a27f7283c1922733211468b7..5e663981d13ba7292b0f8b98ca006fde9b8b4a7c 100644 (file)
@@ -57,7 +57,6 @@ keyboard input/control: <span id="keyboard_control"></span>
       <button id="consume"></button>
       <button id="switch_to_command_thing"></button>
       <button id="teleport"></button>
-      <button id="install"></button>
       <button id="wear"></button>
       <button id="spin"></button>
     </td>
@@ -67,6 +66,7 @@ keyboard input/control: <span id="keyboard_control"></span>
     <td>
       <button id="switch_to_write"></button>
       <button id="flatten"></button>
+      <button id="install"></button>
       <button id="switch_to_annotate"></button>
       <button id="switch_to_portal"></button>
       <button id="switch_to_name_thing"></button>
@@ -454,7 +454,6 @@ let server = {
         this.url = url;
         this.websocket = new WebSocket(this.url);
         this.websocket.onopen = function(event) {
-            server.connected = true;
             game.thing_types = {};
             game.terrains = {};
             server.send(['TASKS']);
@@ -464,7 +463,6 @@ let server = {
             tui.switch_mode('login');
         };
         this.websocket.onclose = function(event) {
-            server.connected = false;
             tui.switch_mode('waiting_for_server');
             tui.log_msg("@ server disconnected :(");
         };
@@ -515,7 +513,7 @@ let server = {
             game.thing_types[tokens[1]] = tokens[2]
         } else if (tokens[0] === 'THING_CARRYING') {
             let t = game.get_thing(tokens[1], false);
-            t.carrying = t = game.get_thing(tokens[2], false);
+            t.carrying = game.get_thing(tokens[2], false);
         } else if (tokens[0] === 'THING_INSTALLED') {
             let t = game.get_thing(tokens[1], false);
             t.installed = true;
@@ -532,13 +530,18 @@ let server = {
             game.map_control = tokens[1]
         } else if (tokens[0] === 'GAME_STATE_COMPLETE') {
             game.turn_complete = true;
+            game.player = game.things[game.player_id];
+            explorer.info_cached = false;
             if (tui.mode.name == 'post_login_wait') {
                 tui.switch_mode('play');
+            } else {
+                tui.full_refresh();
             }
-            explorer.info_cached = false;
-            tui.full_refresh();
         } else if (tokens[0] === 'CHAT') {
              tui.log_msg('# ' + tokens[1], 1);
+        } else if (tokens[0] === 'CHATFACE') {
+            tui.draw_face = tokens[1];
+            tui.full_refresh();
         } else if (tokens[0] === 'REPLY') {
              tui.log_msg('#MUSICPLAYER: ' + tokens[1], 1);
         } else if (tokens[0] === 'PLAYER_ID') {
@@ -701,11 +704,12 @@ let tui = {
   offset: [0,0],
   map_lines: [],
   selectables: [],
+  draw_face: false,
   init: function() {
       this.mode_play.available_modes = ["chat", "study", "edit", "admin_enter",
                                         "command_thing", "take_thing", "drop_thing"]
       this.mode_play.available_actions = ["move", "teleport", "door", "consume",
-                                          "install", "wear", "spin"];
+                                          "wear", "spin"];
       this.mode_study.available_modes = ["chat", "play", "admin_enter", "edit"]
       this.mode_study.available_actions = ["toggle_map_mode", "move_explorer"];
       this.mode_admin.available_modes = ["admin_thing_protect", "control_pw_type",
@@ -717,7 +721,8 @@ let tui = {
       this.mode_edit.available_modes = ["write", "annotate", "portal", "name_thing",
                                         "password", "chat", "study", "play",
                                         "admin_enter", "enter_face"]
-      this.mode_edit.available_actions = ["move", "flatten", "toggle_map_mode"]
+      this.mode_edit.available_actions = ["move", "flatten", "install",
+                                          "toggle_map_mode"]
       this.inputEl = document.getElementById("input");
       this.inputEl.focus();
       this.switch_mode('waiting_for_server');
@@ -763,22 +768,26 @@ let tui = {
       return game.tasks.includes(this.action_tasks[action]);
   },
   switch_mode: function(mode_name) {
+
+    function fail(msg, return_mode) {
+        tui.log_msg('? ' + msg);
+        terminal.blink_screen();
+        this.switch_mode(return_mode);
+    }
+
     if (this.mode && this.mode.name == 'control_tile_draw') {
         tui.log_msg('@ finished tile protection drawing.')
     }
     this.tile_draw = false;
-    const player = game.things[game.player_id];
-    if (mode_name == 'command_thing' && (!player.carrying || !player.carrying.commandable)) {
-        this.log_msg('? not carrying anything commandable');
-        terminal.blink_screen();
-        this.switch_mode('play');
-        return;
+      if (mode_name == 'command_thing' && (!game.player.carrying
+                                           || !game.player.carrying.commandable)) {
+        return fail('not carrying anything commandable', 'play');
     };
-    if (mode_name == 'drop_thing' && (!player.carrying)) {
-        this.log_msg('? not carrying anything droppable');
-        terminal.blink_screen();
-        this.switch_mode('play');
-        return;
+    if (mode_name == 'take_thing' && game.player.carrying) {
+        return fail('already carrying something', 'play');
+    };
+    if (mode_name == 'drop_thing' && !game.player.carrying) {
+        return fail('not carrying anything droppable', 'play');
     }
     if (mode_name == 'admin_enter' && this.is_admin) {
         mode_name = 'admin';
@@ -789,16 +798,14 @@ let tui = {
                 continue;
             }
             let t = game.things[t_id];
-            if (player.position[0] == t.position[0]
-                && player.position[1] == t.position[1]) {
+            if (game.player.position[0] == t.position[0]
+                && game.player.position[1] == t.position[1]) {
                 thing_id = t_id;
                 break;
             }
         }
         if (!thing_id) {
-            terminal.blink_screen();
-            this.log_msg('? not standing over thing');
-            return;
+            return fail('not standing over thing', 'fail');
         } else {
             this.selected_thing_id = thing_id;
         }
@@ -813,7 +820,7 @@ let tui = {
         this.inputEl.focus();
     }
     if (game.player_id in game.things && (this.mode.shows_info || this.mode.name == 'control_tile_draw')) {
-        explorer.position = game.things[game.player_id].position;
+        explorer.position = game.player.position;
     }
     this.inputEl.value = "";
     this.restore_input_values();
@@ -850,9 +857,8 @@ let tui = {
         this.show_help = true;
     } else if (this.mode.name == 'take_thing') {
         this.log_msg("Portable things in reach for pick-up:");
-        const player = game.things[game.player_id];
-        const y = player.position[0]
-        const x = player.position[1]
+        const y = game.player.position[0]
+        const x = game.player.position[1]
         let select_range = [y.toString() + ':' + x.toString(),
                             (y + 0).toString() + ':' + (x - 1).toString(),
                             (y + 0).toString() + ':' + (x + 1).toString(),
@@ -1044,8 +1050,9 @@ let tui = {
         };
         map_lines_split.push(line);
         if (this.map_mode == 'terrain + annotations') {
-            for (const coordinate of explorer.info_hints) {
-                map_lines_split[coordinate[0]][coordinate[1]] = 'A ';
+            for (const [coordinate, _] of Object.entries(explorer.annotations)) {
+                const yx = coordinate.split(',')
+                map_lines_split[yx[0]][yx[1]] = 'A ';
             }
         } else if (this.map_mode == 'terrain + things') {
             for (const p in game.portals) {
@@ -1082,11 +1089,10 @@ let tui = {
                 }
             };
         }
-        let player = game.things[game.player_id];
         if (tui.mode.shows_info || tui.mode.name == 'control_tile_draw') {
             map_lines_split[explorer.position[0]][explorer.position[1]] = '??';
         } else if (tui.map_mode != 'terrain + things') {
-            map_lines_split[player.position[0]][player.position[1]] = '??';
+            map_lines_split[game.player.position[0]][game.player.position[1]] = '??';
         }
         this.map_lines = []
         if (game.map_geometry == 'Square') {
@@ -1105,7 +1111,7 @@ let tui = {
             };
         }
         let window_center = [terminal.rows / 2, this.window_width / 2];
-        let center_position = [player.position[0], player.position[1]];
+        let center_position = [game.player.position[0], game.player.position[1]];
         if (tui.mode.shows_info || tui.mode.name == 'control_tile_draw') {
             center_position = [explorer.position[0], explorer.position[1]];
         }
@@ -1125,6 +1131,27 @@ let tui = {
         terminal.write(term_y, term_x, to_draw);
     }
   },
+  draw_face_popup: function() {
+      const t = game.things[this.draw_face];
+      if (!t) {
+          this.draw_face = false;
+          return;
+      }
+      function draw_body_part(body_part, end_y) {
+          const start_x = tui.window_width - 10;
+          terminal.write(end_y - 4, start_x, '+--------+');
+          terminal.write(end_y - 3, start_x, '|        |');
+          terminal.write(end_y - 2, start_x, '| ' + body_part.slice(0, 6) + ' |');
+          terminal.write(end_y - 1, start_x, '| ' + body_part.slice(6, 12) + ' |');
+          terminal.write(end_y, start_x, '| ' + body_part.slice(12, 18) + ' |');
+      }
+      if (t.face) {
+          draw_body_part(t.face, terminal.rows - 1);
+      }
+      if (t.hat) {
+          draw_body_part(t.hat, terminal.rows - 4);
+      }
+  },
   draw_mode_line: function() {
       let help = 'hit [' + this.keys.help + '] for help';
       if (this.mode.has_input_prompt) {
@@ -1213,7 +1240,8 @@ let tui = {
       content += this.mode.list_available_modes();
       let start_x = 0;
       if (!this.mode.has_input_prompt) {
-          start_x = this.window_width
+          start_x = this.window_width;
+          this.draw_links = false;
       }
       terminal.drawBox(0, start_x, terminal.rows, this.window_width);
       let [lines, _] = this.msg_into_lines_of_width(content, this.window_width);
@@ -1240,6 +1268,7 @@ let tui = {
       }
   },
   full_refresh: function() {
+    this.draw_links = true;
     this.links = {};
     terminal.drawBox(0, 0, terminal.rows, terminal.cols);
     this.recalc_input_lines();
@@ -1260,6 +1289,12 @@ let tui = {
     if (this.show_help) {
         this.draw_help();
     }
+    if (this.draw_face && ['chat', 'play'].includes(this.mode.name)) {
+        this.draw_face_popup();
+    }
+    if (!this.draw_links) {
+        this.links = {};
+    }
     terminal.refresh();
   }
 }
@@ -1327,9 +1362,8 @@ let game = {
         return target;
     },
     teleport: function() {
-        let player = this.get_thing(game.player_id);
-        if (player.position in this.portals) {
-            server.reconnect_to(this.portals[player.position]);
+        if (game.player.position in this.portals) {
+            server.reconnect_to(this.portals[game.player.position]);
         } else {
             terminal.blink_screen();
             tui.log_msg('? not standing on portal')
@@ -1469,14 +1503,16 @@ document.onclick = function() {
 };
 tui.inputEl.addEventListener('keydown', (event) => {
     tui.show_help = false;
+    tui.draw_face = false;
     if (event.key == 'Enter') {
         event.preventDefault();
     }
-    if (tui.mode.has_input_prompt && event.key == 'Enter'
-        && tui.inputEl.value.length == 0
-        && ['chat', 'command_thing', 'take_thing', 'drop_thing',
-            'admin_enter'].includes(tui.mode.name)) {
-        if (tui.mode.name != 'chat') {
+    if ((!tui.mode.is_intro && event.key == 'Escape')
+        || (tui.mode.has_input_prompt && event.key == 'Enter'
+            && tui.inputEl.value.length == 0
+            && ['chat', 'command_thing', 'take_thing', 'drop_thing',
+                'admin_enter'].includes(tui.mode.name))) {
+        if (!['chat', 'play', 'study', 'edit'].includes(tui.mode.name)) {
             tui.log_msg('@ aborted');
         }
         tui.switch_mode('play');
@@ -1588,8 +1624,6 @@ tui.inputEl.addEventListener('keydown', (event) => {
               server.send(["TASK:INTOXICATE"]);
           } else if (event.key === tui.keys.door && tui.task_action_on('door')) {
               server.send(["TASK:DOOR"]);
-          } else if (event.key === tui.keys.install && tui.task_action_on('install')) {
-              server.send(["TASK:INSTALL"]);
           } else if (event.key === tui.keys.wear && tui.task_action_on('wear')) {
               server.send(["TASK:WEAR"]);
           } else if (event.key === tui.keys.spin && tui.task_action_on('spin')) {
@@ -1628,6 +1662,8 @@ tui.inputEl.addEventListener('keydown', (event) => {
             server.send(['TASK:MOVE', tui.movement_keys[event.key]]);
         } else if (event.key === tui.keys.flatten && tui.task_action_on('flatten')) {
             server.send(["TASK:FLATTEN_SURROUNDINGS", tui.password]);
+          } else if (event.key === tui.keys.install && tui.task_action_on('install')) {
+              server.send(["TASK:INSTALL", tui.password]);
         } else if (event.key == tui.keys.toggle_map_mode) {
             tui.toggle_map_mode();
         }
@@ -1659,13 +1695,13 @@ for (let key_selector of key_selectors) {
     }, false);
 }
 window.setInterval(function() {
-    if (server.connected) {
+    if (server.websocket.readyState == 1) {
         server.send(['PING']);
-    } else {
+    } else if (server.websocket.readyState != 0) {
         server.reconnect_to(server.url);
         tui.log_msg('@ attempting reconnect …')
     }
-}, 5000);
+}, 1000);
 window.setInterval(function() {
     let val = "?";
     let span_decoration = "none";