Last active
December 10, 2015 22:29
-
-
Save leper/4502798 to your computer and use it in GitHub Desktop.
get template data place in binaries/data/mods/public
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
import xml.etree.ElementTree as ET | |
import copy | |
import os | |
import errno | |
use_custom_xml_folder = False | |
template_path = "simulation/templates/" | |
save_path = "XML/" | |
# Used to cache the dicts produced by get_template_as_dict | |
templates = {} | |
def get_template_as_dict(template): | |
# Not already cached -> retrieve | |
if template not in templates: | |
tree = ET.parse(get_template_file(template)) | |
if not tree: | |
# TODO: Raise exception? | |
print("Error reading file \"" + template + ".xml\"") | |
return {} | |
root = tree.getroot() | |
parent = root.get('parent') | |
# Get values top-down (parent first) | |
vals = {} | |
if parent: | |
# Get a deep copy, so we don't change the parent | |
vals = copy.deepcopy(get_template_as_dict(parent)) | |
templates[template] = dict_temp_helper(root, vals) | |
return templates[template] | |
def dict_temp_helper(element, vals={}): | |
for el in list(element): | |
if "disable" in el.attrib: | |
# If this raises an exception, then the xml files | |
# are doing something wrong. | |
del vals[el.tag] | |
continue | |
if "datatype" in el.attrib and el.attrib["datatype"] == "tokens": | |
if not el.tag in vals: | |
vals[el.tag] = [] | |
# Merge the tokens (including removal) | |
vals[el.tag].extend(dict_temp_helper(el, vals[el.tag]).split()) | |
# NOTE: We use sorted just to find all values that should be | |
# removed (starting with '-'), but we don't want to change the | |
# order | |
for val in sorted(vals[el.tag]): | |
# No more values to remove | |
# TODO: Doesn't work with templates starting with | |
# characters < '-', but we assume nobody will | |
# feed this with such template names. | |
if val[0] != '-': | |
break | |
# Remove the entry to be removed | |
vals[el.tag].remove(val[1:]) | |
# Remove the remover | |
vals[el.tag].remove(val) | |
else: | |
vals[el.tag] = dict_temp_helper(el, vals[el.tag] if el.tag in vals else {}) | |
if not vals or not isinstance(vals, dict): | |
if element.text: | |
return element.text | |
else: | |
# To support eg. <Looter/> | |
return {} | |
return vals | |
# Returns None in case the element specified by list isn't found | |
def get_stat(stats, list): | |
list.reverse() | |
return get_stat_helper(stats, list) | |
def get_stat_helper(stats, list): | |
val = stats.get(list.pop()) | |
if len(list) and val is not None: | |
return get_stat_helper(val, list) | |
return val | |
# Returns a list with the found elements | |
# or None | |
def get_stats(stats, list): | |
list.reverse() | |
return get_stats_helper(stats, list) | |
def get_stats_helper(stats, l): | |
key = l[-1] | |
if key is None: | |
ret = [] | |
if len(l[:-1]): | |
for val in stats: | |
b = get_stats_helper(stats[val], l[:-1]) | |
if b is not None: | |
if isinstance(b, list): | |
for a in b: | |
ret.append(a) | |
else: | |
ret.append(b) | |
else: | |
if isinstance(stats, dict): | |
for val in stats: | |
ret.append(stats[val]) | |
else: | |
ret = stats | |
return ret | |
else: | |
val = stats.get(key) | |
if len(l[:-1]) and val is not None: | |
return get_stats_helper(val, l[:-1]) | |
return val | |
def get_template_file(template): | |
if use_custom_xml_folder: | |
# TODO: add the retrieval code here | |
pass | |
else: | |
return template_path + template + '.xml' | |
def make_sure_path_exists(path): | |
try: | |
os.makedirs(path) | |
except OSError as exception: | |
if exception.errno != errno.EEXIST: | |
raise | |
def write_file(civ, unit, file, val): | |
path = save_path + civ + '/' + unit + '/' | |
make_sure_path_exists(path) | |
f = open(path + file, 'w', encoding="utf-8") | |
f.write(val) | |
f.close() | |
def printUnit(unit): | |
stats = get_template_as_dict(unit) | |
print("=========") | |
print(unit) | |
civ = get_stat(stats, ["Identity", "Civ"]) | |
print(civ) | |
write_file(civ, unit, "Gen_Name.txt", get_stat(stats, ["Identity", "GenericName"])) | |
print("Specific Name:") | |
print(get_stat(stats, ["Identity", "SpecificName"])) | |
print("History:") | |
print(get_stat(stats, ["Identity", "History"])) | |
resources = get_stats(stats, ["Cost", "Resources"]) | |
# Remove some useless values | |
# TODO: If this happens more than twice we should maybe make this a function, or part of get_stats | |
for res in list(resources): | |
if resources[res] == "0": | |
del resources[res] | |
write_file(civ, unit, "Resources.txt", | |
',\\,'.join(list('\\includegraphics[width=0.0225\\textwidth]{'+res+'.png}\\,'+resources[res] | |
for res in sorted(resources, key=["food", "wood", "stone", "metal"].index)))) | |
# NOTE: Don't use the first None as we only have Melee, Ranged, Charge and Slaughter defined | |
# and some bonuses are defined in the same way for Melee and Charge | |
# Just use Melee and Ranged (Slaughter doesn't support bonuses and Charge isn't implemented yet) | |
print("Attack bonuses:") | |
for a in get_stats(stats, ["Attack", None, "Bonuses", None]): | |
print("Bonused vs "+a["Classes"]+" (x"+a["Multiplier"]+")") | |
print("Location of Portrait:") | |
print(get_stat(stats, ["Identity", "Icon"])) | |
print("Tooltip:") | |
print(get_stat(stats, ["Identity", "Tooltip"])) | |
print("Health:") | |
print(get_stat(stats, ["Health", "Max"])) | |
# Packed siege special case | |
if unit[-9:] == "_unpacked": | |
print("unpacked siege") | |
packed_stats = get_template_as_dict(unit[:-9]+"_packed") | |
print("Velocity(Walk):") | |
print(get_stat(packed_stats, ["UnitMotion", "WalkSpeed"])) | |
print("Velocity(Run):") | |
print(get_stat(packed_stats, ["UnitMotion", "Run", "Speed"])) | |
else: | |
print("Velocity(Walk):") | |
print(get_stat(stats, ["UnitMotion", "WalkSpeed"])) | |
print("Velocity(Run):") | |
print(get_stat(stats, ["UnitMotion", "Run", "Speed"])) | |
print("Armour") | |
armour = get_stats(stats, ["Armour"]) | |
write_file(civ, unit, "Armour.txt", | |
',\\,'.join(list('\\includegraphics[width=0.0225\\textwidth]{'+a.lower()+'.png}\\,'+armour[a] | |
for a in sorted(armour)))) | |
promotions = 0 | |
promotion_stats = stats | |
while True: | |
promotions += 1 | |
promotion = get_stat(promotion_stats, ["Promotion", "Entity"]) | |
if promotion is None: | |
break | |
promotion_stats = get_template_as_dict(promotion) | |
print("Promotion "+str(promotions)+":") | |
print(promotion) | |
print("Health") | |
print(get_stat(promotion_stats, ["Health", "Max"])) | |
# NOTE: No special handling for packed siege here, as we | |
# don't have promotions for any packable units currently. | |
print("Velocity(Walk):") | |
print(get_stat(stats, ["UnitMotion", "WalkSpeed"])) | |
print("Velocity(Run):") | |
print(get_stat(stats, ["UnitMotion", "Run", "Speed"])) | |
# TODO: | |
#armour | |
#attack | |
#range | |
# TODO: Should we move the civ replacement somewhere else? | |
buildable = get_stats(stats, ["Builder", "Entities"]) | |
if buildable is not None: | |
for i in range(len(buildable)): | |
buildable[i] = buildable[i].replace("{civ}", civ) | |
for building in buildable: | |
building_stats = get_template_as_dict(building) | |
print(get_stat(building_stats, ["Identity", "GenericName"])) | |
# TODO: ["ProductionQueue", "Entities"] (Analogous to Builder->Entities | |
# main | |
units = [ | |
[ "units/rome_infantry_swordsman_b", | |
"units/rome_mechanical_siege_ballista_unpacked" | |
] | |
] | |
for civtemplates in units: | |
for unit in civtemplates: | |
printUnit(unit) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment