home · contact · privacy
Add wearable hats.
authorChristian Heller <c.heller@plomlompom.de>
Mon, 7 Dec 2020 05:09:04 +0000 (06:09 +0100)
committerChristian Heller <c.heller@plomlompom.de>
Mon, 7 Dec 2020 05:09:04 +0000 (06:09 +0100)
config.json
plomrogue/commands.py
plomrogue/game.py
plomrogue/tasks.py
plomrogue/things.py
rogue_chat.html
rogue_chat.py
rogue_chat_curses.py

index 7b26b539bfced13b535065a4b42751fee9dc75f1..8fce4dcc8a277357a840f67e54f1101fc1bd595b 100644 (file)
@@ -19,6 +19,8 @@
     "drop_thing": "u",
     "teleport": "p",
     "door": "D",
+    "install": "I",
+    "wear": "W",
     "consume": "C",
     "help": "h",
     "toggle_map_mode": "L",
index 0ccbdc1cb50ef3b646474e1d165fe0a4444ea701..0228c69de5cede80930cb3104d8e14bf9df53073 100644 (file)
@@ -327,3 +327,7 @@ cmd_PLAYER_FACE.argtypes = 'string'
 def cmd_GOD_PLAYER_FACE(game, name, face):
     game.faces[name] = face
 cmd_GOD_PLAYER_FACE.argtypes = 'string string'
+
+def cmd_GOD_PLAYER_HAT(game, name, hat):
+    game.hats[name] = hat
+cmd_GOD_PLAYER_HAT.argtypes = 'string string'
index 017580f24e4cb28ef98062f4d11026b2a02894ca..0fc486796232a1e5c95f102847e5ea59147eb2ba 100755 (executable)
@@ -122,6 +122,7 @@ class Game(GameBase):
         self.thing_types = {}
         self.sessions = {}
         self.faces = {}
+        self.hats = {}
         self.maps = {}
         self.map_controls = {}
         self.map_control_passwords = {}
@@ -246,6 +247,9 @@ class Game(GameBase):
                              c_id)
                 if hasattr(t, 'name'):
                     self.io.send('THING_NAME %s %s' % (t.id_, quote(t.name)), c_id)
+                    if t.type_ == 'Player' and t.name in self.hats:
+                        hat = self.hats[t.name]
+                        self.io.send('THING_HAT %s %s' % (t.id_, quote(hat)), c_id)
                 face = self.get_face(t)
                 if face:
                     self.io.send('THING_FACE %s %s' % (t.id_, quote(face)), c_id)
@@ -386,6 +390,9 @@ class Game(GameBase):
             for name in self.faces:
                 write(f, 'GOD_PLAYER_FACE %s %s' % (quote(name),
                                                     quote(self.faces[name])))
+            for name in self.hats:
+                write(f, 'GOD_PLAYER_HAT %s %s' % (quote(name),
+                                                   quote(self.hats[name])))
             for t in [t for t in self.things if not t.type_ == 'Player']:
                 write(f, 'THING %s %s %s %s' % (t.position[0],
                                                 t.position[1], t.type_, t.id_))
index 9165cd44b63d0adece3c1da95366cdbd7b5fae4a..9fccbc33450f2c50fe5caf6269d0ba171bc7e644 100644 (file)
@@ -202,3 +202,29 @@ class Task_INSTALL(Task):
         else:
             self._get_uninstallables()[0].uninstall()
             self.thing.send_msg('CHAT "You uninstall the thing here."')
+
+
+
+class Task_WEAR(Task):
+
+    def check(self):
+        if self.thing.name in self.thing.game.hats:
+            return
+        if not self.thing.carrying:
+            raise PlayError('carrying nothing to wear')
+        if self.thing.name in self.thing.game.hats:
+            raise PlayError('already wearing a hat')
+        if self.thing.carrying.type_ != 'Hat':
+            raise PlayError('can only wear a hat')
+
+    def do(self):
+        if self.thing.name in self.thing.game.hats:
+            t = self.thing.game.thing_types['Hat'](self.thing.game,
+                                                   position=self.thing.position)
+            self.thing.game.things += [t]
+            t.design = self.thing.game.hats[self.thing.name]
+            del self.thing.game.hats[self.thing.name]
+        else:
+            self.thing.game.hats[self.thing.name] = self.thing.carrying.design
+            self.thing.game.things.remove(self.thing.carrying)
+            self.thing.carrying = None
index 31820541a7ad46a51a76b8a07bf2f412d3b39267..2c12cf283e41cc5b788d37c35d1fabe23225ba17 100644 (file)
@@ -163,6 +163,19 @@ class Thing_BottleSpawner(ThingSpawner):
 
 
 
+class Thing_Hat(Thing):
+    symbol_hint = 'H'
+    portable = True
+    design = ' X  X ==='
+
+
+
+class Thing_HatSpawner(ThingSpawner):
+    child_type = 'Hat'
+
+
+
+
 import datetime
 class Thing_MusicPlayer(Thing):
     symbol_hint = 'R'
index dfeeecdba69e2570d88c4ea1f08fafa512b2c14e..1b5f39d8f732f631f477b5dec8378349a21e8b4b 100644 (file)
@@ -58,6 +58,7 @@ keyboard input/control: <span id="keyboard_control"></span>
       <button id="switch_to_command_thing"></button>
       <button id="teleport"></button>
       <button id="install"></button>
+      <button id="wear"></button>
     </td>
   </tr>
   <tr>
@@ -102,6 +103,7 @@ keyboard input/control: <span id="keyboard_control"></span>
 <li>open/close: <input id="key_door" type="text" value="D" />
 <li>consume: <input id="key_consume" type="text" value="C" />
 <li>install: <input id="key_install" type="text" value="I" />
+<li>(un-)wear: <input id="key_wear" type="text" value="W" />
 <li><input id="key_switch_to_enter_face" type="text" value="f" />
 <li><input id="key_switch_to_take_thing" type="text" value="z" />
 <li><input id="key_switch_to_chat" type="text" value="t" />
@@ -246,6 +248,7 @@ let key_descriptions = {
     'door': 'open/close',
     'consume': 'consume',
     'install': '(un-)install',
+    'wear': '(un-)wear',
     'toggle_map_mode': 'toggle map view',
     'toggle_tile_draw': 'toggle protection character drawing',
     'hex_move_upleft': 'up-left',
@@ -488,6 +491,9 @@ let server = {
         } else if (tokens[0] === 'THING_FACE') {
             let t = game.get_thing(tokens[1], false);
             t.face = tokens[2];
+        } else if (tokens[0] === 'THING_HAT') {
+            let t = game.get_thing(tokens[1], false);
+            t.hat = tokens[2];
         } else if (tokens[0] === 'THING_CHAR') {
             let t = game.get_thing(tokens[1], false);
             t.thing_char = tokens[2];
@@ -677,6 +683,7 @@ let tui = {
       'move': 'MOVE',
       'door': 'DOOR',
       'install': 'INSTALL',
+      'wear': 'WEAR',
       'command': 'COMMAND',
       'consume': 'INTOXICATE',
   },
@@ -686,8 +693,8 @@ let tui = {
   init: function() {
       this.mode_play.available_modes = ["chat", "study", "edit", "admin_enter",
                                         "command_thing", "take_thing"]
-      this.mode_play.available_actions = ["move", "drop_thing",
-                                          "teleport", "door", "consume", "install"];
+      this.mode_play.available_actions = ["move", "drop_thing", "teleport",
+                                          "door", "consume", "install", "wear"];
       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",
@@ -1337,6 +1344,11 @@ let explorer = {
                          protection = 'none';
                      }
                      info_to_cache += " / protection: " + protection + "\n";
+                     if (t.hat) {
+                         info_to_cache += t.hat.slice(0, 3) + '\n';
+                         info_to_cache += t.hat.slice(3, 6) + '\n';
+                         info_to_cache += t.hat.slice(6, 9) + '\n';
+                     }
                      if (t.face) {
                          info_to_cache += t.face.slice(0, 3) + '\n';
                          info_to_cache += t.face.slice(3, 6) + '\n';
@@ -1543,6 +1555,8 @@ tui.inputEl.addEventListener('keydown', (event) => {
               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.install && tui.task_action_on('wear')) {
+              server.send(["TASK:WEAR"]);
           } else if (event.key in tui.movement_keys && tui.task_action_on('move')) {
               server.send(['TASK:MOVE', tui.movement_keys[event.key]]);
           } else if (event.key === tui.keys.teleport) {
@@ -1665,6 +1679,9 @@ document.getElementById("consume").onclick = function() {
 document.getElementById("install").onclick = function() {
     server.send(['TASK:INSTALL']);
 };
+document.getElementById("wear").onclick = function() {
+    server.send(['TASK:WEAR']);
+};
 document.getElementById("teleport").onclick = function() {
     game.teleport();
 };
index 14e23dc91fb13520b3454a82476faefcdca582c0..7882013af3f539838648e373f105ce66178e3bc8 100755 (executable)
@@ -13,15 +13,16 @@ from plomrogue.commands import (cmd_ALL, cmd_LOGIN, cmd_NICK, cmd_PING, cmd_THIN
                                 cmd_THING_MUSICPLAYER_SETTINGS,
                                 cmd_THING_MUSICPLAYER_PLAYLIST_ITEM,
                                 cmd_THING_BOTTLE_EMPTY, cmd_PLAYER_FACE,
-                                cmd_GOD_PLAYER_FACE)
+                                cmd_GOD_PLAYER_FACE, cmd_GOD_PLAYER_HAT)
 from plomrogue.tasks import (Task_WAIT, Task_MOVE, Task_WRITE, Task_PICK_UP,
                              Task_DROP, Task_FLATTEN_SURROUNDINGS, Task_DOOR,
-                             Task_INTOXICATE, Task_COMMAND, Task_INSTALL)
+                             Task_INTOXICATE, Task_COMMAND, Task_INSTALL,
+                             Task_WEAR)
 from plomrogue.things import (Thing_Player, Thing_Item, Thing_ItemSpawner,
                               Thing_SpawnPoint, Thing_SpawnPointSpawner,
                               Thing_Door, Thing_DoorSpawner, Thing_Bottle,
                               Thing_BottleSpawner, Thing_BottleDeposit,
-                              Thing_MusicPlayer)
+                              Thing_MusicPlayer, Thing_Hat, Thing_HatSpawner)
 
 from plomrogue.config import config
 game = Game(config['savefile'])
@@ -59,6 +60,7 @@ game.register_command(cmd_THING_MUSICPLAYER_PLAYLIST_ITEM)
 game.register_command(cmd_THING_BOTTLE_EMPTY)
 game.register_command(cmd_PLAYER_FACE)
 game.register_command(cmd_GOD_PLAYER_FACE)
+game.register_command(cmd_GOD_PLAYER_HAT)
 game.register_task(Task_WAIT)
 game.register_task(Task_MOVE)
 game.register_task(Task_WRITE)
@@ -69,6 +71,7 @@ game.register_task(Task_DOOR)
 game.register_task(Task_INTOXICATE)
 game.register_task(Task_COMMAND)
 game.register_task(Task_INSTALL)
+game.register_task(Task_WEAR)
 game.register_thing_type(Thing_Player)
 game.register_thing_type(Thing_Item)
 game.register_thing_type(Thing_ItemSpawner)
@@ -80,6 +83,8 @@ game.register_thing_type(Thing_Bottle)
 game.register_thing_type(Thing_BottleSpawner)
 game.register_thing_type(Thing_BottleDeposit)
 game.register_thing_type(Thing_MusicPlayer)
+game.register_thing_type(Thing_Hat)
+game.register_thing_type(Thing_HatSpawner)
 game.read_savefile()
 game.io.start_loop()
 for port in config['servers']:
index 89c841140edc871c4108d91c6bb3b5f389599e0a..ff00b503a3eb51de174715329cce08bfad59f323 100755 (executable)
@@ -220,6 +220,11 @@ def cmd_THING_FACE(game, thing_id, face):
     t.face = face
 cmd_THING_FACE.argtypes = 'int:pos string'
 
+def cmd_THING_HAT(game, thing_id, hat):
+    t = game.get_thing(thing_id)
+    t.hat = hat
+cmd_THING_HAT.argtypes = 'int:pos string'
+
 def cmd_THING_CHAR(game, thing_id, c):
     t = game.get_thing(thing_id)
     t.thing_char = c
@@ -343,6 +348,7 @@ class Game(GameBase):
         self.register_command(cmd_THING_NAME)
         self.register_command(cmd_THING_CHAR)
         self.register_command(cmd_THING_FACE)
+        self.register_command(cmd_THING_HAT)
         self.register_command(cmd_THING_CARRYING)
         self.register_command(cmd_THING_INSTALLED)
         self.register_command(cmd_TERRAIN)
@@ -449,7 +455,7 @@ class TUI:
                                           "command_thing", "take_thing"]
         self.mode_play.available_actions = ["move", "drop_thing",
                                             "teleport", "door", "consume",
-                                            "install"]
+                                            "install", "wear"]
         self.mode_study.available_modes = ["chat", "play", "admin_enter", "edit"]
         self.mode_study.available_actions = ["toggle_map_mode", "move_explorer"]
         self.mode_admin.available_modes = ["admin_thing_protect", "control_pw_type",
@@ -498,6 +504,7 @@ class TUI:
             'consume': 'C',
             'door': 'D',
             'install': 'I',
+            'wear': 'W',
             'help': 'h',
             'toggle_map_mode': 'L',
             'toggle_tile_draw': 'm',
@@ -708,6 +715,10 @@ class TUI:
                     if protection == '.':
                         protection = 'none'
                     info_to_cache += ' / protection: %s\n' % protection
+                    if hasattr(t, 'hat'):
+                        info_to_cache += t.hat[0:3] + '\n'
+                        info_to_cache += t.hat[3:6] + '\n'
+                        info_to_cache += t.hat[6:9] + '\n'
                     if hasattr(t, 'face'):
                         info_to_cache += t.face[0:3] + '\n'
                         info_to_cache += t.face[3:6] + '\n'
@@ -975,6 +986,7 @@ class TUI:
             'toggle_map_mode': 'toggle map view',
             'toggle_tile_draw': 'toggle protection character drawing',
             'install': '(un-)install',
+            'wear': '(un-)wear',
             'door': 'open/close',
             'consume': 'consume',
         }
@@ -985,6 +997,7 @@ class TUI:
             'drop_thing': 'DROP',
             'door': 'DOOR',
             'install': 'INSTALL',
+            'wear': 'WEAR',
             'move': 'MOVE',
             'command': 'COMMAND',
             'consume': 'INTOXICATE',
@@ -1166,6 +1179,8 @@ class TUI:
                     self.send('TASK:INTOXICATE')
                 elif key == self.keys['install'] and task_action_on('install'):
                     self.send('TASK:INSTALL')
+                elif key == self.keys['wear'] and task_action_on('wear'):
+                    self.send('TASK:WEAR')
                 elif key == self.keys['teleport']:
                     player = self.game.get_thing(self.game.player_id)
                     if player.position in self.game.portals: