Skip to content

Commit

Permalink
convert: Genie conversion formats.
Browse files Browse the repository at this point in the history
  • Loading branch information
heinezen committed Oct 8, 2019
1 parent 0f05203 commit f154d61
Show file tree
Hide file tree
Showing 14 changed files with 405 additions and 9 deletions.
1 change: 1 addition & 0 deletions openage/convert/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,4 @@ add_subdirectory(hardcoded)
add_subdirectory(interface)
add_subdirectory(nyan)
add_subdirectory(opus)
add_subdirectory(processor)
3 changes: 3 additions & 0 deletions openage/convert/dataformat/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
add_py_modules(
__init__.py
content_snippet.py
converter_object.py
data_definition.py
data_formatter.py
entry_parser.py
Expand All @@ -15,3 +16,5 @@ add_py_modules(
util.py
value_member.py
)

add_subdirectory(aoc)
5 changes: 5 additions & 0 deletions openage/convert/dataformat/aoc/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
add_py_modules(
__init__.py
genie_unit.py
genie_object_container.py
)
5 changes: 5 additions & 0 deletions openage/convert/dataformat/aoc/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Copyright 2019-2019 the openage authors. See copying.md for legal info.

"""
Conversion data formats for Age of Empires II.
"""
69 changes: 69 additions & 0 deletions openage/convert/dataformat/aoc/genie_object_container.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# Copyright 2019-2019 the openage authors. See copying.md for legal info.

from openage.convert.dataformat.converter_object import ConverterObjectContainer


class GenieObjectContainer(ConverterObjectContainer):
"""
Contains everything from the dat file, sorted into several
categories.
"""

def __init__(self):

# ConverterObject types (the data from the game)
self.genie_units = {}
self.genie_techs = {}
self.graphics = {}
self.age_connections = {}
self.building_connections = {}
self.unit_connections = {}
self.tech_connections = {}
self.sounds = {}
self.civs = {}

# ConverterObjectGroup types (things that will become
# nyan objects)
# key: group_id; value: ConverterObjectGroup instance
self.unit_lines = {}
self.building_lines = {}
self.task_groups = {}
self.transform_groups = {}
self.villager_groups = {}
self.monk_groups = {}

def add_unit_line(self, unit_line):
"""
Adds a Genie unit line to the data set.
"""
self.unit_lines.update({unit_line.get_id(): unit_line})

def add_building_line(self, building_line):
"""
Adds a Genie building line to the data set.
"""
self.building_lines.update({building_line.get_id(): building_line})

def add_monk_group(self, monk_group):
"""
Adds a Genie villager task group to the data set.
"""
self.monk_groups.update({monk_group.get_id(): monk_group})

def add_task_group(self, task_group):
"""
Adds a Genie task group to the data set.
"""
self.task_groups.update({task_group.get_id(): task_group})

def add_transform_group(self, transform_group):
"""
Adds a Genie transform group to the data set.
"""
self.transform_groups.update({transform_group.get_id(): transform_group})

def add_villager_group(self, task_group):
"""
Adds a Genie villager task group to the data set.
"""
self.villager_groups.update({task_group.get_id(): task_group})
256 changes: 256 additions & 0 deletions openage/convert/dataformat/aoc/genie_unit.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,256 @@
# Copyright 2019-2019 the openage authors. See copying.md for legal info.


from openage.convert.dataformat.converter_object import ConverterObject,\
ConverterObjectGroup


class GenieUnitObject(ConverterObject):
"""
Ingame object in AoE2.
"""

def __init__(self, unit_id, full_data_set):

super().__init__(unit_id, [])

self.data = full_data_set
self.data.genie_units.append(self)


class GenieUnitLineGroup(ConverterObjectGroup):
"""
A collection of GenieUnitObject types that form an "upgrade line"
in Age of Empires.
Example: Spearman->Pikeman->Helbardier
The first unit in the line will become the GameEntity, the rest will
be patches to that GameEntity applied by Techs.
"""

def __init__(self, line_id, full_data_set):
"""
Creates a new Genie unit line.
:param line_id: Internal line id in the .dat file.
:param full_data_set: GenieObjectContainer instance that
contains all relevant data for the conversion
process.
"""

super().__init__(line_id)

# The line is stored as an ordered list of GenieUnitObjects.
self.line = []

# Reference to everything else in the gamedata
self.data = full_data_set
self.data.add_unit_line(self)

def add_unit(self, genie_unit, after=None):
"""
Adds a unit to the line.
:param genie_unit: A GenieUnit object that is part of this
unit line.
:param after: ID of a unit after which the new unit is
placed in the line. If a unit with this id
is not present, the unit is appended at the end
of the line.
"""

unit_type = genie_unit.get_member("type").get_value()

# Valid units have type >= 70
if unit_type < 70:
raise Exception("GenieUnitObject must have type >= 70"
"to be added to line")

if after:
for unit in self.line:
if after == unit.get_id():
self.line.insert(self.line.index(unit), genie_unit)
break

else:
self.line.append(genie_unit)

else:
self.line.append(genie_unit)

def contains_unit(self, unit_id):
"""
Returns True if a unit with unit_id is part of the line.
"""
for unit in self.line:
if unit.get_member("id") == unit_id:
return True

return False


class GenieBuildingLineGroup(ConverterObjectGroup):
"""
A collection of GenieUnitObject types that represent a building
in Age of Empires. While buildings have no actual "lines" like units in
the game data, we will handle them as if they were organized that way.
Buildings in AoE2 also create units and research techs, so
this is handled in here.
The 'head unit' of a building line becomes the GameEntity, the rest will
be patches to that GameEntity applied by Techs.
"""

def __init__(self, head_building_id, full_data_set):
"""
Creates a new Genie building line.
:param head_building_id: The building that is first in line.
:param full_data_set: GenieObjectContainer instance that
contains all relevant data for the conversion
process.
"""

super().__init__(head_building_id)

# The line is stored as an ordered list of GenieUnitObjects.
self.line = []

# List of GenieUnitLine objects
self.creates = []

# List of TODO objects
self.researches = []

# Reference to everything else in the gamedata
self.data = full_data_set
self.data.add_building_line(self)


class GenieUnitTransformGroup(ConverterObjectGroup):
"""
Collection of genie units that reference each other with their
transform_id.
Example: Trebuchet
"""

def __init__(self, head_unit_id, full_data_set):
"""
Creates a new Genie transform group.
:param head_unit_id: Internal unit id of the unit that should be
the initial state.
:param full_data_set: GenieObjectContainer instance that
contains all relevant data for the conversion
process.
"""

super().__init__(head_unit_id)

# Reference to everything else in the gamedata
self.data = full_data_set
self.data.add_transform_group(self)

self.head_unit = self.data.genie_units[head_unit_id]

transform_id = self.head_unit.get_member("transform_id").get_value()
self.transform_unit = self.data.genie_units[transform_id]


class GenieUnitTaskGroup(ConverterObjectGroup):
"""
Collection of genie units that have the same task group.
Example: Villager
The 'head unit' of a task group becomes the GameEntity, all
the other ones become variants or AnimationOverrides of abilities.
"""

def __init__(self, task_group_id, head_task_id, full_data_set):
"""
Creates a new Genie task group.
:param task_group_id: Internal task group id in the .dat file.
:param head_task_id: The unit with this task will become the head unit.
:param full_data_set: GenieObjectContainer instance that
contains all relevant data for the conversion
process.
"""

super().__init__(task_group_id)

self.head_task_id = head_task_id

# The task group is stored as a dict of GenieUnitObjects.
# key: task id; value: unit
self.units = {}

# Add task group to gamedata
self.data = full_data_set
self.data.add_task_group(self)


class GenieVillagerGroup(GenieUnitTaskGroup):
"""
Special GenieUnitTaskGroup for villagers.
Villagers come in two task groups, so one task group is a
variant of the other one.
"""

def __init__(self, task_group_id, head_task_id,
variant_task_group_id, full_data_set):
"""
Creates a new Genie villager group.
:param task_group_id: Internal task group id in the .dat file.
:param head_task_id: The unit with this task will become the head unit.
:param variant_task_group_id: The task group id of the variant.
:param full_data_set: GenieObjectContainer instance that
contains all relevant data for the conversion
process.
"""
super().__init__(task_group_id, head_task_id, full_data_set)

# Reference to the other task group
self.variant = self.data.task_groups[variant_task_group_id]

# List of buildings that villagers can create
self.creates = []

self.data.add_villager_group(self)


class GenieMonkGroup(ConverterObjectGroup):
"""
Collection of monk and monk with relic. The switch
is hardcoded in AoE2.
The 'head unit' will become the GameEntity, the 'switch unit'
will become a Container ability with CarryProgress.
"""

def __init__(self, head_unit_id, switch_unit_id, full_data_set):
"""
Creates a new Genie monk group.
:param head_unit_id: The unit with this task will become the actual
GameEntity.
:param switch_unit_id: This unit will be used to determine the
CarryProgress objects.
:param full_data_set: GenieObjectContainer instance that
contains all relevant data for the conversion
process.
"""
super().__init__(head_unit_id)

# Reference to everything else in the gamedata
self.data = full_data_set
self.data.add_monk_group(self)

self.head_unit = self.data.genie_units[head_unit_id]
self.switch_unit = self.data.genie_units[switch_unit_id]
14 changes: 11 additions & 3 deletions openage/convert/dataformat/converter_object.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
# Copyright 2014-2019 the openage authors. See copying.md for legal info.

# TODO pylint: disable=C,R,abstract-method
# Copyright 2019-2019 the openage authors. See copying.md for legal info.

"""
Objects that represent data structures in the original game.
Expand Down Expand Up @@ -186,3 +184,13 @@ def get_nyan_object(self):
def __repr__(self):
raise NotImplementedError(
"return short description of the object %s" % (type(self)))


class ConverterObjectContainer:
"""
A conainer for all ConverterObject instances in a converter process.
It is recommended to create one ConverterObjectContainer for everything
and pass the reference around.
"""
pass
2 changes: 1 addition & 1 deletion openage/convert/dataformat/value_members.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright 2014-2019 the openage authors. See copying.md for legal info.
# Copyright 2019-2019 the openage authors. See copying.md for legal info.
# TODO pylint: disable=C,R,abstract-method

"""
Expand Down
Loading

0 comments on commit f154d61

Please sign in to comment.