Skip to content

Commit 3ee1608

Browse files
committed
convert: Refactor SWGBCCProcessor into separate files.
1 parent 5b78903 commit 3ee1608

File tree

18 files changed

+937
-798
lines changed

18 files changed

+937
-798
lines changed

openage/convert/processor/conversion/aoc/main/groups/unit_line.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,6 @@ def create_unit_lines(full_data_set: GenieObjectContainer) -> None:
113113
full_data_set.unit_ref.update({unit_id: unit_line})
114114

115115

116-
@staticmethod
117116
def create_extra_unit_lines(full_data_set: GenieObjectContainer) -> None:
118117
"""
119118
Create additional units that are not in the unit connections.

openage/convert/processor/conversion/swgbcc/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,6 @@ add_py_modules(
1515
add_subdirectory(ability)
1616
add_subdirectory(auxiliary)
1717
add_subdirectory(civ)
18+
add_subdirectory(main)
1819
add_subdirectory(nyan)
1920
add_subdirectory(pregen)
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
add_py_modules(
2+
__init__.py
3+
)
4+
5+
add_subdirectory(groups)
6+
add_subdirectory(link)
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Copyright 2025-2025 the openage authors. See copying.md for legal info.
2+
3+
"""
4+
Routines for the main SWGB conversion process.
5+
"""
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
add_py_modules(
2+
__init__.py
3+
ambient_group.py
4+
building_line.py
5+
tech_group.py
6+
unit_line.py
7+
variant_group.py
8+
villager_group.py
9+
)
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Copyright 2025-2025 the openage authors. See copying.md for legal info.
2+
3+
"""
4+
Create lines and groups fron extracted SWGB data.
5+
"""
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# Copyright 2025-2025 the openage authors. See copying.md for legal info.
2+
3+
"""
4+
Create ambient groups from genie units.
5+
"""
6+
from __future__ import annotations
7+
import typing
8+
9+
from ......entity_object.conversion.aoc.genie_unit import GenieAmbientGroup
10+
from ......value_object.conversion.swgb.internal_nyan_names import AMBIENT_GROUP_LOOKUPS
11+
12+
if typing.TYPE_CHECKING:
13+
from ......entity_object.conversion.aoc.genie_object_container import GenieObjectContainer
14+
15+
16+
def create_ambient_groups(full_data_set: GenieObjectContainer) -> None:
17+
"""
18+
Create ambient groups, mostly for resources and scenery.
19+
20+
:param full_data_set: GenieObjectContainer instance that
21+
contains all relevant data for the conversion
22+
process.
23+
"""
24+
ambient_ids = AMBIENT_GROUP_LOOKUPS.keys()
25+
genie_units = full_data_set.genie_units
26+
27+
for ambient_id in ambient_ids:
28+
ambient_group = GenieAmbientGroup(ambient_id, full_data_set)
29+
ambient_group.add_unit(genie_units[ambient_id])
30+
full_data_set.ambient_groups.update({ambient_group.get_id(): ambient_group})
31+
full_data_set.unit_ref.update({ambient_id: ambient_group})
Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
# Copyright 2025-2025 the openage authors. See copying.md for legal info.
2+
3+
"""
4+
Create building lines from genie buildings.
5+
"""
6+
from __future__ import annotations
7+
import typing
8+
9+
from ......entity_object.conversion.aoc.genie_tech import BuildingUnlock
10+
from ......entity_object.conversion.aoc.genie_tech import BuildingLineUpgrade
11+
from ......entity_object.conversion.aoc.genie_unit import GenieBuildingLineGroup
12+
from ......entity_object.conversion.swgbcc.genie_unit import SWGBStackBuildingGroup
13+
14+
if typing.TYPE_CHECKING:
15+
from ......entity_object.conversion.aoc.genie_object_container import GenieObjectContainer
16+
17+
18+
def create_building_lines(full_data_set: GenieObjectContainer) -> None:
19+
"""
20+
Establish building lines, based on information in the building connections.
21+
Because of how Genie building lines work, this will only find the first
22+
building in the line. Subsequent buildings in the line have to be determined
23+
by effects in AgeUpTechs.
24+
25+
:param full_data_set: GenieObjectContainer instance that
26+
contains all relevant data for the conversion
27+
process.
28+
"""
29+
building_connections = full_data_set.building_connections
30+
genie_techs = full_data_set.genie_techs
31+
32+
# Unlocked = first in line
33+
unlocked_by_tech = set()
34+
35+
# Upgraded = later in line
36+
upgraded_by_tech = {}
37+
38+
# Search all techs for building upgrades. This is necessary because they are
39+
# not stored in tech connections in SWGB
40+
for tech_id, tech in genie_techs.items():
41+
tech_effect_id = tech["tech_effect_id"].value
42+
if tech_effect_id < 0:
43+
continue
44+
45+
tech_effects = full_data_set.genie_effect_bundles[tech_effect_id].get_effects()
46+
47+
# Search for upgrade or unlock effects
48+
age_up = False
49+
for effect in tech_effects:
50+
effect_type = effect["type_id"].value
51+
unit_id_a = effect["attr_a"].value
52+
unit_id_b = effect["attr_b"].value
53+
54+
if effect_type == 1 and effect["attr_a"].value == 6:
55+
# if this is an age up tech, we do not need to create any additional
56+
# unlock techs
57+
age_up = True
58+
59+
if effect_type == 2 and unit_id_a in building_connections.keys():
60+
# Unlocks
61+
unlocked_by_tech.add(unit_id_a)
62+
63+
if not age_up:
64+
# Add an unlock tech group to the data set
65+
building_unlock = BuildingUnlock(tech_id, unit_id_a, full_data_set)
66+
full_data_set.building_unlocks.update(
67+
{building_unlock.get_id(): building_unlock})
68+
69+
elif effect_type == 2 and unit_id_a in full_data_set.genie_units.keys():
70+
# Check if this is a stacked unit (gate or command center)
71+
# for these units, we needs the stack_unit_id
72+
building = full_data_set.genie_units[unit_id_a]
73+
74+
if building.has_member("stack_unit_id") and \
75+
building["stack_unit_id"].value > -1:
76+
unit_id_a = building["stack_unit_id"].value
77+
unlocked_by_tech.add(unit_id_a)
78+
79+
if not age_up:
80+
building_unlock = BuildingUnlock(tech_id, unit_id_a, full_data_set)
81+
full_data_set.building_unlocks.update(
82+
{building_unlock.get_id(): building_unlock})
83+
84+
if effect_type == 3 and unit_id_b in building_connections.keys():
85+
# Upgrades
86+
upgraded_by_tech[unit_id_b] = tech_id
87+
88+
# First only handle the line heads (first buildings in a line)
89+
for connection in building_connections.values():
90+
building_id = connection["id"].value
91+
92+
if building_id not in unlocked_by_tech:
93+
continue
94+
95+
building = full_data_set.genie_units[building_id]
96+
97+
# Check if we have to create a GenieStackBuildingGroup
98+
if building.has_member("stack_unit_id") and \
99+
building["stack_unit_id"].value > -1:
100+
# we don't care about head units because we process
101+
# them with their stack unit
102+
continue
103+
104+
if building.has_member("head_unit_id") and \
105+
building["head_unit_id"].value > -1:
106+
head_unit_id = building["head_unit_id"].value
107+
building_line = SWGBStackBuildingGroup(building_id, head_unit_id, full_data_set)
108+
109+
else:
110+
building_line = GenieBuildingLineGroup(building_id, full_data_set)
111+
112+
building_line.add_unit(building)
113+
full_data_set.building_lines.update({building_line.get_id(): building_line})
114+
full_data_set.unit_ref.update({building_id: building_line})
115+
116+
# Second, handle all upgraded buildings
117+
for connection in building_connections.values():
118+
building_id = connection["id"].value
119+
120+
if building_id not in upgraded_by_tech:
121+
continue
122+
123+
building = full_data_set.genie_units[building_id]
124+
125+
# Search other_connections for the previous unit in line
126+
connected_types = connection["other_connections"].value
127+
for index, _ in enumerate(connected_types):
128+
connected_type = connected_types[index]["other_connection"].value
129+
if connected_type == 1:
130+
# 1 == Building
131+
connected_index = index
132+
break
133+
134+
else:
135+
raise ValueError(f"Building {building_id} is not first in line, but no previous "
136+
"building can be found in other_connections")
137+
138+
connected_ids = connection["other_connected_ids"].value
139+
previous_unit_id = connected_ids[connected_index].value
140+
141+
# Search for the first unit ID in the line recursively
142+
previous_id = previous_unit_id
143+
previous_connection = building_connections[previous_unit_id]
144+
while previous_connection["line_mode"] != 2:
145+
if previous_id in full_data_set.unit_ref.keys():
146+
# Short-circuit here, if we the previous unit was already handled
147+
break
148+
149+
connected_types = previous_connection["other_connections"].value
150+
connected_index = -1
151+
for index, _ in enumerate(connected_types):
152+
connected_type = connected_types[index]["other_connection"].value
153+
if connected_type == 1:
154+
# 1 == Building
155+
connected_index = index
156+
break
157+
158+
connected_ids = previous_connection["other_connected_ids"].value
159+
previous_id = connected_ids[connected_index].value
160+
previous_connection = building_connections[previous_id]
161+
162+
building_line = full_data_set.unit_ref[previous_id]
163+
building_line.add_unit(building, after=previous_unit_id)
164+
full_data_set.unit_ref.update({building_id: building_line})
165+
166+
# Also add the building upgrade tech here
167+
building_upgrade = BuildingLineUpgrade(
168+
upgraded_by_tech[building_id],
169+
building_line.get_id(),
170+
building_id,
171+
full_data_set
172+
)
173+
full_data_set.tech_groups.update({building_upgrade.get_id(): building_upgrade})
174+
full_data_set.building_upgrades.update({building_upgrade.get_id(): building_upgrade})

0 commit comments

Comments
 (0)