diff --git a/char_conditions.tsv b/char_conditions.tsv index 7bf7d9f..9907652 100644 --- a/char_conditions.tsv +++ b/char_conditions.tsv @@ -94,4 +94,6 @@ 2728 Wound 2729 Monster bite 2798 Received an electric shock -2843 I was held as a slave \ No newline at end of file +2843 I was held as a slave +3311 Sleeping comfortably +3327 No entertainment \ No newline at end of file diff --git a/sheditor.py b/sheditor.py index 201198c..f16dea5 100644 --- a/sheditor.py +++ b/sheditor.py @@ -2,6 +2,7 @@ import argparse import copy import os import datetime +import csv from bs4 import BeautifulSoup import rich @@ -16,83 +17,32 @@ storage_ids = { 3062: {"name": "Body storage", "capacity": 20}, } -char_skills = { - 1: "Piloting", # Likely deprecated - now using code 22 - 2: "Mining", - 3: "Botany", - 4: "Construction", - 5: "Industry", - 6: "Medical", - 7: "Gunner", - 8: "Shielding", - 9: "Operations", - 10: "Weapons", - 11: "Unknown-11", - 12: "Logistics", # All characters seem to have this but it doesn't show up in the UI - 13: "Unknown-13", # All characters seem to have this skill but what is it for? - 14: "Navigation", - 15: "Unknown-15", - 16: "Research", - 22: "Piloting", # Appears to be the new piloting code? -} - -char_attributes = { - 210: "Bravery", - 214: "Preception", - 213: "Intelligence", - 212: "Zest", -} - -char_traits = { - "Iron Stomach": 1533, - "Spacefarer": 1045, - "Confident": 1046, - "Hard Working": 1041, - "Antisocial": 1037, - "Nyctophilia": 1534, - "Wimp": 655, - "Clumsy": 656, - "Charming": 1048, - "Bloodlust": 1036, - "Fast Learner": 1039, - "Minimalist": 1535, - "Lazy": 1040, - "Neurotic": 1047, - "Alien Lover": 2082, - "Needy": 1038, - "Peace-loving": 1043, - "Suicidal": 1034, - "Smart": 1035, - "Psychopath": 1042, - "Hero": 191, - "Talkative": 1560, - "Iron-Willed": 1044, - "Gourmand": 1562, -} - - -class ItemCodeDatabase: - - def __init__(self, database_filename): - self.id_dict = {} - - for line in open(database_filename): - result = line.split() - code = int(result[0]) - name = ' '.join(result[1:]) - # print(code, name) - self.id_dict[code] = name - - def get_name_from_code(self, code): - return self.id_dict[code] - - def validate_code(self, code): - return code in self.id_dict - # A single item with its code, name, and quantity class Item: + item_ids = None + + @classmethod + def load_ids(cls, item_filename): + if cls.item_ids is not None: + return + else: + cls.item_ids = {} + + with open(item_filename, 'r') as item_file: + item_reader = csv.reader(item_file, delimiter='\t') + for row in item_reader: + cls.item_ids[int(row[0])] = row[1].strip() + + @classmethod + def get_name_from_code(cls, code): + return cls.item_ids.get(code, None) if cls.item_ids is not None else None + + @classmethod + def validate_code(cls, code): + return code in cls.id_dict if cls.item_ids is not None else False + def __init__(self, code, name, quantity): self.code = code self.name = name @@ -106,7 +56,7 @@ class StorageArea: self.tag = tag self.type_id = None self.items = [] - self.is_abnormal_storage = False + self.is_normal_storage = False def add_item(self, item): self.items.append(item) @@ -121,6 +71,58 @@ class StorageArea: class Character: + skill_ids = None + attribute_ids = None + trait_ids = None + condition_ids = None + + @classmethod + def load_ids(cls, skill_filename, attribute_filename, trait_filename, condition_filename): + if cls.skill_ids is None: + cls.skill_ids = {} + with open(skill_filename, 'r') as skill_file: + skill_reader = csv.reader(skill_file, delimiter='\t') + for row in skill_reader: + cls.skill_ids[int(row[0])] = row[1].strip() + + if cls.attribute_ids is None: + cls.attribute_ids = {} + with open(attribute_filename, 'r') as attribute_file: + attribute_reader = csv.reader(attribute_file, delimiter='\t') + for row in attribute_reader: + cls.attribute_ids[int(row[0])] = row[1].strip() + + if cls.trait_ids is None: + cls.trait_ids = {} + with open(trait_filename, 'r') as trait_file: + trait_reader = csv.reader(trait_file, delimiter='\t') + for row in trait_reader: + print(row) + cls.trait_ids[int(row[0])] = row[1].strip() + + if cls.condition_ids is None: + cls.condition_ids = {} + with open(condition_filename, 'r') as condition_file: + condition_reader = csv.reader(condition_file, delimiter='\t') + for row in condition_reader: + cls.condition_ids[int(row[0])] = row[1].strip() + + @classmethod + def get_skill_from_code(cls, code): + return cls.skill_ids.get(code, None) if cls.skill_ids is not None else None + + @classmethod + def get_attribute_from_code(cls, code): + return cls.attribute_ids.get(code, None) if cls.attribute_ids is not None else None + + @classmethod + def get_trait_from_code(cls, code): + return cls.trait_ids.get(code, None) if cls.trait_ids is not None else None + + @classmethod + def get_condition_from_code(cls, code): + return cls.condition_ids.get(code, None) if cls.condition_ids is not None else None + def __init__(self, name, tag): self.name = name self.tag = tag @@ -170,7 +172,7 @@ class Character: console.print() console.print("Skills:") for i, skill in enumerate(self.skills): - row_string = "{:12} [bright_cyan]{:2}[/]".format(char_skills[skill['id']], skill['level']) + row_string = "{:12} [bright_cyan]{:2}[/]".format(Character.get_skill_from_code(skill['id']), skill['level']) if i % 2 == 0: console.print(" [on #222222]{}[/]".format(row_string)) else: @@ -178,7 +180,7 @@ class Character: console.print() console.print("Attributes:") for i, attribute in enumerate(self.attributes): - row_string = "{:12} [bright_cyan]{:2}[/]".format(char_attributes[attribute['id']], attribute['points']) + row_string = "{:12} [bright_cyan]{:2}[/]".format(Character.get_attribute_from_code(attribute['id']), attribute['points']) if i % 2 == 0: console.print(" [on #222222]{}[/]".format(row_string)) else: @@ -206,7 +208,7 @@ class Ship: self.characters.append(character) def add_item(self, item): - normal_storage_areas = [sa for sa in self.storage_areas if not sa.is_abnormal_storage] + normal_storage_areas = [sa for sa in self.storage_areas if sa.is_normal_storage] min_storage_area = normal_storage_areas[0] min_occupancy = min_storage_area.get_total_occupancy() for storage_area in normal_storage_areas: @@ -225,12 +227,11 @@ class Player: class GameData: - def __init__(self, soup, item_database): + def __init__(self, soup): self.player = None self.ships = [] self.soup = soup - self.item_database = item_database def populate(self): # Step 1 - Player data @@ -262,14 +263,12 @@ class GameData: storage_area = StorageArea(inv_tag.find('inv')) # 632 is the "m" id code for LARGE storage storage_area.type_id = int(inv_tag.parent.parent['m']) - if storage_area.type_id not in normal_storage_ids: # TODO: Un-hardcode this AND take into account SMALL storage - # rich.print("[on #222222]Found abnormal storage id [#666666]{}[/][/]".format(inv_tag.parent.parent['m'])) - storage_area.is_abnormal_storage = True + storage_area.is_normal_storage = storage_area.type_id in normal_storage_ids ship.add_storage_area(storage_area) # Items within storage area for s_tag in inv_tag.find_all('s'): item_code = int(s_tag['elementaryId']) - item_name = self.item_database.get_name_from_code(item_code) + item_name = Item.get_name_from_code(item_code) item_quantity = int(s_tag['inStorage']) item = Item(item_code, item_name, item_quantity) storage_area.add_item(item) @@ -420,7 +419,7 @@ class GameData: continue for index, storage_area in enumerate(ship.storage_areas): - console.print(" Storage area [bright_cyan]{}[/] (type: [bright_cyan]{}[/], abnormal storage: [bright_cyan]{}[/]):".format(index, storage_ids[storage_area.type_id]["name"], storage_area.is_abnormal_storage)) + console.print(" Storage area [bright_cyan]{}[/] (type: [bright_cyan]{}[/], normal storage: [bright_cyan]{}[/]):".format(index, storage_ids[storage_area.type_id]["name"], storage_area.is_normal_storage)) if len(storage_area.items) == 0: console.print(" This storage area is empty.") console.print() @@ -632,11 +631,14 @@ def main(): soup = BeautifulSoup(full_text, "xml") - item_code_database = ItemCodeDatabase('item_ids.tsv') + Item.load_ids('item_ids.tsv') print("Item code database successfully loaded.") print() + Character.load_ids('char_skills.tsv', 'char_attributes.tsv', 'char_traits.tsv', 'char_conditions.tsv') + print("Character code database successfully loaded.") + print() - game_data = GameData(soup, item_code_database) + game_data = GameData(soup) game_data.populate() edits_made = False @@ -665,7 +667,7 @@ def main(): # print(item_list) print("Items to be added:") for (item_code, item_quantity) in item_list: - print("{} : {}".format(item_code_database.get_name_from_code(item_code), item_quantity)) + print("{} : {}".format(Item.get_name_from_code(item_code), item_quantity)) game_data.add_item(item_code, item_quantity) edits_made = True @@ -678,7 +680,7 @@ def main(): game_data.writeback() if args.test_gamedata: - game_data = GameData(soup, item_code_database) + game_data = GameData(soup) game_data.populate() # game_data.add_item(1759, 100) # game_data.buff_characters()