2023-06-30 20:32:58 +00:00
import sys , argparse , copy , os , datetime
2023-06-28 15:36:32 +00:00
from bs4 import BeautifulSoup
2023-06-30 02:37:25 +00:00
char_skills = {
2023-06-30 04:59:23 +00:00
1 : " Piloting " , # Likely deprecated
2023-06-30 02:37:25 +00:00
2 : " Mining " ,
3 : " Botany " ,
4 : " Construction " ,
5 : " Industry " ,
6 : " Medical " ,
7 : " Gunner " ,
8 : " Shielding " ,
9 : " Operations " ,
10 : " Weapons " ,
2023-06-30 04:59:23 +00:00
11 : " Unknown-1 " ,
12 : " Logistics " , # All characters seem to have this but it doesn't show up in the UI
13 : " Unknown-2-enigma " , # All characters seem to have this skill but what is it for?
2023-06-30 02:37:25 +00:00
14 : " Navigation " ,
2023-06-30 04:59:23 +00:00
15 : " Unknown-3 " ,
2023-06-30 02:37:25 +00:00
16 : " Research " ,
2023-06-30 04:59:23 +00:00
22 : " Piloting " , # Appears to be the new piloting code?
2023-06-30 02:37:25 +00:00
}
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 ,
}
2023-06-28 23:58:33 +00:00
class ItemCodeDatabase :
def __init__ ( self , database_filename ) :
2023-06-30 02:37:25 +00:00
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
2023-06-28 23:58:33 +00:00
def get_name_from_code ( self , code ) :
2023-06-30 02:37:25 +00:00
return self . id_dict [ code ]
2023-06-28 23:58:33 +00:00
def validate_code ( self , code ) :
2023-06-30 02:37:25 +00:00
return code in self . id_dict
2023-06-28 23:58:33 +00:00
# A single item with its code, name, and quantity
class Item :
def __init__ ( self , code , name , quantity ) :
self . code = code
self . name = name
self . quantity = quantity
# A single storage area, with a list of contents (Items)
class StorageArea :
2023-06-30 02:37:25 +00:00
def __init__ ( self , tag ) :
self . tag = tag
self . items = [ ]
2023-06-28 23:58:33 +00:00
def add_item ( self , item ) :
2023-06-30 02:37:25 +00:00
self . items . append ( item )
2023-06-28 23:58:33 +00:00
# Returns how full the storage area is based on its contents
2023-06-30 02:37:25 +00:00
def get_total_occupancy ( self ) :
total_quantity = 0
for item in self . items :
total_quantity + = item . quantity
return total_quantity
2023-06-28 23:58:33 +00:00
class Character :
2023-06-30 02:37:25 +00:00
def __init__ ( self , name , tag ) :
2023-06-28 23:58:33 +00:00
self . name = name
2023-06-30 02:37:25 +00:00
self . tag = tag
2023-06-30 05:13:59 +00:00
self . is_clone = False
2023-06-28 23:58:33 +00:00
2023-06-30 04:59:23 +00:00
self . skills = [ ]
self . attributes = [ ]
2023-06-28 23:58:33 +00:00
2023-06-30 02:37:25 +00:00
def set_skills ( self , skill_list ) :
2023-06-30 04:59:23 +00:00
# Expected format is a list of dictionaries
# Each dictionary has keys id, mxn, exp, expd, level
2023-06-30 02:37:25 +00:00
self . skills = skill_list
def set_attributes ( self , attribute_list ) :
2023-06-30 04:59:23 +00:00
# Expected format is a list of dictionaries
# Each dictionary has keys id, points
2023-06-30 02:37:25 +00:00
self . attributes = attribute_list
2023-06-28 23:58:33 +00:00
def maximize_skills ( self ) :
2023-06-30 04:59:23 +00:00
# Max LEVEL is 5
# Max MXN should be 8 for some reason
# Exp* keys are probably for a future experience system but I don't know how they work so I won't touch them
for skill in self . skills :
skill [ ' level ' ] = 5
skill [ ' mxn ' ] = 8
2023-06-28 23:58:33 +00:00
def maximize_attributes ( self ) :
2023-06-30 04:59:23 +00:00
# Max POINTS is 6
for attribute in self . attributes :
attribute [ ' points ' ] = 6
2023-06-28 23:58:33 +00:00
2023-06-30 02:37:25 +00:00
def clone ( self , new_name ) :
2023-06-30 04:59:23 +00:00
# How to deep copy the skills/attributes appropriately?
2023-06-30 05:13:59 +00:00
new_char = Character ( new_name , copy . copy ( self . tag ) )
new_char . is_clone = True
2023-06-30 06:50:42 +00:00
new_char . tag [ ' name ' ] = new_name
2023-06-30 05:13:59 +00:00
new_skills = [ s . copy ( ) for s in self . skills ]
new_attributes = [ a . copy ( ) for a in self . attributes ]
new_char . skills = new_skills
new_char . attributes = new_attributes
return new_char
2023-06-30 02:37:25 +00:00
2023-06-30 04:59:23 +00:00
def print_summary ( self ) :
print ( " Name: {} " . format ( self . name ) )
2023-06-30 06:37:37 +00:00
print ( )
2023-06-30 04:59:23 +00:00
print ( " Skills: " )
for skill in self . skills :
print ( " {} : {} " . format ( char_skills [ skill [ ' id ' ] ] , skill [ ' level ' ] ) )
print ( )
print ( " Attributes: " )
for attribute in self . attributes :
print ( " {} : {} " . format ( char_attributes [ attribute [ ' id ' ] ] , attribute [ ' points ' ] ) )
2023-06-30 02:37:25 +00:00
def __repr__ ( self ) :
2023-06-30 04:59:23 +00:00
return " {} - Skills: {} - Attributes: {} " . format ( self . name , repr ( self . skills ) , repr ( self . attributes ) )
2023-06-30 02:37:25 +00:00
class Ship :
def __init__ ( self , name , owner , state , tag ) :
self . name = name
self . owner = owner
self . state = state
self . tag = tag # Soup tag corresponding to this ship's node
self . storage_areas = [ ]
self . characters = [ ]
def add_storage_area ( self , storage_area ) :
self . storage_areas . append ( storage_area )
def add_character ( self , character ) :
self . characters . append ( character )
2023-06-30 05:48:37 +00:00
def add_item ( self , item ) :
min_storage_area = self . storage_areas [ 0 ]
min_occupancy = min_storage_area . get_total_occupancy ( )
for storage_area in self . storage_areas :
if storage_area . get_total_occupancy ( ) < min_occupancy :
min_storage_area = storage_area
min_occupancy = min_storage_area . get_total_occupancy ( )
min_storage_area . add_item ( item )
2023-06-30 02:37:25 +00:00
class Player :
2023-06-30 04:59:23 +00:00
def __init__ ( self , currency , tag ) :
2023-06-30 02:37:25 +00:00
self . currency = currency
2023-06-30 04:59:23 +00:00
self . tag = tag
2023-06-30 02:37:25 +00:00
class GameData :
def __init__ ( self , soup , item_database ) :
self . player = None
self . ships = [ ]
self . soup = soup
self . item_database = item_database
def populate ( self ) :
# Step 1 - Player data
char_tag = self . soup . find ( ' playerBank ' )
2023-06-30 05:48:37 +00:00
currency = int ( char_tag [ ' ca ' ] )
2023-06-30 04:59:23 +00:00
self . player = Player ( currency , char_tag )
2023-06-30 02:37:25 +00:00
# Step 2 - Ship data
ship_tags = self . soup . find_all ( ' ship ' )
for ship_tag in ship_tags :
2023-06-30 20:32:58 +00:00
# Something strange is happening here
# In some unexplored ships/derelicts (?fog="true" in the tag) the name appears in the game but NOWHERE in the file
ship_name = " UNNAMED (?fogged) "
if ship_tag . has_attr ( ' sname ' ) :
ship_name = ship_tag [ ' sname ' ]
# print(ship_name)
2023-06-30 02:37:25 +00:00
owner_node = ship_tag . find ( ' settings ' , owner = True )
ship_owner = owner_node [ ' owner ' ]
ship_state = owner_node [ ' state ' ]
ship = Ship ( ship_name , ship_owner , ship_state , ship_tag )
self . ships . append ( ship )
# Step 3 - Storage area data
for inv_tag in ship_tag . find_all ( ' feat ' , eatAllowed = True ) :
2023-06-30 04:59:23 +00:00
storage_area = StorageArea ( inv_tag . find ( ' inv ' ) )
2023-06-30 02:37:25 +00:00
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_quantity = int ( s_tag [ ' inStorage ' ] )
item = Item ( item_code , item_name , item_quantity )
storage_area . add_item ( item )
# print("{:4}: {} - {}".format(item_code, item_name, item_quantity))
# Step 4 - Character data
for character_list in ship_tag . find_all ( ' characters ' ) :
character_tags = character_list . find_all ( ' c ' , attrs = { ' name ' : True } )
for character_tag in character_tags :
char_name = character_tag [ ' name ' ]
character = Character ( char_name , character_tag )
ship . add_character ( character )
skills = [ ]
skill_tag = character_tag . find ( ' skills ' )
for sk_tag in skill_tag . find_all ( ' s ' ) :
skill_id = sk_tag [ ' sk ' ]
skill_level = sk_tag [ ' level ' ]
skill_mxn = sk_tag [ ' mxn ' ]
skill_exp = sk_tag [ ' exp ' ]
skill_expd = sk_tag [ ' expd ' ]
skill_dict = {
' id ' : int ( skill_id ) ,
' level ' : int ( skill_level ) ,
' mxn ' : int ( skill_mxn ) ,
' exp ' : int ( skill_exp ) ,
' expd ' : int ( skill_expd ) ,
}
skills . append ( skill_dict )
character . set_skills ( skills )
attributes = [ ]
attribute_tag = character_tag . find ( ' attr ' )
for a_tag in attribute_tag . find_all ( ' a ' ) :
attribute_id = a_tag [ ' id ' ]
attribute_points = a_tag [ ' points ' ]
attribute_dict = {
' id ' : int ( attribute_id ) ,
' points ' : int ( attribute_points ) ,
}
attributes . append ( attribute_dict )
character . set_attributes ( attributes )
def writeback ( self ) :
2023-06-30 04:59:23 +00:00
def replace_id ( dict , old_key , new_key ) :
dict_copy = dict . copy ( )
dict_copy [ new_key ] = dict_copy [ old_key ]
del dict_copy [ old_key ]
return dict_copy
2023-06-30 05:13:59 +00:00
2023-06-30 02:37:25 +00:00
# Purpose of this mission is to take all our data and replace the relevant parts of the soup
# Suspect this may be harder than it sounds - original saved game editor more or less deleted and rewrote some sections (e.g. item lists)
2023-06-30 04:59:23 +00:00
# Shouldn't need to update player tag as this will be done directly
# Only need to update things with structure / lists
"""
Step 1 - Update characters
Step 2 - Update storage areas
"""
# Step 1 - Update characters
# Names etc will be done automatically - just need to reconstruct skills and attributes
2023-06-30 05:48:37 +00:00
self . player . tag [ ' ca ' ] = self . player . currency
2023-06-30 04:59:23 +00:00
for ship in self . ships :
for character in ship . characters :
2023-06-30 05:13:59 +00:00
# Cloned character tags have to be added to the list
if character . is_clone :
2023-06-30 06:50:42 +00:00
print ( " ADDING CLONED CHARACTER " )
2023-06-30 05:13:59 +00:00
charlist_tag = ship . tag . find ( ' characters ' )
charlist_tag . append ( character . tag )
2023-06-30 04:59:23 +00:00
skill_tag = character . tag . find ( ' skills ' )
skill_tag . clear ( )
for skill in character . skills :
skill_copy = replace_id ( skill , ' id ' , ' sk ' )
new_tag = self . soup . new_tag ( ' s ' , attrs = skill_copy )
skill_tag . append ( new_tag )
attribute_tag = character . tag . find ( ' attr ' )
attribute_tag . clear ( )
for attribute in character . attributes :
new_tag = self . soup . new_tag ( ' a ' , attrs = attribute )
attribute_tag . append ( new_tag )
for storage_area in ship . storage_areas :
area_tag = storage_area . tag
area_tag . clear ( )
for item in storage_area . items :
tag_dict = { ' elementaryId ' : item . code , ' inStorage ' : item . quantity , ' onTheWayIn ' : 0 , ' onTheWayOut ' : 0 }
new_tag = self . soup . new_tag ( ' s ' , attrs = tag_dict )
area_tag . append ( new_tag )
2023-06-30 05:48:37 +00:00
def add_item ( self , item_code , item_quantity ) :
item_name = self . item_database . get_name_from_code ( item_code )
item = Item ( item_code , item_name , item_quantity )
for ship in self . ships :
if ship . owner == " Player " :
ship . add_item ( item )
break
def buff_characters ( self ) :
for ship in self . ships :
if ship . owner == " Player " :
for character in ship . characters :
character . maximize_skills ( )
character . maximize_attributes ( )
def add_currency ( self , amount ) :
self . player . currency + = amount
2023-06-30 06:50:42 +00:00
def clone_character ( self , character_name , new_name ) :
for ship in self . ships :
for character in ship . characters :
if character . name == character_name :
new_char = character . clone ( new_name )
ship . characters . append ( new_char )
return
2023-06-30 06:09:15 +00:00
def print_detailed_character_summary ( self ) :
for ship in self . ships :
2023-06-30 06:37:37 +00:00
if len ( ship . characters ) == 0 :
print ( " Ship {} (owned by {} , state {} ) has no characters, skipping... " . format ( ship . name , ship . owner , ship . state ) )
print ( )
continue
print ( " Listing characters for ship {} (owned by {} , state {} ): " . format ( ship . name , ship . owner , ship . state ) )
print ( ' ----- ' )
2023-06-30 06:09:15 +00:00
for character in ship . characters :
character . print_summary ( )
2023-06-30 06:37:37 +00:00
print ( ' ----- ' )
print ( )
def print_detailed_item_summary ( self ) :
for ship in self . ships :
if len ( ship . storage_areas ) == 0 :
print ( " Ship {} (owned by {} , state {} ) has no storage areas, skipping... " . format ( ship . name , ship . owner , ship . state ) )
print ( )
continue
print ( " Inventory for ship {} (owned by {} , state {} ) " . format ( ship . name , ship . owner , ship . state ) )
for index , storage_area in enumerate ( ship . storage_areas ) :
if len ( storage_area . items ) == 0 :
print ( " Storage area {} is empty. " . format ( index ) )
continue
print ( " Storage area {} : " . format ( index ) )
for item in storage_area . items :
print ( " {:4} : {} - {} " . format ( item . code , item . name , item . quantity ) )
print ( )
print ( )
2023-06-30 06:09:15 +00:00
2023-06-30 02:37:25 +00:00
def print_summary ( self ) :
print ( " Start game summary: " )
print ( " Player currency: {} " . format ( self . player . currency ) )
print ( " Number of ships: {} " . format ( len ( self . ships ) ) )
for ship in self . ships :
print ( " {} (owner {} , state {} ) " . format ( ship . name , ship . owner , ship . state ) )
print ( " Contains {} storage area(s): " . format ( len ( ship . storage_areas ) ) )
for index , storage_area in enumerate ( ship . storage_areas ) :
print ( " Storage area {} - contains {} item(s) - occupancy {} unit(s) " . format ( index , len ( storage_area . items ) , storage_area . get_total_occupancy ( ) ) )
print ( " Has {} character(s): " . format ( len ( ship . characters ) ) )
for char in ship . characters :
print ( " {} " . format ( char . name ) )
2023-06-30 06:09:15 +00:00
# char.print_summary()
2023-06-30 02:37:25 +00:00
2023-06-28 23:58:33 +00:00
2023-06-28 15:36:32 +00:00
def characters ( soup ) :
for character in soup . find_all ( ' characters ' ) :
c_elems = character . find_all ( ' c ' )
if len ( c_elems ) > 0 :
print ( ' Found some appropriate c-tags ' )
for char_c in c_elems :
# print(char_c['name'])
if ' name ' in char_c . attrs :
print ( char_c [ ' name ' ] )
# We have found a character tag!
# ---- SKILL UPRGRADING
skill_tag = char_c . find ( ' skills ' )
print ( skill_tag )
# Experimental changing
for sk_tag in skill_tag . find_all ( ' s ' ) :
sk_tag [ ' level ' ] = ' 5 '
sk_tag [ ' mxn ' ] = ' 8 '
if ' mxp ' in sk_tag . attrs :
sk_tag [ ' mxp ' ] = ' 8 '
print ( skill_tag )
# ---- ATTRIBUTE UPGRADING
attribute_tag = char_c . find ( ' attr ' )
print ( attribute_tag )
for a_tag in attribute_tag . find_all ( ' a ' ) :
a_tag [ ' points ' ] = ' 6 '
print ( attribute_tag )
2023-06-28 23:58:33 +00:00
def inventory ( soup , add_code , add_quantity ) :
2023-06-28 15:36:32 +00:00
# Load tag names first:
id_dict = { }
2023-06-28 23:58:33 +00:00
filename = " item_ids.txt "
2023-06-28 15:36:32 +00:00
for line in open ( filename ) :
result = line . split ( )
code = int ( result [ 0 ] )
name = ' ' . join ( result [ 1 : ] )
# print(code, name)
id_dict [ code ] = name
# print(id_dict)
2023-06-28 23:58:33 +00:00
print ( " You have requested that {} unit(s) of {} be added to existing storage of this item (storage site will be selected at random) " . format ( add_quantity , id_dict [ add_code ] ) )
2023-06-28 15:36:32 +00:00
item_tracking = { }
2023-06-28 16:22:45 +00:00
print ( ' ----- ' )
storage_space_counter = 1
2023-06-28 23:58:33 +00:00
# This line is a hack to prevent finding alien ship inventories
# Unfortunately at the moment it will only likely work if the player has only one ship
# I do not yet know how to fix this problem if the player has a fleet
ship_tag = soup . find ( ' ship ' )
added_quantity = False
for inv_tag in ship_tag . find_all ( ' inv ' ) :
2023-06-28 15:36:32 +00:00
if inv_tag . parent . name != ' feat ' :
continue
2023-06-28 16:22:45 +00:00
print ( ' Storage space {} ' . format ( storage_space_counter ) )
print ( )
2023-06-28 15:36:32 +00:00
quantity_total = 0
for s_tag in inv_tag . find_all ( ' s ' ) :
item_code = int ( s_tag [ ' elementaryId ' ] )
item_quantity = int ( s_tag [ ' inStorage ' ] )
item_name = id_dict [ item_code ]
2023-06-28 16:22:45 +00:00
print ( " {:4} : {} - {} " . format ( item_code , item_name , item_quantity ) )
2023-06-28 23:58:33 +00:00
if item_code == add_code and not added_quantity :
print ( " Updating quantity with requested amount... " )
item_quantity + = add_quantity
s_tag [ ' inStorage ' ] = item_quantity
added_quantity = True
print ( " Item quantity is now {} " . format ( s_tag [ ' inStorage ' ] ) )
2023-06-28 15:36:32 +00:00
quantity_total + = item_quantity
if item_code not in item_tracking :
item_tracking [ item_code ] = item_quantity
else :
item_tracking [ item_code ] = item_tracking [ item_code ] + item_quantity
2023-06-28 16:22:45 +00:00
print ( )
print ( ' Total use of storage space {} : {} ' . format ( storage_space_counter , quantity_total ) )
storage_space_counter + = 1
2023-06-28 15:36:32 +00:00
print ( ' ----- ' )
2023-06-28 15:51:05 +00:00
print ( ' Item total summary: ' )
2023-06-28 16:22:45 +00:00
print ( )
2023-06-28 15:51:05 +00:00
for item in item_tracking . items ( ) :
item_code = item [ 0 ]
item_name = id_dict [ item_code ]
item_quantity = item [ 1 ]
2023-06-28 23:58:33 +00:00
print ( ' {:4} - {} - {} ' . format ( item_code , item_name , item_quantity ) )
2023-06-28 15:51:05 +00:00
2023-06-28 23:58:33 +00:00
def give_money ( soup , amount ) :
bank_tag = soup . find ( ' playerBank ' )
bank_tag [ ' ca ' ] = amount
2023-06-28 15:36:32 +00:00
2023-06-30 02:37:25 +00:00
def list_ships ( soup ) :
ship_tags = soup . find_all ( ' ship ' )
for ship_tag in ship_tags :
ship_name = ship_tag [ ' sname ' ]
"""
settings_nodes = ship_tag . find_all ( ' settings ' )
for settings_node in settings_nodes :
if settings_node . has_attr ( ' owner ' ) :
ship_owner = settings_node [ ' owner ' ]
else :
continue
"""
owner_node = ship_tag . find ( ' settings ' , owner = True )
ship_owner = owner_node [ ' owner ' ]
ship_state = owner_node [ ' state ' ]
print ( ' Ship found: {} owned by {} (state: {} ) ' . format ( ship_name , ship_owner , ship_state ) )
# print(settings_node)
2023-06-30 20:32:58 +00:00
def parse_item_file ( filename ) :
results = [ ]
for line in open ( filename ) :
line = line . strip ( )
if line [ 0 ] == ' # ' :
continue
components = line . split ( )
item_code = int ( components [ 0 ] )
item_quantity = int ( components [ 1 ] )
results . append ( ( item_code , item_quantity ) )
return results
2023-06-30 02:37:25 +00:00
2023-06-28 15:36:32 +00:00
def main ( ) :
2023-06-28 16:22:45 +00:00
parser = argparse . ArgumentParser ( prog = " Space Haven Saved Game Inspector " , description = " As above. " )
parser . add_argument ( ' filename ' )
2023-06-28 23:58:33 +00:00
parser . add_argument ( ' --add_item ' , required = False , metavar = ' N ' , type = int , nargs = 2 , help = " Add more of an existing item to storage by CODE - refer to accompanying data file reference for codes. First number is the code, second is the desired quantity. " )
parser . add_argument ( ' --buff_chars ' , required = False , action = ' store_true ' , help = " For all characters, increases all skills and attributes to maximum. Use wisely. " )
parser . add_argument ( ' --money ' , required = False , type = int , nargs = 1 , help = " Give the player credits of the specified amount " )
2023-06-30 02:37:25 +00:00
parser . add_argument ( ' --list_ships ' , required = False , action = ' store_true ' , help = " List all ships with names and their respective owners " )
parser . add_argument ( ' --test_gamedata ' , required = False , action = ' store_true ' , help = " Test of new class-based system of storing game information " )
2023-06-30 07:07:33 +00:00
parser . add_argument ( ' --clone_character ' , required = False , type = str , nargs = 2 , help = " Clones a character of one name into another " )
2023-06-30 20:32:58 +00:00
parser . add_argument ( ' --add_item_set ' , required = False , type = str , nargs = 1 , help = " Takes a file containing a list of item codes and quantities (whitespace separated) and adds all of these to player storage " )
parser . add_argument ( ' --detailed_items ' , required = False , action = ' store_true ' , help = ' Print a detailed item listing from player inventory ' )
parser . add_argument ( ' --detailed_chars ' , required = False , action = ' store_true ' , help = ' Print a comprehensive listing of player character details ' )
parser . add_argument ( ' --replace_original ' , required = False , action = ' store_true ' , help = ' Replace original file instead of creating edited alternative. Renames original for backup, but USE WITH CAUTION ' )
2023-06-28 16:22:45 +00:00
args = parser . parse_args ( )
2023-06-28 23:58:33 +00:00
# print(args)
print ( " --- Space Haven Saved Game Inspector --- " )
print ( )
2023-06-28 16:22:45 +00:00
filename = args . filename
2023-06-28 23:58:33 +00:00
# print(filename)
2023-06-28 15:36:32 +00:00
full_text = " "
for line in open ( filename ) :
full_text + = line
# print(full_text)
soup = BeautifulSoup ( full_text , " xml " )
2023-06-30 06:58:40 +00:00
item_code_database = ItemCodeDatabase ( ' item_ids.txt ' )
print ( " Item code database successfully loaded " )
game_data = GameData ( soup , item_code_database )
game_data . populate ( )
2023-06-30 20:54:15 +00:00
edits_made = False
2023-06-30 06:58:40 +00:00
if args . buff_chars :
game_data . buff_characters ( )
2023-06-30 20:54:15 +00:00
edits_made = True
2023-06-30 06:58:40 +00:00
if args . add_item :
game_data . add_item ( args . add_item [ 0 ] , args . add_item [ 1 ] )
2023-06-30 20:54:15 +00:00
edits_made = True
2023-06-30 06:58:40 +00:00
if args . money :
game_data . add_currency ( args . money [ 0 ] )
2023-06-30 20:54:15 +00:00
edits_made = True
2023-06-30 06:58:40 +00:00
if args . list_ships :
game_data . print_summary ( )
2023-06-30 07:07:33 +00:00
if args . clone_character :
game_data . clone_character ( args . clone_character [ 0 ] , args . clone_character [ 1 ] )
2023-06-30 20:54:15 +00:00
edits_made = True
2023-06-30 07:07:33 +00:00
2023-06-30 20:32:58 +00:00
if args . add_item_set :
item_list = parse_item_file ( args . add_item_set [ 0 ] )
# 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 ) )
game_data . add_item ( item_code , item_quantity )
2023-06-30 20:54:15 +00:00
edits_made = True
2023-06-30 06:58:40 +00:00
2023-06-30 20:32:58 +00:00
if args . detailed_items :
game_data . print_detailed_item_summary ( )
2023-06-28 23:58:33 +00:00
2023-06-30 20:32:58 +00:00
if args . detailed_chars :
game_data . print_detailed_character_summary ( )
2023-06-28 23:58:33 +00:00
2023-06-30 20:32:58 +00:00
game_data . writeback ( )
2023-06-28 15:36:32 +00:00
2023-06-30 02:37:25 +00:00
if args . test_gamedata :
item_code_database = ItemCodeDatabase ( ' item_ids.txt ' )
print ( " Item code database successfully loaded " )
game_data = GameData ( soup , item_code_database )
game_data . populate ( )
2023-06-30 06:37:37 +00:00
# game_data.add_item(1759, 100)
# game_data.buff_characters()
# game_data.add_currency(10000)
2023-06-30 02:37:25 +00:00
game_data . print_summary ( )
2023-06-30 20:32:58 +00:00
game_data . print_detailed_item_summary ( )
# game_data.clone_character("Byron", "Anthony")
# game_data.print_detailed_character_summary()
2023-06-30 04:59:23 +00:00
game_data . writeback ( )
2023-06-30 02:37:25 +00:00
2023-06-30 20:54:15 +00:00
if edits_made :
if args . replace_original :
print ( ' Renaming original file ' )
datetime_suffix = datetime . datetime . now ( ) . strftime ( ' % Y- % m- %d - % H % M_ % S_ %f ' )
new_filename = args . filename + " - " + datetime_suffix
# print(datetime_suffix)
os . rename ( args . filename , new_filename )
print ( ' Now rewriting game file with new information ' )
text = soup . prettify ( )
# Delete XML header - game doesn't have it
sansfirstline = ' \n ' . join ( text . split ( ' \n ' ) [ 1 : ] )
f = open ( args . filename , ' w ' )
f . write ( sansfirstline )
f . close ( )
print ( ' Complete. ' )
else :
text = soup . prettify ( )
# Delete XML header - game doesn't have it
sansfirstline = ' \n ' . join ( text . split ( ' \n ' ) [ 1 : ] )
f = open ( ' game.xml ' , ' w ' )
f . write ( sansfirstline )
f . close ( )
2023-06-28 15:36:32 +00:00
if __name__ == " __main__ " :
main ( )