diff options
Diffstat (limited to 'srb_lib.py')
-rw-r--r-- | srb_lib.py | 98 |
1 files changed, 94 insertions, 4 deletions
@@ -29,6 +29,11 @@ PROFILE_START_POSITION = [0, 0x10, 0x142C, 0x2848] POS_MONEY = 0x270 POS_EQUIPPED_WEAPON = 0x284 +# stinger purchased is relative 0x28C, value 0x40 (b01000000) or 64 +# water-balloon-gun is relative 0x2D, value 0x0001 +# stinger and potato gun is relative 0x28C, value 0x60, so potato gun is (b00100000) or 64 +#POS_STINGER = 0x028C + WEAPONS = [ "undefined", # 0x0 "undefined", # secondary weapon is a single machine gun?! @@ -48,6 +53,57 @@ WEAPONS = [ "undefined", # 0xF ] +# WORKHERE: position is for where the balloon info is stored for this levelset, if it is stored here and not per-level. +LEVELSETS = [ + {"id":0,"name":"Aerodrome Island","pos":0x0}, + {"id":1,"name":"Woods of Montsec","pos":0x0}, + {"id":2,"name":"Front Lines of Verdon","pos":0x0}, + {"id":3,"name":"Mines of the Matterhorn","pos":0x0}, + {"id":4,"name":"Verdon Gorge","pos":0x0}, + {"id":5,"name":"Flying Fortress","pos":0x0}, +] + +# relative to player profile +POS_LEVEL_START = 0x2D8 +# each level position is POS_LEVEL_START + (4*level["pos_r"]) +# the relative position is because each level set gets 7 (or 6 plus 1 blank) slots, but not all levelsets have 6 levels. +LEVELS = [ + {"id":0, "pos_r":0, "setid":0,"name":"Defend Island"}, + {"id":1, "pos_r":1, "setid":0,"name":"Recover Plans"}, + {"id":2, "pos_r":2, "setid":0,"name":"Protect the Trucks"}, + {"id":3, "pos_r":3, "setid":0,"name":"Attack of the U-Boats"}, + {"id":4, "pos_r":4, "setid":0,"name":"Cripple Outpost Island"}, + {"id":5, "pos_r":5, "setid":0,"name":"Sink the Battleship"}, + {"id":6, "pos_r":7, "setid":1,"name":"Rerun's Challenge"}, + {"id":7, "pos_r":8, "setid":1,"name":"Eliminate Tree Village"}, + {"id":8, "pos_r":9, "setid":1,"name":"Tree Chopper"}, + {"id":9, "pos_r":14,"setid":2,"name":"Trench Warfare"}, + {"id":10,"pos_r":15,"setid":2,"name":"Recover Allied Base"}, + {"id":11,"pos_r":16,"setid":2,"name":"Giant Tank"}, + {"id":12,"pos_r":21,"setid":3,"name":"Surprise Attack"}, + {"id":13,"pos_r":22,"setid":3,"name":"Derail the Train"}, + {"id":14,"pos_r":23,"setid":3,"name":"Enter the Mines"}, + {"id":15,"pos_r":24,"setid":3,"name":"Explore the Mines"}, + {"id":16,"pos_r":25,"setid":3,"name":"Destroy Driller Boss"}, + {"id":17,"pos_r":28,"setid":4,"name":"Navigate the Canyon"}, + {"id":18,"pos_r":29,"setid":4,"name":"Destroy Circus City"}, + {"id":19,"pos_r":30,"setid":4,"name":"Circus Aircraft Carrier"}, + {"id":20,"pos_r":35,"setid":5,"name":"Rescue Allies"}, + {"id":21,"pos_r":36,"setid":5,"name":"Battle the Red Baron"} +] + +# hex values +# WOKRHERE: profile 2 level statuses are off somehow?! they are 4 bytes closer to front than the calculation shows. +LEVEL_STATUSES = { + "59": "all-balloons,all-letters,sergeant", + "5B": "all-balloons,all-letters,colonel", + "5D": "all-balloons,all-letters,colonel", + "60": "all-balloons,all-letters,colonel", + "62": "all-balloons,all-letters,colonel", + "63": "all-balloons,all-letters,colonel", + "64": "all-balloons,all-letters,general" +} + # DEFINE FUNCTIONS def ferror(*args, **kwargs): print(*args, file=sys.stderr, **kwargs) @@ -196,12 +252,46 @@ def get_weapon_info(weapon): except: return -1, f"cannot find weapon {weapon}" # must be an incorrect name elif type(weapon) == int: - if weapon not in range(0,16): + if weapon in range(0,16): + return weapon, WEAPONS[weapon] + else: return -1, f"invalid index {weapon}; use 0-15" # must be <0 or >15 + return -1, f"invalid way to reference weapon: [{type(weapon)}]. Use index or name." + +def get_level_status(data_object,profile_id,level): + """ WORKHERE: not sure how to use this, but making sure my position in the data works. """ + data = _get_data_from_data_object(data_object) + level_obj, message = get_level_info(level) + if message != "valid" or level == -1: + ferror(f"Unable to get level status for {level}.") + print(f"Debug: got level_obj {level_obj} and message {message}") + profile_level_status = data[PROFILE_START_POSITION[profile_id]+POS_LEVEL_START+(4*level_obj["pos_r"])] + # it comes back as an int, but does it look better as a hex? + return hex(profile_level_status) + +def get_level_info(level): + """ Returns dictionary of level from LEVELS, searching by id or name. """ + try: + # if it is an integer, make sure it shows up as one in the next check + level = int(level) + except: + pass + if type(level) == str: + try: + level = [i for i in LEVELS if i["name"].lower() == level.lower()][0] + return level, "valid" + except: + return -1, f"cannot find level {level}" + elif type(level) == int: + if level in range(0,len(LEVELS)+1): + try: + level = [i for i in LEVELS if i["id"] == level][0] + return level, "valid" + except: + return -1, f"cannot find level by id {level}" else: - return weapon, WEAPONS[weapon] - else: - return -1, f"invalid way to reference weapon: [{type(weapon)}]. Use index or name." + return -1, f"invalid level index {level}; use 0-{len(LEVELS)}" + return -1, f"invalid way to reference level: [{type(level)}]. Use id or name." def calculate_checksum(data): """ Return the 4-byte checksum used by the game for the provided data. """ |