Updated to use external tsv files for ids.
This commit is contained in:
parent
6e0ceaf239
commit
13073df432
|
@ -94,4 +94,6 @@
|
||||||
2728 Wound
|
2728 Wound
|
||||||
2729 Monster bite
|
2729 Monster bite
|
||||||
2798 Received an electric shock
|
2798 Received an electric shock
|
||||||
2843 I was held as a slave
|
2843 I was held as a slave
|
||||||
|
3311 Sleeping comfortably
|
||||||
|
3327 No entertainment
|
|
178
sheditor.py
178
sheditor.py
|
@ -2,6 +2,7 @@ import argparse
|
||||||
import copy
|
import copy
|
||||||
import os
|
import os
|
||||||
import datetime
|
import datetime
|
||||||
|
import csv
|
||||||
from bs4 import BeautifulSoup
|
from bs4 import BeautifulSoup
|
||||||
|
|
||||||
import rich
|
import rich
|
||||||
|
@ -16,83 +17,32 @@ storage_ids = {
|
||||||
3062: {"name": "Body storage", "capacity": 20},
|
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
|
# A single item with its code, name, and quantity
|
||||||
class Item:
|
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):
|
def __init__(self, code, name, quantity):
|
||||||
self.code = code
|
self.code = code
|
||||||
self.name = name
|
self.name = name
|
||||||
|
@ -106,7 +56,7 @@ class StorageArea:
|
||||||
self.tag = tag
|
self.tag = tag
|
||||||
self.type_id = None
|
self.type_id = None
|
||||||
self.items = []
|
self.items = []
|
||||||
self.is_abnormal_storage = False
|
self.is_normal_storage = False
|
||||||
|
|
||||||
def add_item(self, item):
|
def add_item(self, item):
|
||||||
self.items.append(item)
|
self.items.append(item)
|
||||||
|
@ -121,6 +71,58 @@ class StorageArea:
|
||||||
|
|
||||||
class Character:
|
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):
|
def __init__(self, name, tag):
|
||||||
self.name = name
|
self.name = name
|
||||||
self.tag = tag
|
self.tag = tag
|
||||||
|
@ -170,7 +172,7 @@ class Character:
|
||||||
console.print()
|
console.print()
|
||||||
console.print("Skills:")
|
console.print("Skills:")
|
||||||
for i, skill in enumerate(self.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:
|
if i % 2 == 0:
|
||||||
console.print(" [on #222222]{}[/]".format(row_string))
|
console.print(" [on #222222]{}[/]".format(row_string))
|
||||||
else:
|
else:
|
||||||
|
@ -178,7 +180,7 @@ class Character:
|
||||||
console.print()
|
console.print()
|
||||||
console.print("Attributes:")
|
console.print("Attributes:")
|
||||||
for i, attribute in enumerate(self.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:
|
if i % 2 == 0:
|
||||||
console.print(" [on #222222]{}[/]".format(row_string))
|
console.print(" [on #222222]{}[/]".format(row_string))
|
||||||
else:
|
else:
|
||||||
|
@ -206,7 +208,7 @@ class Ship:
|
||||||
self.characters.append(character)
|
self.characters.append(character)
|
||||||
|
|
||||||
def add_item(self, item):
|
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_storage_area = normal_storage_areas[0]
|
||||||
min_occupancy = min_storage_area.get_total_occupancy()
|
min_occupancy = min_storage_area.get_total_occupancy()
|
||||||
for storage_area in normal_storage_areas:
|
for storage_area in normal_storage_areas:
|
||||||
|
@ -225,12 +227,11 @@ class Player:
|
||||||
|
|
||||||
class GameData:
|
class GameData:
|
||||||
|
|
||||||
def __init__(self, soup, item_database):
|
def __init__(self, soup):
|
||||||
self.player = None
|
self.player = None
|
||||||
self.ships = []
|
self.ships = []
|
||||||
|
|
||||||
self.soup = soup
|
self.soup = soup
|
||||||
self.item_database = item_database
|
|
||||||
|
|
||||||
def populate(self):
|
def populate(self):
|
||||||
# Step 1 - Player data
|
# Step 1 - Player data
|
||||||
|
@ -262,14 +263,12 @@ class GameData:
|
||||||
storage_area = StorageArea(inv_tag.find('inv'))
|
storage_area = StorageArea(inv_tag.find('inv'))
|
||||||
# 632 is the "m" id code for LARGE storage
|
# 632 is the "m" id code for LARGE storage
|
||||||
storage_area.type_id = int(inv_tag.parent.parent['m'])
|
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
|
storage_area.is_normal_storage = storage_area.type_id in normal_storage_ids
|
||||||
# rich.print("[on #222222]Found abnormal storage id [#666666]{}[/][/]".format(inv_tag.parent.parent['m']))
|
|
||||||
storage_area.is_abnormal_storage = True
|
|
||||||
ship.add_storage_area(storage_area)
|
ship.add_storage_area(storage_area)
|
||||||
# Items within storage area
|
# Items within storage area
|
||||||
for s_tag in inv_tag.find_all('s'):
|
for s_tag in inv_tag.find_all('s'):
|
||||||
item_code = int(s_tag['elementaryId'])
|
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_quantity = int(s_tag['inStorage'])
|
||||||
item = Item(item_code, item_name, item_quantity)
|
item = Item(item_code, item_name, item_quantity)
|
||||||
storage_area.add_item(item)
|
storage_area.add_item(item)
|
||||||
|
@ -420,7 +419,7 @@ class GameData:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
for index, storage_area in enumerate(ship.storage_areas):
|
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:
|
if len(storage_area.items) == 0:
|
||||||
console.print(" This storage area is empty.")
|
console.print(" This storage area is empty.")
|
||||||
console.print()
|
console.print()
|
||||||
|
@ -632,11 +631,14 @@ def main():
|
||||||
|
|
||||||
soup = BeautifulSoup(full_text, "xml")
|
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("Item code database successfully loaded.")
|
||||||
print()
|
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()
|
game_data.populate()
|
||||||
|
|
||||||
edits_made = False
|
edits_made = False
|
||||||
|
@ -665,7 +667,7 @@ def main():
|
||||||
# print(item_list)
|
# print(item_list)
|
||||||
print("Items to be added:")
|
print("Items to be added:")
|
||||||
for (item_code, item_quantity) in item_list:
|
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)
|
game_data.add_item(item_code, item_quantity)
|
||||||
edits_made = True
|
edits_made = True
|
||||||
|
|
||||||
|
@ -678,7 +680,7 @@ def main():
|
||||||
game_data.writeback()
|
game_data.writeback()
|
||||||
|
|
||||||
if args.test_gamedata:
|
if args.test_gamedata:
|
||||||
game_data = GameData(soup, item_code_database)
|
game_data = GameData(soup)
|
||||||
game_data.populate()
|
game_data.populate()
|
||||||
# game_data.add_item(1759, 100)
|
# game_data.add_item(1759, 100)
|
||||||
# game_data.buff_characters()
|
# game_data.buff_characters()
|
||||||
|
|
Loading…
Reference in New Issue