mirror of
https://github.com/pret/pokeplatinum.git
synced 2026-04-10 03:40:59 -05:00
This new code is responsible for packing the following archives: - `pl_personal` -> basic information for each species: stats, types, etc. - `evo` -> evolution lines for each species - `wotbl` -> by-level learnsets for each species - `ppark` -> catching show data for each species - `height` -> y-offsets for front and back sprites for each species - `pl_poke_data` -> sprite-rendering data for each species: animation ID, frame data, shadow size and offsets, etc. Additionally, the following headers are generated: - `res/pokemon/tutorable_moves.h` -> A listing of moves taught by each tutor and how much each move costs to be tutored - `res/pokemon/species_learnsets_by_tutor.h` -> An array of bitmasks for each species designating which moves can be tutored to that species
131 lines
4.5 KiB
Python
Executable File
131 lines
4.5 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
|
|
"""
|
|
This is a standalone script for existing end-users to migrate their data
|
|
structures to the new species_data format expected by datagen_species.cpp.
|
|
New users and users who have not made any changes to species' data.json
|
|
files should not need to use it. Any user which *has* made changes to these
|
|
files can accept their copy during a merge from main, then run this script
|
|
to update all of their files in bulk.
|
|
"""
|
|
|
|
import json
|
|
import pathlib
|
|
|
|
|
|
class SpeciesJSONEncoder(json.JSONEncoder):
|
|
def __init__(self, *args, **kwargs):
|
|
super().__init__(*args, **kwargs)
|
|
self.indentation_level = 0
|
|
|
|
def encode(self, o):
|
|
if isinstance(o, (list, tuple)):
|
|
if self._is_inlinable(o):
|
|
return f"[ {', '.join(json.dumps(el) for el in o)} ]"
|
|
else:
|
|
self.indentation_level += 1
|
|
output = [f"{self.indent_str}{self.encode(el)}" for el in o]
|
|
self.indentation_level -= 1
|
|
return f"[\n{',\n'.join(output)}\n{self.indent_str}]"
|
|
elif isinstance(o, dict):
|
|
self.indentation_level += 1
|
|
output = [
|
|
f"{self.indent_str}{json.dumps(k)}: {self.encode(v)}"
|
|
for k, v in o.items()
|
|
]
|
|
self.indentation_level -= 1
|
|
return f"{{\n{',\n'.join(output)}\n{self.indent_str}}}"
|
|
else:
|
|
return json.dumps(o)
|
|
|
|
def _is_inlinable(self, o):
|
|
if isinstance(o, (list, tuple)):
|
|
return (
|
|
not any(isinstance(el, (list, tuple, dict)) for el in o)
|
|
and len(o) <= 2
|
|
and len(str(o)) - 2 <= 80
|
|
)
|
|
|
|
@property
|
|
def indent_str(self) -> str:
|
|
if isinstance(self.indent, int):
|
|
return " " * (self.indentation_level * self.indent)
|
|
elif isinstance(self.indent, str):
|
|
return self.indentation_level * self.indent
|
|
else:
|
|
raise ValueError(
|
|
f"indent must be of type int or str (is: {type(self.indent)})"
|
|
)
|
|
|
|
def iterencode(self, o, **kwargs):
|
|
return self.encode(o)
|
|
|
|
|
|
def migrate(d: dict) -> dict:
|
|
o = {}
|
|
o["name"] = d["name"]
|
|
o["base_stats"] = d["base_stats"]
|
|
o["types"] = d["types"]
|
|
o["catch_rate"] = d["catch_rate"]
|
|
o["base_exp_reward"] = d["base_exp_reward"]
|
|
o["ev_yields"] = d["ev_yields"]
|
|
o["held_items"] = d["held_items"]
|
|
o["gender_ratio"] = d["gender_ratio"]
|
|
o["hatch_cycles"] = d["hatch_cycles"]
|
|
o["base_friendship"] = d["base_friendship"]
|
|
o["exp_rate"] = d["exp_rate"]
|
|
o["egg_groups"] = d["egg_groups"]
|
|
o["abilities"] = d["abilities"]
|
|
o["safari_flee_rate"] = d.get("safari_flee_rate", d.get("great_marsh_flee_rate"))
|
|
o["body_color"] = d["sprite"]["color"]
|
|
o["flip_sprite"] = d["sprite"].get("flip", d["sprite"].get("flip_sprite"))
|
|
|
|
o["learnset"] = {}
|
|
learnsets = d["learnset"]
|
|
|
|
by_level = []
|
|
if "level_up" in learnsets: # old dictionary-based structure
|
|
for k, v in learnsets["level_up"].items():
|
|
if isinstance(v, list):
|
|
for mem in v:
|
|
by_level.append([int(k), mem])
|
|
else:
|
|
by_level.append([int(k), v])
|
|
else: # newer list-of-tuples structure
|
|
by_level = learnsets["by_level"]
|
|
|
|
o["learnset"]["by_level"] = by_level
|
|
o["learnset"]["by_tm"] = learnsets.get("by_tm", learnsets.get("tms"))
|
|
if "tutor" in learnsets:
|
|
o["learnset"]["by_tutor"] = learnsets["tutor"]
|
|
elif "by_tutor" in learnsets:
|
|
o["learnset"]["by_tutor"] = learnsets["by_tutor"]
|
|
|
|
o["evolutions"] = d.get("evolutions", [])
|
|
|
|
if "footprint" in d:
|
|
o["footprint"] = {}
|
|
footprint = d["footprint"]
|
|
o["footprint"]["has"] = footprint.get("has", footprint.get("has_footprint"))
|
|
o["footprint"]["size"] = footprint.get("size", footprint.get("footprint_size"))
|
|
|
|
if "pokedex_data" in d:
|
|
o["pokedex_data"] = d["pokedex_data"]
|
|
if "catching_show_data" in d:
|
|
o["catching_show"] = d["catching_show_data"]
|
|
|
|
return o
|
|
|
|
|
|
parent = pathlib.Path("res/pokemon")
|
|
for fname in parent.rglob("**/data.json"):
|
|
try:
|
|
with open(fname, "r", encoding="utf-8") as f:
|
|
j = json.load(f)
|
|
d = migrate(j)
|
|
with open(fname, "w", encoding="utf-8") as f:
|
|
json.dump(d, f, cls=SpeciesJSONEncoder, indent=4, ensure_ascii=False)
|
|
except KeyError as e:
|
|
print(f"Error parsing {fname}")
|
|
raise e
|