diff --git a/pokedex/extract/rby.py b/pokedex/extract/rby.py index fe2d175..a664da2 100644 --- a/pokedex/extract/rby.py +++ b/pokedex/extract/rby.py @@ -1601,18 +1601,35 @@ def bitfield_to_machines(bits, machine_moves): return machines +# TODO this is not correctly using my half-baked "slice" idea class WriterWrapper: def __init__(self, locus, language): - self.locus = locus - self.language = language + self.__dict__.update(dict( + locus=locus, + language=language, + )) def __setattr__(self, key, value): - # TODO finish this... - # 1. disallow reassigning an existing attr with a value - setattr(self.locus, key, value) + # TODO yeah this is fucking ludicrous + attr = type(self.locus).__dict__[key] + # TODO i think my descriptor stuff needs some work here if i have to root around in __dict__ + if isinstance(attr, schema._Localized): + if key not in self.locus.__dict__: + langdict = {} + setattr(self.locus, key, langdict) + else: + langdict = getattr(self.locus, key) + langdict[self.language] = value + else: + if key in self.locus.__dict__: + oldvalue = getattr(self.locus, key) + if value != oldvalue: + raise ValueError( + "Trying to set {!r}'s {} to {!r}, but it already " + "has a different value: {!r}" + .format(self.locus, key, value, oldvalue)) - def __getattr__(self, key): - return getattr(self.locus, key) + setattr(self.locus, key, value) def main(base_root): @@ -1661,16 +1678,11 @@ def main(base_root): for id in range(cart.NUM_POKEMON): pokemon = pokemons[POKEMON_IDENTIFIERS[id + 1]] - #writer = WriterWrapper(pokemon) - writer = pokemon + writer = WriterWrapper(pokemon, language) - # TODO LOLLLL - if 'name' not in writer.__dict__: - writer.name = {} - writer.name[cart.language] = cart.pokemon_names[id] + writer.name = cart.pokemon_names[id] record = cart.pokemon_records[id] - # TODO put this in construct types = [record.type1] if record.type1 != record.type2: @@ -1700,12 +1712,11 @@ def main(base_root): level_up_moves.append({ level_up_move.level: level_up_move.move, }) - # TODO LOLLLL - if 'moves' not in writer.__dict__: - writer.moves = {} - writer.moves['level-up'] = level_up_moves - writer.moves['machines'] = bitfield_to_machines( - record.machines, cart.machine_moves) + writer.moves = { + 'level-up': level_up_moves, + 'machines': bitfield_to_machines( + record.machines, cart.machine_moves), + } # Evolution # TODO alas, the species here is a number, because it's an @@ -1724,13 +1735,8 @@ def main(base_root): # Pokédex flavor flavor_struct = cart.pokedex_entries[id] - # TODO LOLLLL - if 'genus' not in writer.__dict__: - writer.genus = {} - writer.genus[cart.language] = flavor_struct.genus.decrypt(language) - if 'flavor_text' not in writer.__dict__: - writer.flavor_text = {} - writer.flavor_text[cart.language] = flavor_struct.flavor_text.decrypt(language) + writer.genus = flavor_struct.genus.decrypt(language) + writer.flavor_text = flavor_struct.flavor_text.decrypt(language) if cart.uses_metric: writer.height = 1000 * flavor_struct.height_decimeters writer.weight = 100000000 * flavor_struct.weight_hectograms diff --git a/pokedex/schema.py b/pokedex/schema.py index 0220623..4694c41 100644 --- a/pokedex/schema.py +++ b/pokedex/schema.py @@ -128,7 +128,7 @@ class Locus(metaclass=LocusMeta): def __repr__(self): return "<{}: {}>".format( type(self).__qualname__, - self.identifier, + '???', # TODO where is self.identifier assigned when writing? ) @@ -160,9 +160,8 @@ Pokedex = _ForwardDeclaration() class Pokémon(VersionedLocus): # TODO version, language. but those are kind of meta-fields; do they need # treating specially? - # TODO in old games, names are unique per game; in later games, they differ - # per language. what do i do about that? - name = _Value(str) + + name = _Localized(str) types = _List(Type, min=1, max=2) base_stats = _Map(Stat, int) @@ -174,8 +173,8 @@ class Pokémon(VersionedLocus): # TODO family? evolutions = _List(Evolution) - genus = _Value(str) - flavor_text = _Value(str) + genus = _Localized(str) + flavor_text = _Localized(str) # TODO maybe want little wrapper types that can display as either imperial # or metric # TODO maybe also dump as metric rather than plain numbers @@ -184,13 +183,14 @@ class Pokémon(VersionedLocus): # both metric and imperial values as integers with no loss of precision: # myriameters (tenths of a millimeter) and micrograms. # Divide by 100 for centimeters, or by 254 for inches - height = _Value(int) + height = _Localized(int) # Divide by one billion for kilograms, or by 453592370 for pounds - weight = _Value(int) + weight = _Localized(int) # TODO this belongs to a place, not to a pokemon #encounters = _Value(EncounterMap) + # TODO having a custom type here is handy, but it's not a locus moves = _Value(MoveSet) # TODO should this be written in hex, maybe?