Skip to content

Commit 8ea0c3f

Browse files
committed
Extended build data generation script to also generate ability_lookup.csv and unit_lookup.csv
1 parent e89e0fc commit 8ea0c3f

File tree

1 file changed

+132
-30
lines changed

1 file changed

+132
-30
lines changed

generate_build_data.py

Lines changed: 132 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -10,93 +10,195 @@ def generate_build_data(balance_data_path):
1010
abilities = {}
1111
units = {}
1212

13+
ability_lookup = {}
14+
1315
for xml_file_path in glob.glob(os.path.join(balance_data_path, "*.xml")):
1416
tree = xml.etree.ElementTree.parse(xml_file_path)
1517
root = tree.getroot()
1618

1719
for ability_element in root.findall("./abilities/ability"):
18-
if ability_element.get("index") and ability_element.get("id"):
19-
abilities[ability_element.get("index")] = ability_element.get("id")
20+
ability_name = ability_element.get("id")
21+
if ability_element.get("index") and ability_name:
22+
abilities[ability_element.get("index")] = ability_name
23+
24+
if ability_name not in ability_lookup:
25+
ability_lookup[ability_name] = []
26+
27+
for command_element in ability_element.findall("./command"):
28+
command_id = command_element.get("id")
29+
command_index_str = command_element.get("index")
30+
31+
if command_id and command_index_str:
32+
command_index = int(command_index_str)
2033

21-
unit_name = root.get("id")
34+
# Pad potential gaps in command indices with empty strings
35+
while len(ability_lookup[ability_name]) <= command_index:
36+
ability_lookup[ability_name].append("")
37+
38+
command_name = command_id if command_id != "Execute" else ability_name
39+
ability_lookup[ability_name][command_index] = command_name
40+
41+
unit_id = root.get("id")
2242

2343
meta_element = root.find("./meta")
2444

25-
if unit_name and meta_element is not None and meta_element.get("index"):
26-
units[meta_element.get("index")] = unit_name
45+
if unit_id and meta_element is not None and meta_element.get("index"):
46+
units[meta_element.get("index")] = unit_id
2747

28-
build_unit_element = root.find("./builds/unit")
29-
if build_unit_element is not None:
30-
build_ability_index = build_unit_element.get("ability")
48+
build_unit_elements = root.findall("./builds/unit")
49+
if build_unit_elements:
50+
build_ability_index = build_unit_elements[0].get("ability")
3151

32-
if unit_name == "SCV":
52+
if unit_id == "SCV":
3353
build_ability_name = "TerranBuild"
34-
elif unit_name == "Probe":
54+
elif unit_id == "Probe":
3555
build_ability_name = "ProtossBuild"
36-
elif unit_name == "Drone":
56+
elif unit_id == "Drone":
3757
build_ability_name = "ZergBuild"
3858
else:
39-
build_ability_name = "{}Build".format(unit_name)
59+
build_ability_name = "{}Build".format(unit_id)
4060

4161
if build_ability_index:
4262
abilities[build_ability_index] = build_ability_name
4363

64+
if build_ability_name not in ability_lookup:
65+
ability_lookup[build_ability_name] = []
66+
67+
for element in build_unit_elements:
68+
built_unit_id = element.get("id")
69+
command_index_str = element.get("index")
70+
71+
if built_unit_id and command_index_str:
72+
command_index = int(command_index_str)
73+
74+
# Pad potential gaps in command indices with empty strings
75+
while len(ability_lookup[build_ability_name]) <= command_index:
76+
ability_lookup[build_ability_name].append("")
77+
78+
build_command_name = "Build{}".format(built_unit_id)
79+
ability_lookup[build_ability_name][command_index] = build_command_name
80+
4481
train_unit_elements = root.findall("./trains/unit")
4582
if train_unit_elements:
4683
train_ability_index = train_unit_elements[0].get("ability")
4784

4885
if train_ability_index:
49-
abilities[train_ability_index] = "{}Train".format(unit_name)
86+
train_ability_name = "{}Train".format(unit_id)
87+
abilities[train_ability_index] = train_ability_name
88+
89+
if train_ability_name not in ability_lookup:
90+
ability_lookup[train_ability_name] = []
5091

51-
# Handle cases where a unit can train other units using multiple ability indices.
52-
# The Nexus is currently the only known example.
53-
for element in train_unit_elements[1:]:
92+
for element in train_unit_elements:
5493
element_ability_index = element.get("ability")
5594
trained_unit_name = element.get("id")
5695

57-
if element_ability_index != train_ability_index and trained_unit_name:
58-
train_ability_index = element_ability_index
96+
if trained_unit_name:
97+
# Handle cases where a unit can train other units using multiple ability indices.
98+
# The Nexus is currently the only known example.
99+
if element_ability_index != train_ability_index:
100+
train_ability_index = element_ability_index
101+
102+
train_ability_name = "{}Train{}".format(unit_id, trained_unit_name)
103+
abilities[train_ability_index] = train_ability_name
104+
105+
if train_ability_name not in ability_lookup:
106+
ability_lookup[train_ability_name] = []
107+
108+
command_index_str = element.get("index")
109+
110+
if command_index_str:
111+
command_index = int(command_index_str)
59112

60-
abilities[train_ability_index] = "{}Train{}".format(unit_name, trained_unit_name)
113+
# Pad potential gaps in command indices with empty strings
114+
while len(ability_lookup[train_ability_name]) <= command_index:
115+
ability_lookup[train_ability_name].append("")
61116

62-
research_upgrade_element = root.find("./researches/upgrade")
63-
if research_upgrade_element is not None:
64-
research_ability_index = research_upgrade_element.get("ability")
65-
research_ability_name = "{}Research".format(unit_name)
117+
ability_lookup[train_ability_name][command_index] = train_ability_name
118+
else:
119+
command_index_str = element.get("index")
120+
121+
if command_index_str:
122+
command_index = int(command_index_str)
123+
124+
# Pad potential gaps in command indices with empty strings
125+
while len(ability_lookup[train_ability_name]) <= command_index:
126+
ability_lookup[train_ability_name].append("")
127+
128+
train_command_name = "Train{}".format(trained_unit_name)
129+
ability_lookup[train_ability_name][command_index] = train_command_name
130+
131+
research_upgrade_elements = root.findall("./researches/upgrade")
132+
if research_upgrade_elements:
133+
research_ability_index = research_upgrade_elements[0].get("ability")
134+
research_ability_name = "{}Research".format(unit_id)
66135

67136
abilities[research_ability_index] = research_ability_name
68137

69-
sorted_abilities = collections.OrderedDict(sorted(abilities.items(), key=lambda x: int(x[0])))
138+
if research_ability_name not in ability_lookup:
139+
ability_lookup[research_ability_name] = []
140+
141+
for element in research_upgrade_elements:
142+
researched_upgrade_id = element.get("id")
143+
command_index_str = element.get("index")
144+
145+
if researched_upgrade_id and command_index_str:
146+
command_index = int(command_index_str)
147+
148+
# Pad potential gaps in command indices with empty strings
149+
while len(ability_lookup[research_ability_name]) <= command_index:
150+
ability_lookup[research_ability_name].append("")
151+
152+
research_command_name = "Research{}".format(researched_upgrade_id)
153+
ability_lookup[research_ability_name][command_index] = research_command_name
154+
70155
sorted_units = collections.OrderedDict(sorted(units.items(), key=lambda x: int(x[0])))
156+
sorted_abilities = collections.OrderedDict(sorted(abilities.items(), key=lambda x: int(x[0])))
157+
158+
unit_lookup = [[unit_name, unit_name] for _, unit_name in sorted_units.items()]
71159

72-
return sorted_units, sorted_abilities
160+
return sorted_units, sorted_abilities, unit_lookup, ability_lookup
73161

74162

75163
def main():
76-
parser = argparse.ArgumentParser(description='Generate [BUILD_VERSION]_abilities.csv and [BUILD_VERSION]_units.csv'
77-
' files from exported balance data.')
164+
parser = argparse.ArgumentParser(description='Generate [BUILD_VERSION]_abilities.csv, [BUILD_VERSION]_units.csv,'
165+
' ability_lookup.csv and unit_lookup.csv files from exported balance'
166+
' data.')
78167
parser.add_argument('build_version', metavar='BUILD_VERSION', type=int,
79168
help='the build version of the balance data export')
80169
parser.add_argument('balance_data_path', metavar='BALANCE_DATA_PATH', type=str,
81170
help='the path to the balance data export')
82171

83172
args = parser.parse_args()
84173

85-
units, abilities = generate_build_data(args.balance_data_path)
174+
units, abilities, unit_lookup, ability_lookup = generate_build_data(args.balance_data_path)
86175

87176
if not units or not abilities:
177+
parser.print_help()
178+
print("\n")
179+
88180
raise ValueError("No balance data found at provided balance data path.")
89181

90182
with open('{}_units.csv'.format(args.build_version), 'w', newline='') as csvfile:
91-
csv_writer = csv.writer(csvfile, delimiter=',')
183+
csv_writer = csv.writer(csvfile, delimiter=',', lineterminator=os.linesep)
92184
for unit_index, unit_name in units.items():
93185
csv_writer.writerow([unit_index, unit_name])
94186

95187
with open('{}_abilities.csv'.format(args.build_version), 'w', newline='') as csvfile:
96-
csv_writer = csv.writer(csvfile, delimiter=',')
188+
csv_writer = csv.writer(csvfile, delimiter=',', lineterminator=os.linesep)
97189
for ability_index, ability_name in abilities.items():
98190
csv_writer.writerow([ability_index, ability_name])
99191

192+
with open('unit_lookup.csv'.format(args.build_version), 'w', newline='') as csvfile:
193+
csv_writer = csv.writer(csvfile, delimiter=',', lineterminator=os.linesep)
194+
for lookup_entry in unit_lookup:
195+
csv_writer.writerow(lookup_entry)
196+
197+
with open('ability_lookup.csv'.format(args.build_version), 'w', newline='') as csvfile:
198+
csv_writer = csv.writer(csvfile, delimiter=',', lineterminator=os.linesep)
199+
for ability_name, commands in ability_lookup.items():
200+
csv_writer.writerow([ability_name] + commands)
201+
100202

101203
if __name__ == "__main__":
102204
main()

0 commit comments

Comments
 (0)