Added soul plates, reflectors and messaging for pankration.
Showing
4 changed files
with
273 additions
and
24 deletions
... | @@ -247,25 +247,100 @@ def db_get_pankration_record(member_id): | ... | @@ -247,25 +247,100 @@ def db_get_pankration_record(member_id): |
247 | pan_record.close() | 247 | pan_record.close() |
248 | return dict_factory(c, result) | 248 | return dict_factory(c, result) |
249 | 249 | ||
250 | def db_add_monster(member_id, monster): | 250 | def db_add_soul_plate(member_id, soul_plate): |
251 | pan_record = db_get_pankration_record(member_id) | 251 | pan_record = db_get_pankration_record(member_id) |
252 | log("{}".format(member_id)) | 252 | log("{}".format(member_id)) |
253 | conn = sqlite3.connect('db.sqlite3') | 253 | conn = sqlite3.connect('db.sqlite3') |
254 | c = conn.cursor() | 254 | c = conn.cursor() |
255 | db_state = c.execute("SELECT monster_inventory FROM pankration WHERE member_id = ?;", (member_id,)).fetchone() | 255 | db_state = c.execute("SELECT soul_plates, member_id FROM pankration WHERE member_id = ?;", (member_id,)).fetchone() |
256 | if not db_state: | 256 | if not db_state: |
257 | c.execute("""INSERT INTO pankration(member_id, wins, losses, monster_inventory) | 257 | log("no record") |
258 | VALUES(?, ?, ?, ?);""", (member_id, 0, 0, pickle.dumps([monster]))) | 258 | c.execute("""INSERT INTO pankration(member_id, wins, losses, soul_plates) |
259 | VALUES(?, ?, ?, ?);""", (member_id, 0, 0, pickle.dumps([soul_plate]))) | ||
259 | conn.commit() | 260 | conn.commit() |
260 | else: | 261 | else: |
261 | log(db_state) | 262 | log(db_state) |
263 | if db_state[0] and len(db_state[0]) > 0: | ||
262 | inv = str(db_state[0]) | 264 | inv = str(db_state[0]) |
263 | log(inv) | 265 | soul_plates = pickle.loads(inv) |
264 | monster_inventory = pickle.loads(inv) | 266 | else: |
265 | monster_inventory.append(monster) | 267 | soul_plates = [] |
266 | c.execute("""UPDATE pankration SET monster_inventory = ? | 268 | soul_plates.append(soul_plate) |
267 | WHERE member_id = ?;""", (pickle.dumps(monster_inventory), member_id)) | 269 | c.execute("""UPDATE pankration SET soul_plates = ? |
270 | WHERE member_id = ?;""", (pickle.dumps(soul_plates), member_id)) | ||
271 | conn.commit() | ||
272 | |||
273 | def db_remove_soul_plate(member_id, idx): | ||
274 | pan_record = db_get_pankration_record(member_id) | ||
275 | log("{}".format(member_id)) | ||
276 | conn = sqlite3.connect('db.sqlite3') | ||
277 | c = conn.cursor() | ||
278 | db_state = c.execute("SELECT soul_plates, member_id FROM pankration WHERE member_id = ?;", (member_id,)).fetchone() | ||
279 | if not db_state: | ||
280 | log("Invalid remove request for reflector: {}".format(idx,)) | ||
281 | return False | ||
282 | else: | ||
283 | log(db_state) | ||
284 | if db_state[0] and len(db_state[0]) > 0: | ||
285 | inv = str(db_state[0]) | ||
286 | soul_plates = pickle.loads(inv) | ||
287 | else: | ||
288 | log("Invalid remove request for reflector: {}".format(idx,)) | ||
289 | return False | ||
290 | del soul_plates[idx] | ||
291 | c.execute("""UPDATE pankration SET soul_plates = ? | ||
292 | WHERE member_id = ?;""", (pickle.dumps(soul_plates), member_id)) | ||
293 | conn.commit() | ||
294 | |||
295 | def db_add_reflector(member_id, reflector): | ||
296 | pan_record = db_get_pankration_record(member_id) | ||
297 | log("{}".format(member_id)) | ||
298 | conn = sqlite3.connect('db.sqlite3') | ||
299 | c = conn.cursor() | ||
300 | db_state = c.execute("SELECT reflectors, member_id FROM pankration WHERE member_id = ?;", (member_id,)).fetchone() | ||
301 | if not db_state: | ||
302 | log("no record") | ||
303 | c.execute("""INSERT INTO pankration(member_id, wins, losses, reflectors) | ||
304 | VALUES(?, ?, ?, ?);""", (member_id, 0, 0, pickle.dumps([reflector]))) | ||
268 | conn.commit() | 305 | conn.commit() |
306 | else: | ||
307 | log(db_state) | ||
308 | if db_state[0] and len(db_state[0]) > 0: | ||
309 | inv = str(db_state[0]) | ||
310 | reflectors = pickle.loads(inv) | ||
311 | else: | ||
312 | reflectors = [] | ||
313 | reflectors.append(reflector) | ||
314 | c.execute("""UPDATE pankration SET reflectors = ? | ||
315 | WHERE member_id = ?;""", (pickle.dumps(reflectors), member_id)) | ||
316 | conn.commit() | ||
317 | |||
318 | def db_remove_reflector(member_id, idx): | ||
319 | pan_record = db_get_pankration_record(member_id) | ||
320 | log("{}".format(member_id)) | ||
321 | conn = sqlite3.connect('db.sqlite3') | ||
322 | c = conn.cursor() | ||
323 | db_state = c.execute("SELECT reflectors, member_id FROM pankration WHERE member_id = ?;", (member_id,)).fetchone() | ||
324 | if not db_state: | ||
325 | log("Invalid remove request for reflector: {}".format(idx,)) | ||
326 | return False | ||
327 | else: | ||
328 | log(db_state) | ||
329 | if db_state[0] and len(db_state[0]) > 0: | ||
330 | inv = str(db_state[0]) | ||
331 | reflectors = pickle.loads(inv) | ||
332 | else: | ||
333 | log("Invalid remove request for reflector: {}".format(idx,)) | ||
334 | return False | ||
335 | del reflectors[idx] | ||
336 | c.execute("""UPDATE pankration SET reflectors = ? | ||
337 | WHERE member_id = ?;""", (pickle.dumps(reflectors), member_id)) | ||
338 | conn.commit() | ||
339 | |||
340 | def db_convert_soul_plate_to_reflector(member_id, soul_plate, idx): | ||
341 | db_add_reflector(member_id, soul_plate) | ||
342 | db_remove_soul_plate(member_id, idx) | ||
343 | |||
269 | 344 | ||
270 | def db_get_member(discord_id=None, username=None): | 345 | def db_get_member(discord_id=None, username=None): |
271 | # Do a lookup by ID, if it's found but the name doesn't match then add a row to aliases with the previous name and change the member name | 346 | # Do a lookup by ID, if it's found but the name doesn't match then add a row to aliases with the previous name and change the member name | ... | ... |
No preview for this file type
... | @@ -85,7 +85,11 @@ registered_commands = {'!help': 'do_help', '!commands': 'do_help', | ... | @@ -85,7 +85,11 @@ registered_commands = {'!help': 'do_help', '!commands': 'do_help', |
85 | '!rigged': 'do_rigged', | 85 | '!rigged': 'do_rigged', |
86 | '!listzones': 'do_list_zones', | 86 | '!listzones': 'do_list_zones', |
87 | '!huntmonster': 'do_hunt_monster', | 87 | '!huntmonster': 'do_hunt_monster', |
88 | '!listmonster': 'do_list_monsters', | 88 | '!listferalskills': 'do_list_feral_skills', '!listferalskill': 'do_list_feral_skills', |
89 | '!listreflectors': 'do_list_reflectors', '!listreflector': 'do_list_reflectors', | ||
90 | '!listsoulplates': 'do_list_soul_plates', '!listsoulplate': 'do_list_soul_plates', | ||
91 | '!convertplate': 'do_convert_plate', '!convertsoulplate': 'do_convert_plate', | ||
92 | '!pankration': 'do_pankration', | ||
89 | } | 93 | } |
90 | 94 | ||
91 | 95 | ||
... | @@ -1015,34 +1019,116 @@ def do_rigged(client, message_parts, message): | ... | @@ -1015,34 +1019,116 @@ def do_rigged(client, message_parts, message): |
1015 | send_message(client, message.channel, ":musical_note: {} :musical_note:".format(random.choice(lines))) | 1019 | send_message(client, message.channel, ":musical_note: {} :musical_note:".format(random.choice(lines))) |
1016 | return | 1020 | return |
1017 | 1021 | ||
1018 | def do_list_monsters(client, message_parts, message): | 1022 | #### PANKRATION |
1023 | |||
1024 | |||
1025 | def do_pankration(client, message_parts, message): | ||
1026 | send_message(client, message.channel, """**NOTE! This is NOT implemented yet.. only partially** | ||
1027 | {} Available Commands: | ||
1028 | |||
1029 | *Hunting for Soul Plates:* | ||
1030 | **!listzones** - Returns a list of zones available for hunting and how many credits it costs to search in that zone. Depending on the weather and other factors some zones may not always be available. | ||
1031 | **!huntmonster <zone>** - An attempt will be made to search for a soul plate (monster) in the zone specified. Each search costs a certain amount of credits. Each zone has a different cost. | ||
1032 | |||
1033 | *Viewing Your Inventory:* | ||
1034 | **!listsoulplates** - Returns a list of all soul plates you have in your posession. | ||
1035 | **!listreflectors** - Returns a list of all reflectors you have in your posession (The available monsters you can fight with). | ||
1036 | **!listferalskills** - Returns a list of all feral skills you have in your inventory | ||
1037 | |||
1038 | *Editing Your Collections:* | ||
1039 | **!convertplate <plate number> <convert_to>** - From the list of soul plates you can choose to either convert the plate into a \"reflector\" or \"skill\". | ||
1040 | Ex: **!convertplate 1 reflector** | ||
1041 | **!convertplate 4 skill** | ||
1042 | **!assignskill <reflector number> <skill num>** - Assigns a skill to a reflector. Each skill is worth a certain amount of feral points, each monster has a maximum of feral points available. | ||
1043 | |||
1044 | *Arena Battle:* | ||
1045 | **!registerbattle <reflector number>** - Adds your reflector to the queue in the arena. When the arena is available your monster will be paired with either another players monster or a similarly matched arena monster. | ||
1046 | **!registerbattle <reflector number> <player name>** - If you want to challenge a specific user to a battle just provide their user name. Have them do the same and your battle will start when the arena is available. | ||
1047 | |||
1048 | """.format(message.author.mention())) | ||
1049 | |||
1050 | def do_convert_plate(client, message_parts, message): | ||
1019 | member = data.db_get_member(message.author.id) | 1051 | member = data.db_get_member(message.author.id) |
1020 | log(member) | 1052 | |
1021 | monster_data = data.db_get_pankration_record(member['member_id']) | 1053 | pankration_data = data.db_get_pankration_record(member['member_id']) |
1022 | if monster_data: | 1054 | if pankration_data and pankration_data['soul_plates']: |
1023 | monsters = pickle.loads(str(monster_data['monster_inventory'])) | 1055 | log(message_parts) |
1024 | send_message(client, message.channel, "\n\n".join(str(monster) for monster in monsters)) | 1056 | if len(message_parts) < 2: |
1057 | send_message(client, message.channel, 'You must provide at least 2 arguments for converting a plate. The plate number and the type of conversion. Please see !pankration for an example.') | ||
1058 | return | ||
1059 | |||
1060 | plate_num = message_parts[0] | ||
1061 | convert_to = message_parts[1] | ||
1062 | |||
1063 | soul_plates = pickle.loads(str(pankration_data['soul_plates'])) | ||
1064 | if not plate_num.isdigit() or int(plate_num) < 1 or int(plate_num) > len(soul_plates): | ||
1065 | send_message(client, message.channel, 'The requested plate is invalid. Please provide the number from !listsoulplates') | ||
1066 | return | ||
1067 | plate_num = int(plate_num) | ||
1068 | if convert_to == "reflector": | ||
1069 | # do reflector stuff | ||
1070 | data.db_convert_soul_plate_to_reflector(member['member_id'], soul_plates[plate_num], plate_num) | ||
1071 | pass | ||
1072 | elif convert_to == "skill": | ||
1073 | # do skill stuff | ||
1074 | pass | ||
1025 | else: | 1075 | else: |
1026 | send_message(client, message.channel, 'You have no monsters.') | 1076 | send_message(client, message.channel, 'A plate can only be converted into a reflector or skill. Please see !pankration for an example.') |
1077 | return | ||
1078 | |||
1079 | #send_message(client, message.channel, "\n\n".join("{}. {}".format(idx+1, str(soul_plate)) for idx, soul_plate in enumerate(soul_plates))) | ||
1080 | else: | ||
1081 | send_message(client, message.channel, 'You have no soul plates to convert.') | ||
1082 | |||
1083 | def do_list_soul_plates(client, message_parts, message): | ||
1084 | member = data.db_get_member(message.author.id) | ||
1085 | |||
1086 | pankration_data = data.db_get_pankration_record(member['member_id']) | ||
1087 | if pankration_data and pankration_data['soul_plates']: | ||
1088 | soul_plates = pickle.loads(str(pankration_data['soul_plates'])) | ||
1089 | send_message(client, message.channel, "\n\n".join("{}. {}".format(idx+1, str(soul_plate.get_soul_plate_description())) for idx, soul_plate in enumerate(soul_plates))) | ||
1090 | else: | ||
1091 | send_message(client, message.channel, 'You have no soul plates.') | ||
1092 | |||
1093 | def do_list_reflectors(client, message_parts, message): | ||
1094 | member = data.db_get_member(message.author.id) | ||
1095 | |||
1096 | pankration_data = data.db_get_pankration_record(member['member_id']) | ||
1097 | if pankration_data and pankration_data['reflectors']: | ||
1098 | reflectors = pickle.loads(str(pankration_data['reflectors'])) | ||
1099 | send_message(client, message.channel, "\n\n".join("{}. {}".format(idx+1, str(reflector)) for idx, reflector in enumerate(reflectors))) | ||
1100 | else: | ||
1101 | send_message(client, message.channel, 'You have no reflectors.') | ||
1102 | |||
1103 | |||
1104 | def do_list_feral_skills(client, message_parts, message): | ||
1105 | member = data.db_get_member(message.author.id) | ||
1106 | |||
1107 | pankration_data = data.db_get_pankration_record(member['member_id']) | ||
1108 | if pankration_data and pankration_data['feral_skills']: | ||
1109 | feral_skills = pickle.loads(str(pankration_data['feral_skills'])) | ||
1110 | send_message(client, message.channel, "\n\n".join("{}. {}".format(idx+1, str(feral_skill)) for idx, feral_skill in enumerate(feral_skills))) | ||
1111 | else: | ||
1112 | send_message(client, message.channel, 'You have no feral skills.') | ||
1027 | 1113 | ||
1028 | def do_hunt_monster(client, message_parts, message): | 1114 | def do_hunt_monster(client, message_parts, message): |
1029 | p = Pankration() | 1115 | p = Pankration() |
1030 | hunt_response = p.hunt_monster(' '.join(message_parts)) | 1116 | hunt_response = p.hunt_monster(' '.join(message_parts)) |
1031 | str_out = hunt_response.message + "\n\n" | 1117 | str_out = hunt_response.message + "\n\n" |
1032 | if hunt_response.result == HuntResponse.SUCCESS: | 1118 | if hunt_response.result == HuntResponse.SUCCESS: |
1033 | monster = hunt_response.monster | 1119 | soul_plate = hunt_response.monster |
1034 | member = data.db_get_member(message.author.id) | 1120 | member = data.db_get_member(message.author.id) |
1035 | data.db_add_monster(member['member_id'], monster) | 1121 | data.db_add_soul_plate(member['member_id'], soul_plate) |
1036 | str_out += str(monster) | 1122 | str_out += str(soul_plate.get_soul_plate_description()) |
1037 | send_message(client, message.channel, str_out) | 1123 | send_message(client, message.channel, str_out) |
1038 | 1124 | ||
1039 | return | ||
1040 | |||
1041 | def do_list_zones(client, message_parts, message): | 1125 | def do_list_zones(client, message_parts, message): |
1042 | p = Pankration() | 1126 | p = Pankration() |
1043 | send_message(client, message.channel, ', '.join(p.list_zones())) | 1127 | send_message(client, message.channel, ', '.join(p.list_zones())) |
1044 | return | 1128 | return |
1045 | 1129 | ||
1130 | |||
1131 | ### END PANKRATION | ||
1046 | def start_timer(client): | 1132 | def start_timer(client): |
1047 | needs_loot = True | 1133 | needs_loot = True |
1048 | while not quitting: | 1134 | while not quitting: | ... | ... |
... | @@ -79,6 +79,31 @@ class Jobs: | ... | @@ -79,6 +79,31 @@ class Jobs: |
79 | members = [attr for attr in dir(Jobs()) if not callable(attr) and not attr.startswith("__") and not attr.startswith("get_job_name")] | 79 | members = [attr for attr in dir(Jobs()) if not callable(attr) and not attr.startswith("__") and not attr.startswith("get_job_name")] |
80 | return members[job-1] | 80 | return members[job-1] |
81 | 81 | ||
82 | evasion_by_job = { | ||
83 | Jobs.BLM: {'base_eva': 4, 'eva_per_level': 2.48}, | ||
84 | Jobs.BLU: {'base_eva': 5, 'eva_per_level': 2.78}, | ||
85 | Jobs.BRD: {'base_eva': 4, 'eva_per_level': 2.66}, | ||
86 | Jobs.BST: {'base_eva': 5, 'eva_per_level': 2.78}, | ||
87 | Jobs.COR: {'base_eva': 4, 'eva_per_level': 2.66}, | ||
88 | Jobs.DNC: {'base_eva': 5, 'eva_per_level': 2.88}, | ||
89 | Jobs.DRG: {'base_eva': 5, 'eva_per_level': 2.88}, | ||
90 | Jobs.DRK: {'base_eva': 5, 'eva_per_level': 2.78}, | ||
91 | Jobs.GEO: {'base_eva': 4, 'eva_per_level': 2.66}, | ||
92 | Jobs.MNK: {'base_eva': 5, 'eva_per_level': 2.88}, | ||
93 | Jobs.NIN: {'base_eva': 6, 'eva_per_level': 3}, | ||
94 | Jobs.PLD: {'base_eva': 5, 'eva_per_level': 2.78}, | ||
95 | Jobs.PUP: {'base_eva': 5, 'eva_per_level': 2.88}, | ||
96 | Jobs.RDM: {'base_eva': 4, 'eva_per_level': 2.66}, | ||
97 | Jobs.RNG: {'base_eva': 4, 'eva_per_level': 2.48}, | ||
98 | Jobs.RUN: {'base_eva': 5, 'eva_per_level': 2.88}, | ||
99 | Jobs.SAM: {'base_eva': 5, 'eva_per_level': 2.88}, | ||
100 | Jobs.SCH: {'base_eva': 4, 'eva_per_level': 2.48}, | ||
101 | Jobs.SMN: {'base_eva': 4, 'eva_per_level': 2.48}, | ||
102 | Jobs.THF: {'base_eva': 6, 'eva_per_level': 3}, | ||
103 | Jobs.WAR: {'base_eva': 5, 'eva_per_level': 2.78}, | ||
104 | Jobs.WHM: {'base_eva': 4, 'eva_per_level': 2.48}, | ||
105 | } | ||
106 | |||
82 | TemperamentPosture = { | 107 | TemperamentPosture = { |
83 | 4: {"name": "Very Agressive", "message": "Show no mercy!", "value": 4}, | 108 | 4: {"name": "Very Agressive", "message": "Show no mercy!", "value": 4}, |
84 | 3: {"name": "Somewhat Agressive", "message": "Give em' a little more bite!", "value": 3}, | 109 | 3: {"name": "Somewhat Agressive", "message": "Give em' a little more bite!", "value": 3}, |
... | @@ -297,9 +322,28 @@ class Monster: | ... | @@ -297,9 +322,28 @@ class Monster: |
297 | self.base_dex = family['base_dex'] | 322 | self.base_dex = family['base_dex'] |
298 | self.dex_per_level = family['dex_per_level'] | 323 | self.dex_per_level = family['dex_per_level'] |
299 | self.hp = self.get_hp() | 324 | self.hp = self.get_hp() |
325 | self.wins = 0 | ||
326 | self.losses = 0 | ||
300 | 327 | ||
301 | def __str__(self): | 328 | def __str__(self): |
302 | return "**Stats:**\nFamily: {}\nLevel: {}\nMain Job: {}\nSupport Job: {}\nInnate Feral Skills: {}\nEquipped Feral Skills: {}\nFeral Points: {}".format(self.family_name, self.level, Jobs().get_job_name(self.main_job), Jobs().get_job_name(self.support_job), ', '.join(self.innate_feral_skills), ', '.join(self.equipped_feral_skills), self.get_fp()) | 329 | try: |
330 | return "**{}**\n*Stats:*\nFamily: {}\nLevel: {}\nMain Job: {}\nSupport Job: {}\nInnate Feral Skills: {}\nEquipped Feral Skills: {}\nFeral Points: {}\n\nWins: {}\nLosses: {}".format(self.monster_type, self.family_name, self.level, Jobs().get_job_name(self.main_job), Jobs().get_job_name(self.support_job), ', '.join(self.innate_feral_skills), ', '.join(self.equipped_feral_skills), self.get_fp(), self.wins, self.losses) | ||
331 | except AttributeError: | ||
332 | return "Old Format monster, unable to display." | ||
333 | #return "Family: {}\nLevel: {}\nMain Job: {}\nSupport Job: {}\nInnate Feral Skills: {}\nEquipped Feral Skills: {}\nDicipline Level: {}\nTemperament...".format(self.family, self.level, self.main_job, self.support_job, self.innate_feral_skills, self.equipped_feral_skills, self.discipline_level) | ||
334 | |||
335 | def get_soul_plate_description(self): | ||
336 | try: | ||
337 | return "*Family:*\n**{}**\nJob Trait: {}\nFeral Points: {}".format(self.family_name, Jobs().get_job_name(self.main_job), self.get_fp()) | ||
338 | except AttributeError: | ||
339 | return "Old Format monster, unable to display." | ||
340 | #return "Family: {}\nLevel: {}\nMain Job: {}\nSupport Job: {}\nInnate Feral Skills: {}\nEquipped Feral Skills: {}\nDicipline Level: {}\nTemperament...".format(self.family, self.level, self.main_job, self.support_job, self.innate_feral_skills, self.equipped_feral_skills, self.discipline_level) | ||
341 | |||
342 | def get_reflector_description(self): | ||
343 | try: | ||
344 | return "**{}**\n*Stats:*\nFamily: {}\nLevel: {}\nMain Job: {}\nSupport Job: {}\nInnate Feral Skills: {}\nEquipped Feral Skills: {}\nFeral Points: {}\n\nWins: {}\nLosses: {}".format(self.monster_type, self.family_name, self.level, Jobs().get_job_name(self.main_job), Jobs().get_job_name(self.support_job), ', '.join(self.innate_feral_skills), ', '.join(self.equipped_feral_skills), self.get_fp(), self.wins, self.losses) | ||
345 | except AttributeError: | ||
346 | return "Old Format monster, unable to display." | ||
303 | #return "Family: {}\nLevel: {}\nMain Job: {}\nSupport Job: {}\nInnate Feral Skills: {}\nEquipped Feral Skills: {}\nDicipline Level: {}\nTemperament...".format(self.family, self.level, self.main_job, self.support_job, self.innate_feral_skills, self.equipped_feral_skills, self.discipline_level) | 347 | #return "Family: {}\nLevel: {}\nMain Job: {}\nSupport Job: {}\nInnate Feral Skills: {}\nEquipped Feral Skills: {}\nDicipline Level: {}\nTemperament...".format(self.family, self.level, self.main_job, self.support_job, self.innate_feral_skills, self.equipped_feral_skills, self.discipline_level) |
304 | 348 | ||
305 | def get_hp(self): | 349 | def get_hp(self): |
... | @@ -336,11 +380,25 @@ class Monster: | ... | @@ -336,11 +380,25 @@ class Monster: |
336 | else: | 380 | else: |
337 | return "Obedient" | 381 | return "Obedient" |
338 | 382 | ||
383 | def get_combat_skill(self): | ||
384 | # This is a very very complicated relationship betwen job and weapon type and how often it is used. | ||
385 | # We are going to generalize it since it's a pain in the ass and just take the average A+ rating and get the cap for the current level | ||
386 | return int(round(max(5, self.level * 2.88))) | ||
387 | |||
388 | |||
339 | def get_dexterity(self): | 389 | def get_dexterity(self): |
340 | return int(round(max(self.base_dex, self.level * self.dex_per_level))) | 390 | return int(round(max(self.base_dex, self.level * self.dex_per_level))) |
341 | 391 | ||
342 | def get_accuracy(self): | 392 | def get_accuracy(self): |
343 | return int(math.floor(3*self.get_dexterity()/4) + 100) | 393 | # We ignore magic / ranged / melee here and give everyone a good acc. This could be improved by doing a lookup for each type and based on the |
394 | # type of monster (magic, range, or melee) then adjust the combat skill according to what type of attack is being performed. | ||
395 | return int(math.floor(3*self.get_dexterity()/4) + self.get_combat_skill()) | ||
396 | |||
397 | def get_evasion(self): | ||
398 | job_eva = evasion_by_job[self.main_job] | ||
399 | base_eva = int(round(max(job_eva['base_eva'], self.level * job_eva['eva_per_level']))) | ||
400 | |||
401 | return base_eva + int(self.get_agility() / 2) | ||
344 | 402 | ||
345 | def get_vitality(self): | 403 | def get_vitality(self): |
346 | return int(round(max(self.base_vit, self.level * self.vit_per_level))) | 404 | return int(round(max(self.base_vit, self.level * self.vit_per_level))) |
... | @@ -358,6 +416,14 @@ class Monster: | ... | @@ -358,6 +416,14 @@ class Monster: |
358 | print(self.hp) | 416 | print(self.hp) |
359 | return max(0, int(round((self.hp/self.get_hp())*100))) | 417 | return max(0, int(round((self.hp/self.get_hp())*100))) |
360 | 418 | ||
419 | def get_hit_rate(self, enemy_eva, level_difference): | ||
420 | rate = 75 + math.floor(((self.get_accuracy() - enemy_eva)/2)) - (2*level_difference) | ||
421 | if rate < 20: | ||
422 | rate = 20 | ||
423 | elif rate > 95: | ||
424 | rate = 95 | ||
425 | return rate | ||
426 | |||
361 | # Calculate the base damage against the provided defense | 427 | # Calculate the base damage against the provided defense |
362 | # attack_type can be 'ranged' or 'melee' | 428 | # attack_type can be 'ranged' or 'melee' |
363 | def get_physical_base_damage(self, defense, attack_type, level_difference, enemy_vit): | 429 | def get_physical_base_damage(self, defense, attack_type, level_difference, enemy_vit): |
... | @@ -421,6 +487,9 @@ class Monster: | ... | @@ -421,6 +487,9 @@ class Monster: |
421 | phy_damage = self.get_physical_base_damage(monster.get_base_defense(), 'melee', monster.level - self.level, monster.get_vitality()) | 487 | phy_damage = self.get_physical_base_damage(monster.get_base_defense(), 'melee', monster.level - self.level, monster.get_vitality()) |
422 | return (phy_damage, 'hits') | 488 | return (phy_damage, 'hits') |
423 | 489 | ||
490 | def is_a_hit(self, monster): | ||
491 | hit_rate = self.get_hit_rate(monster.get_evasion(), monster.level - self.level) | ||
492 | return random.randint(1, 100) < hit_rate | ||
424 | 493 | ||
425 | def apply_damage(self, damage): | 494 | def apply_damage(self, damage): |
426 | self.hp -= damage | 495 | self.hp -= damage |
... | @@ -458,6 +527,12 @@ class AttackAction(Action): | ... | @@ -458,6 +527,12 @@ class AttackAction(Action): |
458 | self.damage = damage | 527 | self.damage = damage |
459 | self.message = message | 528 | self.message = message |
460 | 529 | ||
530 | class MissAction(Action): | ||
531 | def __init__(self, attacker, target, message): | ||
532 | self.attacker = attacker | ||
533 | self.target = target | ||
534 | self.message = message | ||
535 | |||
461 | class DefeatAction(Action): | 536 | class DefeatAction(Action): |
462 | def __init__(self, attacker, target, message, xp): | 537 | def __init__(self, attacker, target, message, xp): |
463 | self.attacker = attacker | 538 | self.attacker = attacker |
... | @@ -465,6 +540,7 @@ class DefeatAction(Action): | ... | @@ -465,6 +540,7 @@ class DefeatAction(Action): |
465 | self.message = message | 540 | self.message = message |
466 | self.xp = xp | 541 | self.xp = xp |
467 | 542 | ||
543 | |||
468 | class Arena: | 544 | class Arena: |
469 | 545 | ||
470 | def __init__(self, monster1, monster2, battle_type): | 546 | def __init__(self, monster1, monster2, battle_type): |
... | @@ -489,6 +565,7 @@ class Arena: | ... | @@ -489,6 +565,7 @@ class Arena: |
489 | primary = self.monster2 | 565 | primary = self.monster2 |
490 | secondary = self.monster1 | 566 | secondary = self.monster1 |
491 | 567 | ||
568 | if primary.is_a_hit(secondary): | ||
492 | result1 = primary.attack(secondary) | 569 | result1 = primary.attack(secondary) |
493 | secondary.apply_damage(result1[0]) | 570 | secondary.apply_damage(result1[0]) |
494 | actions.append(AttackAction(primary, secondary, result1[0], result1[1])) | 571 | actions.append(AttackAction(primary, secondary, result1[0], result1[1])) |
... | @@ -502,6 +579,10 @@ class Arena: | ... | @@ -502,6 +579,10 @@ class Arena: |
502 | xp = 0 | 579 | xp = 0 |
503 | actions.append(DefeatAction(primary, secondary, 'was defeated', xp)) | 580 | actions.append(DefeatAction(primary, secondary, 'was defeated', xp)) |
504 | return actions | 581 | return actions |
582 | else: | ||
583 | actions.append(MissAction(primary, secondary, 'missed')) | ||
584 | |||
585 | if secondary.is_a_hit(primary): | ||
505 | result2 = secondary.attack(primary) | 586 | result2 = secondary.attack(primary) |
506 | primary.apply_damage(result2[0]) | 587 | primary.apply_damage(result2[0]) |
507 | actions.append(AttackAction(secondary, primary, result2[0], result2[1])) | 588 | actions.append(AttackAction(secondary, primary, result2[0], result2[1])) |
... | @@ -509,6 +590,8 @@ class Arena: | ... | @@ -509,6 +590,8 @@ class Arena: |
509 | xp = 200 + (20 * (primary.level - secondary.level)) | 590 | xp = 200 + (20 * (primary.level - secondary.level)) |
510 | actions.append(DefeatAction(secondary, primary, 'was defeated', xp)) | 591 | actions.append(DefeatAction(secondary, primary, 'was defeated', xp)) |
511 | return actions | 592 | return actions |
593 | else: | ||
594 | actions.append(MissAction(secondary, primary, 'missed')) | ||
512 | return actions | 595 | return actions |
513 | 596 | ||
514 | 597 | ||
... | @@ -552,7 +635,10 @@ if __name__ == "__main__": | ... | @@ -552,7 +635,10 @@ if __name__ == "__main__": |
552 | 635 | ||
553 | 636 | ||
554 | print("Acc: {}".format(monster.get_accuracy())) | 637 | print("Acc: {}".format(monster.get_accuracy())) |
638 | print("Eva: {}".format(monster.get_evasion())) | ||
639 | |||
555 | print("Acc: {}".format(monster2.get_accuracy())) | 640 | print("Acc: {}".format(monster2.get_accuracy())) |
641 | print("Eva: {}".format(monster2.get_evasion())) | ||
556 | 642 | ||
557 | battle_arena = p.start_battle(monster, monster2, "derp") | 643 | battle_arena = p.start_battle(monster, monster2, "derp") |
558 | fighting = True | 644 | fighting = True |
... | @@ -560,6 +646,8 @@ if __name__ == "__main__": | ... | @@ -560,6 +646,8 @@ if __name__ == "__main__": |
560 | actions = battle_arena.step() | 646 | actions = battle_arena.step() |
561 | time.sleep(2) | 647 | time.sleep(2) |
562 | for action in actions: | 648 | for action in actions: |
649 | if isinstance(action, MissAction): | ||
650 | print("{} {} {}.".format(action.attacker.monster_type, action.message, action.target.monster_type)) | ||
563 | if isinstance(action, AttackAction): | 651 | if isinstance(action, AttackAction): |
564 | print("{} {} {} for {}.".format(action.attacker.monster_type, action.message, action.target.monster_type, action.damage)) | 652 | print("{} {} {} for {}.".format(action.attacker.monster_type, action.message, action.target.monster_type, action.damage)) |
565 | if isinstance(action, DefeatAction): | 653 | if isinstance(action, DefeatAction): | ... | ... |
-
Please register or sign in to post a comment