1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
|
#!/usr/bin/env python3
# Startdate: 2024-03-08-6 15:28
# File: srb_lib.py
# Purpose: frontend for srb_lib
# History:
# Usage:
# Reference:
# blog posts 2024-03
# delsum from github
# bgconf.py
# WORKHERE:
# or --set-rank-level 1,general --set-rank-level 1,none --set-rank-level all,general
# or --give-balloons-level 10 --take-balloons-level 11
# or --reset-level 5 (which zeros out all info about completion of that level)
import srb_lib, argparse, sys
from srb_lib import ferror, debuglev
HELP_WEAPONS = ""
for w in srb_lib.WEAPONS:
HELP_WEAPONS += str(w["id"]) + "," + w["name"] + ','
HELP_WEAPONS = HELP_WEAPONS.rstrip(",")
parser = argparse.ArgumentParser(description="Cli tool for manipulating savegame files for srb.exe",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog=f"""LEVELS include {[i['name'] for i in srb_lib.LEVELS]+list(range(0,len(srb_lib.LEVELS)))}
WEAPONS include {HELP_WEAPONS}
NAME_CHARS include "{srb_lib.NAME_CHARS}"
""")
parser.add_argument("-V","--version",action="version",version="%(prog)s " + srb_lib.srb_lib_version)
parser.add_argument("-d","--debug",nargs='?',default=0,type=int,choices=range(0,11),help="Set debug level")
parser.add_argument("--profile",type=int,choices=range(1,4),help="Profile in user menu.")
parser.add_argument("--get-money",action="store_true",help="Print current money for profile.")
parser.add_argument("--set-money",type=int,help="Set money for profile.")
parser.add_argument("--get-weapon",action="store_true",help="Print currently equipped weapon for profile.")
# choices seems to be too strict here for the numbers. We can live with just the
#choices=[i for i in srb_lib.WEAPONS if i != "undefined"]+list(range(0,16))
#parser.add_argument("--set-weapon",choices=[i for i in srb_lib.WEAPONS if i != "undefined"],help="Print currently equipped weapon for profile.")
parser.add_argument("--set-weapon",help="Set currently equipped weapon for profile.")
parser.add_argument("--get-purchased-weapons",action="store_true",help="Print currently purchased weapons for profile.")
parser.add_argument("--add-purchased-weapons",action="append",help="For profile, add these purchased weapons. Can be used multiple times.")
parser.add_argument("--remove-purchased-weapons",action="append",help="For profile, remove (un-buy) these purchased weapons. Can be used multiple times.")
parser.add_argument("--get-purchased-planes",action="store_true",help="Print currently purchased planes for profile.")
parser.add_argument("--add-purchased-planes",action="append",help="For profile, add these purchased planes. Can be used multiple times.")
parser.add_argument("--remove-purchased-planes",action="append",help="For profile, remove (un-buy) these purchased planes. Can be used multiple times.")
parser.add_argument("--get-level",help="Print status for this level for profile.")
parser.add_argument("--get-levelset",help="Print status for this levelset for profile.")
parser.add_argument("--get-name",action="store_true",help="Print name for profile.")
parser.add_argument("--set-name",help="Set name for profile.")
parser.add_argument("--get-profile-in-use",action="store_true",help="Print if profile is in use.")
parser.add_argument("--get-tutorial-completed",action="store_true",help="Print if profile has completed the tutorial.")
parser.add_argument("--set-tutorial-completed",choices=["True","False"],help="Set tutorial-completed for profile.")
parser.add_argument("--get-health",action="store_true",help="Print stat health for profile.")
parser.add_argument("--set-health",type=int,choices=range(1,5),help="Set stat health for profile.")
parser.add_argument("--get-stunt",action="store_true",help="Print stat stunt for profile.")
parser.add_argument("--set-stunt",type=int,choices=range(1,5),help="Set stat stunt for profile.")
parser.add_argument("--get-gun",action="store_true",help="Print stat gun for profile.")
parser.add_argument("--set-gun",type=int,choices=range(1,6),help="Set stat gun for profile.")
parser.add_argument("--checksum",action=argparse.BooleanOptionalAction,default=True,help="Correct checksum. Default is to do this. It happens at the end of everything else.")
parser.add_argument("file",default="Profile 1.sav")
args = parser.parse_args()
debuglevel = 0
if args.debug:
debuglevel = args.debug
if debuglev(1,debuglevel):
ferror("debug level", debuglevel)
if debuglev(8,debuglevel):
ferror(args)
# common parameters
profile_id = args.profile
#print(f"profile_id={profile_id}")
# WORKHERE: new actions that need --profile must be added here.
if not profile_id and (args.get_money or args.set_money or args.get_weapon or args.set_weapon or args.get_level or args.get_name or args.set_name or args.get_profile_in_use or args.get_purchased_weapons or args.get_tutorial_completed or args.add_purchased_weapons or args.remove_purchased_weapons or args.get_health or args.get_stunt or args.get_gun or args.set_health or args.set_stunt or args.set_gun or args.get_levelset or args.get_purchased_planes or args.add_purchased_planes or args.remove_purchased_planes):
ferror("Warning: Cannot perform most actions without --profile. Not all tasks may run.")
else:
if args.get_money:
money = srb_lib.get_money(args.file, profile_id)
print(f"Profile {profile_id} has {money} money.")
if args.set_money:
if args.set_money > 0xFFFF:
ferror(f"Warning: Do not set money higher than 65535. While it can technically work, there's no need for that in-game anyways. Continuing...")
else:
data = srb_lib.set_money(args.file, profile_id, args.set_money)
srb_lib.write_file(args.file,0,data)
if args.get_weapon:
print(f"Profile {profile_id} has weapon {srb_lib.get_weapon(args.file, profile_id)}")
if args.set_weapon:
try:
args.set_weapon = int(args.set_weapon)
except:
pass
data = srb_lib.set_weapon(args.file, profile_id, args.set_weapon)
if type(data) == int and data == -1:
# error is printed in the function
pass
else:
srb_lib.write_file(args.file,0,data)
if args.get_level:
print(f"Profile {profile_id} has level {args.get_level} status {srb_lib.get_level_status(args.file,profile_id,args.get_level)}")
if args.get_levelset:
print(f"Profile {profile_id} has levelset {args.get_levelset} status {srb_lib.get_levelset_status(args.file,profile_id,args.get_levelset)}")
if args.get_name:
print(f"Profile {profile_id} has name {srb_lib.get_name(args.file,profile_id)}")
if args.set_name:
data, message = srb_lib.set_name(args.file, profile_id, args.set_name)
if (type(data) == int and data == -1) or message != "":
ferror(f"Failed to set profile {profile_id} name to {args.set_name} because {message}")
else:
srb_lib.write_file(args.file,0,data)
if args.get_profile_in_use:
print(f"Profile {profile_id} in use is {srb_lib.get_profile_in_use(args.file,profile_id)}")
if args.get_purchased_weapons:
print(f"Profile {profile_id} has weapons {srb_lib.get_purchased_weapons(args.file,profile_id)}")
if args.add_purchased_weapons:
data, message = srb_lib.set_purchased_weapons(args.file,profile_id,"add",args.add_purchased_weapons)
if (type(data) == int and data == -1) or message != "":
ferror(f"Failed to add purchased weapons {args.add_purchased_weapons} because {message}")
else:
srb_lib.write_file(args.file,0,data)
if args.remove_purchased_weapons:
data, message = srb_lib.set_purchased_weapons(args.file,profile_id,"remove",args.remove_purchased_weapons)
if (type(data) == int and data == -1) or message != "":
ferror(f"Failed to add purchased weapons {args.remove_purchased_weapons} because {message}")
else:
srb_lib.write_file(args.file,0,data)
if args.get_tutorial_completed:
print(f"Profile {profile_id} completed-tutorial is {srb_lib.get_tutorial_completed(args.file,profile_id)}")
if args.set_tutorial_completed:
thisbool = False if args.set_tutorial_completed == "False" else True
data, newstatus = srb_lib.set_tutorial_completed(args.file,profile_id,thisbool)
srb_lib.write_file(args.file,0,data)
if args.get_health:
stat, message = srb_lib.get_plane_stat(args.file,profile_id,"health")
# error is printed in the function, so if not any error, run
if not (stat == -1 or message != ""):
print(f"Profile {profile_id} has health level {stat}")
if args.set_health:
data, message = srb_lib.set_plane_stat(args.file,profile_id,"health",args.set_health)
if data == -1 or message != "":
print(f"Failed to set health to {args.set_health} because {message}")
else:
srb_lib.write_file(args.file,0,data)
if args.get_stunt:
stat, message = srb_lib.get_plane_stat(args.file,profile_id,"stunt")
# error is printed in the function, so if not any error, run
if not (stat == -1 or message != ""):
print(f"Profile {profile_id} has stunt level {stat}")
if args.set_stunt:
data, message = srb_lib.set_plane_stat(args.file,profile_id,"stunt",args.set_stunt)
if data == -1 or message != "":
print(f"Failed to set stunt to {args.set_stunt} because {message}")
else:
srb_lib.write_file(args.file,0,data)
if args.get_gun:
stat, message = srb_lib.get_plane_stat(args.file,profile_id,"gun")
# error is printed in the function, so if not any error, run
if not (stat == -1 or message != ""):
print(f"Profile {profile_id} has gun level {stat}")
if args.set_gun:
data, message = srb_lib.set_plane_stat(args.file,profile_id,"gun",args.set_gun)
if data == -1 or message != "":
print(f"Failed to set gun to {args.set_gun} because {message}")
else:
srb_lib.write_file(args.file,0,data)
if args.get_purchased_planes:
print(f"Profile {profile_id} has planes {srb_lib.get_purchased_planes(args.file,profile_id)}")
if args.add_purchased_planes:
data, message = srb_lib.set_purchased_planes(args.file,profile_id,"add",args.add_purchased_planes)
if (type(data) == int and data == -1) or message != "":
ferror(f"Failed to add purchased planes {args.add_purchased_planes} because {message}")
else:
srb_lib.write_file(args.file,0,data)
if args.remove_purchased_planes:
data, message = srb_lib.set_purchased_planes(args.file,profile_id,"remove",args.remove_purchased_planes)
if (type(data) == int and data == -1) or message != "":
ferror(f"Failed to add purchased planes {args.remove_purchased_planes} because {message}")
else:
srb_lib.write_file(args.file,0,data)
if args.checksum:
f = args.file
#for f in args.file:
if debuglev(1,debuglevel):
ferror(f"Fixing checksum for file {f}")
srb_lib.correct_file(f,debuglevel)
|