aboutsummaryrefslogtreecommitdiff
path: root/srb_lib.py
diff options
context:
space:
mode:
Diffstat (limited to 'srb_lib.py')
-rw-r--r--srb_lib.py98
1 files changed, 94 insertions, 4 deletions
diff --git a/srb_lib.py b/srb_lib.py
index f3a1deb..dc69614 100644
--- a/srb_lib.py
+++ b/srb_lib.py
@@ -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. """
bgstack15