a277bbbb by Barry

Added some new things to the login to get character setup rolling

1 parent a757808c
...@@ -727,20 +727,6 @@ class CommandHandler(object): ...@@ -727,20 +727,6 @@ class CommandHandler(object):
727 if callable(command_method): 727 if callable(command_method):
728 params = params.lower().strip() 728 params = params.lower().strip()
729 return command_method(id, params, players, mud, tokens, cmd) 729 return command_method(id, params, players, mud, tokens, cmd)
730 # else:
731 # ldict = locals()
732
733 # with open('commands/{}.txt'.format(cmd), 'r', encoding='utf-8') as f:
734 # command_text = f.read()
735 # exec(command_text, globals(), ldict)
736 # del command_text
737 # if ldict['next_command'] is not None:
738 # locals()['tokens'] = []
739 # tokens = []
740 # with open('commands/{}.txt'.format(ldict['next_command']), 'r', encoding='utf-8') as f:
741 # exec(f.read())
742 # del ldict
743 #raise Exception("Missing command: {}".format(cmd))
744 except Exception as e: 730 except Exception as e:
745 print('Command handler exception:') 731 print('Command handler exception:')
746 if 'esp' not in sys.platform: 732 if 'esp' not in sys.platform:
......
...@@ -48,12 +48,15 @@ class MudServer(object): ...@@ -48,12 +48,15 @@ class MudServer(object):
48 # the last time we checked if the client was still connected 48 # the last time we checked if the client was still connected
49 lastcheck = 0 49 lastcheck = 0
50 50
51 color_enabled = True
52
51 def __init__(self, socket, address, buffer, lastcheck): 53 def __init__(self, socket, address, buffer, lastcheck):
52 self.socket = socket 54 self.socket = socket
53 self.address = address 55 self.address = address
54 self.buffer = buffer 56 self.buffer = buffer
55 self.lastcheck = lastcheck 57 self.lastcheck = lastcheck
56 58
59
57 # Used to store different types of occurences 60 # Used to store different types of occurences
58 _EVENT_NEW_PLAYER = 1 61 _EVENT_NEW_PLAYER = 1
59 _EVENT_PLAYER_LEFT = 2 62 _EVENT_PLAYER_LEFT = 2
...@@ -223,20 +226,29 @@ class MudServer(object): ...@@ -223,20 +226,29 @@ class MudServer(object):
223 """ 226 """
224 # we make sure to put a newline on the end so the client receives the 227 # we make sure to put a newline on the end so the client receives the
225 # message on its own line 228 # message on its own line
226 message = multiple_replace(message, get_color_list()) 229
230 try:
231 color_enabled = self._clients[to].color_enabled
232 except KeyError:
233 color_enabled = False
234
235 message = multiple_replace(message, get_color_list(), color_enabled)
227 if nowrap: 236 if nowrap:
228 lines = [message] 237 lines = [message]
229 else: 238 else:
230 chunks, chunk_size = len(message), 80 #len(x)/4 239 chunks, chunk_size = len(message), 80 #len(x)/4
231 lines = [message[i:i + chunk_size] for i in range(0, chunks, chunk_size)] 240 lines = [message[i:i + chunk_size] for i in range(0, chunks, chunk_size)]
232 if color: 241 if color and self._clients[to].color_enabled:
233 if isinstance(color, list): 242 if isinstance(color, list):
234 colors = ''.join([get_color(c) for c in color]) 243 colors = ''.join([get_color(c) for c in color])
235 self._attempt_send(to, colors + '\r\n'.join(lines) + line_ending + get_color('reset')) 244 self._attempt_send(to, colors + '\r\n'.join(lines) + line_ending + get_color('reset'))
236 else: 245 else:
237 self._attempt_send(to, get_color(color) + '\r\n'.join(lines) + line_ending + get_color('reset')) 246 self._attempt_send(to, get_color(color) + '\r\n'.join(lines) + line_ending + get_color('reset'))
238 else: 247 else:
248 if color_enabled:
239 self._attempt_send(to, '\r\n'.join(lines) + line_ending + get_color('reset')) 249 self._attempt_send(to, '\r\n'.join(lines) + line_ending + get_color('reset'))
250 else:
251 self._attempt_send(to, '\r\n'.join(lines) + line_ending)
240 252
241 def shutdown(self): 253 def shutdown(self):
242 """Closes down the server, disconnecting all clients and 254 """Closes down the server, disconnecting all clients and
......
...@@ -36,9 +36,12 @@ def get_color(name): ...@@ -36,9 +36,12 @@ def get_color(name):
36 return '\x1b[{}m'.format(codes.get(name, 0)) 36 return '\x1b[{}m'.format(codes.get(name, 0))
37 37
38 38
39 def multiple_replace(text, replace_words): 39 def multiple_replace(text, replace_words, color_enabled=True):
40 for word, replacement in replace_words.items(): 40 for word, replacement in replace_words.items():
41 if color_enabled:
41 text = text.replace(word, get_color(replacement)) 42 text = text.replace(word, get_color(replacement))
43 else:
44 text = text.replace(word, '')
42 return text 45 return text
43 46
44 def save_object_to_file(obj, filename): 47 def save_object_to_file(obj, filename):
......
...@@ -9,7 +9,7 @@ Micropython port and expansion author: Barry Ruffner - barryruffner@gmail.com ...@@ -9,7 +9,7 @@ Micropython port and expansion author: Barry Ruffner - barryruffner@gmail.com
9 from time import sleep 9 from time import sleep
10 from math import floor 10 from math import floor
11 from sys import platform 11 from sys import platform
12 from os import listdir 12 from os import listdir, remove
13 13
14 from mudserver import MudServer 14 from mudserver import MudServer
15 from commandhandler import CommandHandler 15 from commandhandler import CommandHandler
...@@ -33,6 +33,137 @@ players = {} ...@@ -33,6 +33,137 @@ players = {}
33 # start the server 33 # start the server
34 globals()['mud'] = MudServer() 34 globals()['mud'] = MudServer()
35 35
36 races = {
37 "Android": {
38 "desc":"Androids are artificial creatures with both biological and mechanical elements, originally created by humanity as servants and now free to chart their own destiny among the stars.",
39 "mods": {"dex": 2, "int": 2, "cha": -2, "hp": 4}
40 },
41 "Human": {
42 "desc":"Ambitious, creative, and endlessly curious, humans have shown more drive to explore their system and the universe beyond than any of their neighbor races for better and for worse. They've helped usher in a new era of system-wide communication and organization and are admired for their passion and tenacity, but their tendency to shoot first and think about the consequences later can make them a liability for those races otherwise inclined to work with them.",
43 "mods": {"hp": 4}
44 },
45 "Kasathas": {
46 "desc":"Originally from a planet orbiting a dying star far beyond the Pact Worlds, the four-armed kasathas maintain a reputation as a noble and mysterious people. They are famous for their anachronistic warriors, ancient wisdom, and strange traditions.",
47 "mods": {"str": 2, "wis": 2, "int": -2, "hp": 4}
48 },
49 "Korasha Lashuntas": {
50 "desc":"Idealized by many other humanoid races and gifted with innate psychic abilities, lashuntas are at once consummate scholars and enlightened warriors, naturally divided into two specialized subraces with different abilities and societal roles.",
51 "mods": {"str": 2, "cha": 2, "wis": -2, "hp": 4}
52 },
53 "Damaya Lashuntas": {
54 "desc":"Idealized by many other humanoid races and gifted with innate psychic abilities, lashuntas are at once consummate scholars and enlightened warriors, naturally divided into two specialized subraces with different abilities and societal roles.",
55 "mods": {"int": 2, "cha": 2, "con": -2, "hp": 4}
56 },
57 "Shirrens": {
58 "desc":"Once part of a ravenous hive of locust-like predators, the insectile shirrens only recently broke with their hive mind to become a race of telepaths physically addicted to their own individualism, yet dedicated to the idea of community and harmony with other races",
59 "mods": {"con": 2, "wis": 2, "cha": -2, "hp": 6}
60 },
61 "Vesk": {
62 "desc":"Heavily muscled and covered with thick scales and short, sharp horns, the reptilian vesk are exactly as predatory and warlike as they appear. Originally hailing from a star system near the Pact Worlds, they sought to conquer and subdue their stellar neighbors, as they had all the other intelligent races in their own system, until an overwhelming threat forced them into a grudging alliance with the Pact Worlds for now.",
63 "mods": {"str": 2, "con": 2, "int": -2, "hp": 6}
64 },
65 "Ysoki": {
66 "desc":"Small and furtive, the ysoki are often overlooked by larger races. Yet through wit and technological prowess, they've spread throughout the solar system, giving truth to the old adage that every starship needs a few rats.",
67 "mods": {"dex": 2, "int": 2, "str": -2, "hp": 2}
68 }
69 }
70
71 themes = {
72 "Ace Pilot": {
73 "desc": "Skillful operator of starships and other vehicles who is obsessed with all related knowledge and lore.",
74 "mods": {"dex": 1}
75 },
76 "Bounty Hunter": {
77 "desc": "Unstoppable tracker who knows how to stay hot on the trail of those who flee.",
78 "mods": {"con": 1}
79 },
80 "Icon": {
81 "desc": "Popular and respected celebrity who can leverage the public's adoration for specific needs.",
82 "mods": {"cha": 1}
83 },
84 "Mercenary": {
85 "desc": "Well-trained soldier of fortune who can work equally well as a combat grunt or a squad leader.",
86 "mods": {"str": 1}
87 },
88 "Outlaw": {
89 "desc": "Wanted criminal with back-alley connections to black markets and associates who can fend off legal trouble.",
90 "mods": {"dex": 1}
91 },
92 "Priest": {
93 "desc": "Dedicated and knowledgeable adherent to a philosophy or religion who commands clout among other followers.",
94 "mods": {"wis": 1}
95 },
96 "Scholar": {
97 "desc": "Skilled researcher and cutting-edge thinker with a broad base of knowledge and a thirst to expand it.",
98 "mods": {"int": 1}
99 },
100 "Spacefarer": {
101 "desc": "Restless explorer who has strong intuition and has collected deep knowledge about alien biology and topology.",
102 "mods": {"con": 1}
103 },
104 "Xenoseeker": {
105 "desc": "Guru of alien life-forms who finds that meeting them is one of life's most rewarding accomplishments.",
106 "mods": {"cha": 1}
107 }
108 # "Themeless":{
109 # "desc": "One who doesn't fit into any niche above but forges a personal path of determination and training."
110 # "mods": {"": 1}
111 # },
112 }
113
114
115 classes = {
116 "Envoy": {
117 "desc": "Charismatic people person good at a wide range of skills who inspires allies to accomplish great heroic feats.",
118 "skills": ["Acrobatics", "Intimidate", "Athletics", "Medicine", "Bluff", "Perception", "Computers", "Piloting", "Culture", "Profession", "Diplomacy", "Sense Motive", "Disguise", "Sleight of Hand", "Engineering", "Stealth"],
119 "keyability": "cha",
120 "proficiencies": ["light armor", "basic melee", "grenades", "small arms"],
121 "skillperlevel": 8,
122 },
123 "Mechanic": {
124 "desc": "Master of machines and technology whose tinkering produces a drone companion or a powerful brain implant.",
125 "skills": ["Athletics", "Perception", "Computers", "Physical Science", "Engineering", "Piloting", "Medicine", "Profession"],
126 "keyability": "int",
127 "proficiencies": ["light armor", "basic melee", "grenades", "small arms"],
128 "skillperlevel": 4,
129 },
130 "Mystic": {
131 "desc": "Magic user whose mysterious connection to a powerful force grants abilities that break the laws of the universe.",
132 "skills": ["Bluff", "Medicine", "Culture", "Mysticism", "Diplomacy", "Perception", "Disguise", "Profession", "Intimidate", "Sense Motive", "Life Science", "Survival"],
133 "keyability": "wis",
134 "proficiencies": ["light armor", "basic melee", "small arms"],
135 "skillperlevel": 6,
136 },
137 "Operative": {
138 "desc": "Stealthy combatant with wide-ranging know-how who is adept at taking advantage of unprepared foes.",
139 "skills": ["Acrobatics", "Medicine", "Athletics", "Perception", "Bluff", "Piloting", "Computers", "Profession", "Culture", "Sense Motive", "Disguise", "Sleight of Hand", "Engineering", "Stealth", "Intimidate", "Survival"],
140 "keyability": "dex",
141 "proficiencies": ["light armor", "basic melee", "small arms", "sniper weapons"],
142 "skillperlevel": 8,
143 },
144 "Solarian": {
145 "desc": "Disciplined warrior whose mastery of the stars grants either a weapon or armor made of stellar power.",
146 "skills": ["Acrobatics", "Perception", "Athletics", "Physical Science", "Diplomacy", "Profession", "Intimidate", "Sense Motive", "Mysticism", "Stealth"],
147 "keyability": "cha",
148 "proficiencies": ["light armor", "basic melee", "advanced melee", "small arms"],
149 "skillperlevel": 4,
150 },
151 "Soldier": {
152 "desc": "Expert with a huge range of armor, guns, and melee weapons who specializes in certain types of gear.",
153 "skills": ["Acrobatics", "Medicine", "Athletics", "Piloting", "Engineering", "Profession", "Intimidate", "Survival"],
154 "keyability": "str",
155 "proficiencies": ["light armor", "heavy armor", "basic melee", "advanced melee", "small arms", "long arms", "heavy weapons", "sniper weapons", "grenades"],
156 "skillperlevel": 4,
157 },
158 "Technomancer": {
159 "desc": "Magic user who is preternaturally attuned to technology and can use it to unlock powerful effects.",
160 "skills": ["Computers", "Physical Science", "Engineering", "Piloting", "Life Science", "Profession", "Mysticism", "Sleight of Hand"],
161 "keyability": "int",
162 "proficiencies": ["light armor", "basic melee", "small arms"],
163 "skillperlevel": 4,
164 }
165 }
166
36 167
37 def show_prompt(pid): 168 def show_prompt(pid):
38 if "prompt" not in players[pid]: 169 if "prompt" not in players[pid]:
...@@ -143,6 +274,123 @@ def isalnum(c): ...@@ -143,6 +274,123 @@ def isalnum(c):
143 return False 274 return False
144 return True 275 return True
145 276
277 def handle_character_create(id, command, params):
278 if players[id]["createstep"] == 1:
279 players[id]["color_enabled"] = command[0] in ['y', 'Y']
280 mud._clients[id].color_enabled = players[id]["color_enabled"]
281 if players[id]["color_enabled"]:
282 mud.send_message(id, '%bold%blueC%yellowo%redl%greeno%cyanr%reset %boldenabled.%reset\r\n')
283 else:
284 mud.send_message(id, 'Color disabled.\r\n')
285 mud.send_message(id, "Are you at least 13 years of age?")
286 players[id]["createstep"] = 2
287
288 elif players[id]["createstep"] == 2:
289 players[id]["over_13"] = command[0] in ['y', 'Y']
290 if not players[id]["over_13"]:
291 mud.send_message(id, "You must be at least 13 years old to play this game.")
292 try:
293 mud._clients[id].socket.close()
294 remove("players/{}.json".format(players[id]["name"]))
295 del(players[id])
296 del(mud._clients[id])
297 except:
298 pass
299 return
300 else:
301 mud.send_message(id, " %green+------------=Races=------------+", nowrap=True)
302 for idx, race in enumerate(races):
303 mud.send_message(id, " %%green|%%reset%%bold%%white%s%%reset%%green|" % ('{}. {:<28}'.format(idx, race),), nowrap=True)
304 mud.send_message(id, " %green+-------------------------------+", nowrap=True)
305
306 mud.send_message(id, 'Please choose a race from the list by number: ')
307 players[id]["createstep"] = 3
308
309 elif players[id]["createstep"] == 3:
310 if command.lower().startswith("help"):
311 races_lower = {k.lower():v for k,v in races.items()}
312 race = races_lower.get(params.lower().strip())
313 if race:
314 mods = '\r\n'.join(" %green{!s: <4} %bold{!r}%reset".format(key,val) for (key,val) in race.get("mods").items())
315
316 mud.send_message(id, "\r\n%green{}\r\n%bold{}\r\n\n%resetStat Modifiers:".format(params.strip(), race.get("desc")))
317 mud.send_message(id, mods + "\r\n", nowrap=True)
318 else:
319 mud.send_message(id, "Please type the name of the race you want to learn about.", color='cyan')
320 if not command.isdigit():
321 mud.send_message(id, " %green+------------=Races=-----------+", nowrap=True)
322 for idx, race in enumerate(races):
323 mud.send_message(id, " %%green|%%reset%%bold%%white%s%%reset%%green|" % ('{}. {:<27}'.format(idx, race),), nowrap=True)
324 mud.send_message(id, " %green+------------------------------+", nowrap=True)
325
326 mud.send_message(id, ' (Type %boldhelp [race]%reset for details)\r\n')
327 mud.send_message(id, 'Please choose a race from the list by number: ')
328 else:
329 race = list(races)[int(command)]
330 mud.send_message(id, 'Race selected: {}'.format(race))
331
332 players[id]["race"] = race
333 players[id]["createstep"] = 4
334 mud.send_message(id, " %green+------------=Themes=-----------+", nowrap=True)
335 for idx, theme in enumerate(themes):
336 mud.send_message(id, " %%green|%%reset%%bold%%white%s%%reset%%green|" % ('{}. {:<27}'.format(idx, theme),), nowrap=True)
337 mud.send_message(id, " %green+------------------------------+", nowrap=True)
338
339 mud.send_message(id, ' (Type %boldhelp [theme]%reset for details)\r\n')
340 mud.send_message(id, 'Please choose a theme from the list by number: ')
341 elif players[id]["createstep"] == 4:
342 if command.lower().startswith("help"):
343 themes_lower = {k.lower():v for k,v in themes.items()}
344 theme = themes_lower.get(params.lower().strip())
345 if theme:
346 mods = '\r\n'.join(" %green{!s: <4} %bold{!r}%reset".format(key,val) for (key,val) in theme.get("mods").items())
347
348 mud.send_message(id, "\r\n%green{}\r\n%bold{}\r\n\n%resetStat Modifiers:".format(params.strip(), theme.get("desc")))
349 mud.send_message(id, mods + "\r\n", nowrap=True)
350 else:
351 mud.send_message(id, "Please type the name of the theme you want to learn about.", color='cyan')
352 if not command.isdigit():
353 mud.send_message(id, " %green+------------=Themes=-----------+", nowrap=True)
354 for idx, theme in enumerate(themes):
355 mud.send_message(id, " %%green|%%reset%%bold%%white%s%%reset%%green|" % ('{}. {:<27}'.format(idx, theme),), nowrap=True)
356 mud.send_message(id, " %green+------------------------------+", nowrap=True)
357
358 mud.send_message(id, ' (Type %boldhelp [theme]%reset for details)\r\n')
359 mud.send_message(id, 'Please choose a theme from the list by number: ')
360 else:
361 theme = list(themes)[int(command)]
362 mud.send_message(id, 'Theme selected: {}'.format(theme))
363
364 players[id]["theme"] = theme
365 players[id]["createstep"] = 5
366 elif players[id]["createstep"] == 5:
367 if command.lower().startswith("help"):
368 themes_lower = {k.lower():v for k,v in themes.items()}
369 theme = themes_lower.get(params.lower().strip())
370 if theme:
371 mods = '\r\n'.join(" %green{!s: <4} %bold{!r}%reset".format(key,val) for (key,val) in theme.get("mods").items())
372
373 mud.send_message(id, "\r\n%green{}\r\n%bold{}\r\n\n%resetStat Modifiers:".format(params.strip(), theme.get("desc")))
374 mud.send_message(id, mods + "\r\n", nowrap=True)
375 else:
376 mud.send_message(id, "Please type the name of the theme you want to learn about.", color='cyan')
377 if not command.isdigit():
378 mud.send_message(id, " %green+------------=Themes=-----------+", nowrap=True)
379 for idx, theme in enumerate(themes):
380 mud.send_message(id, " %%green|%%reset%%bold%%white%s%%reset%%green|" % ('{}. {:<27}'.format(idx, theme),), nowrap=True)
381 mud.send_message(id, " %green+------------------------------+", nowrap=True)
382
383 mud.send_message(id, ' (Type %boldhelp [theme]%reset for details)\r\n')
384 mud.send_message(id, 'Please choose a theme from the list by number: ')
385 else:
386 theme = list(themes)[int(command)]
387 mud.send_message(id, 'Theme selected: {}'.format(theme))
388
389 players[id]["theme"] = theme
390 players[id]["createstep"] = 5
391
392 save_object_to_file(players[id], "players/{}.json".format(players[id]["name"]))
393
146 # main game loop. We loop forever (i.e. until the program is terminated) 394 # main game loop. We loop forever (i.e. until the program is terminated)
147 while True: 395 while True:
148 if 'esp' in platform: 396 if 'esp' in platform:
...@@ -261,9 +509,16 @@ while True: ...@@ -261,9 +509,16 @@ while True:
261 if loaded_player is None: 509 if loaded_player is None:
262 players[id]["password"] = password_hash(players[pid]["name"], command) 510 players[id]["password"] = password_hash(players[pid]["name"], command)
263 players[id]["room"] = "town/tavern" 511 players[id]["room"] = "town/tavern"
512 players[id]["createstep"] = 1
513 mud.send_message(pid, "Can you view %bold%bluecolors%reset? ")
514 continue
264 else: 515 else:
265 if loaded_player["password"] == password_hash(players[pid]["name"], command): 516 if loaded_player["password"] == password_hash(players[pid]["name"], command):
266 players[id] = loaded_player 517 players[id] = loaded_player
518 mud._clients[id].color_enabled = players[id]["color_enabled"]
519 if players[id]["createstep"]:
520 mud.send_message(pid, "Can you view %bold%bluecolors%reset? ")
521 continue
267 else: 522 else:
268 players[id]["retries"] = players[id].get("retries", 0) + 1 523 players[id]["retries"] = players[id].get("retries", 0) + 1
269 mud.send_message(id, "Invalid Password") 524 mud.send_message(id, "Invalid Password")
...@@ -283,6 +538,8 @@ while True: ...@@ -283,6 +538,8 @@ while True:
283 538
284 cmd_handler.parse(id, 'look', '', mud, players) 539 cmd_handler.parse(id, 'look', '', mud, players)
285 show_prompt(id) 540 show_prompt(id)
541 elif players[id].get("createstep"):
542 handle_character_create(id, command, params)
286 else: 543 else:
287 if 'esp' in platform: 544 if 'esp' in platform:
288 collect() 545 collect()
......