Skip to content

Commit c2fe6a6

Browse files
committed
convert: Refactor AoCUpgradeAbilitySubprocessor into separate files.
1 parent 9193b00 commit c2fe6a6

27 files changed

+3154
-2814
lines changed

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,6 @@ add_subdirectory(nyan)
2929
add_subdirectory(pregen)
3030
add_subdirectory(resistance)
3131
add_subdirectory(tech)
32+
add_subdirectory(upgrade_ability)
33+
add_subdirectory(upgrade_effect)
34+
add_subdirectory(upgrade_resistance)

openage/convert/processor/conversion/aoc/ability/util.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
if typing.TYPE_CHECKING:
1818
from .....entity_object.conversion.aoc.genie_civ import GenieCivilizationGroup
1919
from .....entity_object.conversion.aoc.genie_unit import GenieGameEntityGroup
20-
from .....value_object.conversion.forward_ref import ForwardRef
2120

2221

2322
def create_animation(
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
add_py_modules(
2+
__init__.py
3+
apply_continuous_effect.py
4+
apply_discrete_effect.py
5+
attribute_change_tracker.py
6+
death.py
7+
despawn.py
8+
idle.py
9+
line_of_sight.py
10+
live.py
11+
move.py
12+
named.py
13+
resistance.py
14+
selectable.py
15+
shoot_projectile.py
16+
turn.py
17+
util.py
18+
)
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 nyan patches for upgrading abilities of AoC entities.
5+
"""
Lines changed: 243 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,243 @@
1+
# Copyright 2025-2025 the openage authors. See copying.md for legal info.
2+
3+
"""
4+
Create patches for upgrading the ApplyContinuousEffect ability.
5+
"""
6+
from __future__ import annotations
7+
import typing
8+
9+
from ......nyan.nyan_structs import MemberOperator
10+
from .....entity_object.conversion.aoc.genie_unit import GenieBuildingLineGroup
11+
from .....entity_object.conversion.converter_object import RawAPIObject
12+
from .....service.conversion import internal_name_lookups
13+
from .....value_object.conversion.forward_ref import ForwardRef
14+
from .....value_object.read.value_members import NoDiffMember
15+
from .util import create_animation_patch, create_command_sound_patch
16+
17+
if typing.TYPE_CHECKING:
18+
from .....entity_object.conversion.converter_object import ConverterObject, \
19+
ConverterObjectGroup
20+
from .....entity_object.conversion.aoc.genie_unit import GenieGameEntityGroup
21+
22+
23+
def apply_continuous_effect_ability(
24+
converter_group: ConverterObjectGroup,
25+
line: GenieGameEntityGroup,
26+
container_obj_ref: str,
27+
command_id: int,
28+
ranged: bool = False,
29+
diff: ConverterObject = None
30+
) -> list[ForwardRef]:
31+
"""
32+
Creates a patch for the ApplyContinuousEffect ability of a line.
33+
34+
:param converter_group: Group that gets the patch.
35+
:param line: Unit/Building line that has the ability.
36+
:param container_obj_ref: Reference of the raw API object the patch is nested in.
37+
:param command_id: The command ID of the AoC command.
38+
:param ranged: Whether the ability is a ranged attack.
39+
:param diff: A diff between two ConvertObject instances.
40+
:returns: The forward references for the generated patches.
41+
"""
42+
head_unit_id = line.get_head_unit_id()
43+
tech_id = converter_group.get_id()
44+
dataset = line.data
45+
46+
patches = []
47+
48+
name_lookup_dict = internal_name_lookups.get_entity_lookups(dataset.game_version)
49+
tech_lookup_dict = internal_name_lookups.get_tech_lookups(dataset.game_version)
50+
command_lookup_dict = internal_name_lookups.get_command_lookups(dataset.game_version)
51+
52+
game_entity_name = name_lookup_dict[head_unit_id][0]
53+
ability_name = command_lookup_dict[command_id][0]
54+
55+
data_changed = False
56+
diff_animation = diff["attack_sprite_id"]
57+
diff_comm_sound = diff["command_sound_id"]
58+
diff_frame_delay = diff["frame_delay"]
59+
if any(not isinstance(value, NoDiffMember) for value in (diff_frame_delay)):
60+
data_changed = True
61+
62+
# Command types Heal, Construct, Repair are not upgraded by lines
63+
64+
if ranged:
65+
diff_min_range = diff["weapon_range_min"]
66+
diff_max_range = diff["weapon_range_max"]
67+
68+
if any(not isinstance(value, NoDiffMember) for value in (
69+
diff_min_range,
70+
diff_max_range
71+
)):
72+
patch_target_ref = f"{game_entity_name}.{ability_name}.Ranged"
73+
patch_target_forward_ref = ForwardRef(line, patch_target_ref)
74+
75+
# Wrapper
76+
wrapper_name = f"Change{game_entity_name}{ability_name}RangedWrapper"
77+
wrapper_ref = f"{container_obj_ref}.{wrapper_name}"
78+
wrapper_raw_api_object = RawAPIObject(wrapper_ref,
79+
wrapper_name,
80+
dataset.nyan_api_objects)
81+
wrapper_raw_api_object.add_raw_parent("engine.util.patch.Patch")
82+
83+
if isinstance(line, GenieBuildingLineGroup):
84+
wrapper_raw_api_object.set_location(("data/game_entity/generic/"
85+
f"{name_lookup_dict[head_unit_id][1]}/"))
86+
wrapper_raw_api_object.set_filename(f"{tech_lookup_dict[tech_id][1]}_upgrade")
87+
88+
else:
89+
wrapper_raw_api_object.set_location(ForwardRef(converter_group,
90+
container_obj_ref))
91+
92+
# Nyan patch
93+
nyan_patch_name = f"Change{game_entity_name}{ability_name}Ranged"
94+
nyan_patch_ref = ForwardRef(line, nyan_patch_name)
95+
nyan_patch_location = ForwardRef(converter_group, wrapper_ref)
96+
nyan_patch_raw_api_object = RawAPIObject(nyan_patch_ref,
97+
nyan_patch_name,
98+
dataset.nyan_api_objects,
99+
nyan_patch_location)
100+
nyan_patch_raw_api_object.add_raw_parent("engine.util.patch.NyanPatch")
101+
nyan_patch_raw_api_object.set_patch_target(patch_target_forward_ref)
102+
103+
if not isinstance(diff_min_range, NoDiffMember):
104+
min_range = diff_min_range.value
105+
nyan_patch_raw_api_object.add_raw_patch_member(
106+
"min_range",
107+
min_range,
108+
"engine.ability.property.type.Ranged",
109+
MemberOperator.ADD)
110+
111+
if not isinstance(diff_max_range, NoDiffMember):
112+
max_range = diff_max_range.value
113+
nyan_patch_raw_api_object.add_raw_patch_member(
114+
"max_range",
115+
max_range,
116+
"engine.ability.property.type.Ranged",
117+
MemberOperator.ADD)
118+
119+
patch_forward_ref = ForwardRef(converter_group, nyan_patch_ref)
120+
wrapper_raw_api_object.add_raw_member("patch",
121+
patch_forward_ref,
122+
"engine.util.patch.Patch")
123+
124+
converter_group.add_raw_api_object(wrapper_raw_api_object)
125+
converter_group.add_raw_api_object(nyan_patch_raw_api_object)
126+
127+
wrapper_forward_ref = ForwardRef(converter_group, wrapper_ref)
128+
patches.append(wrapper_forward_ref)
129+
130+
if not isinstance(diff_animation, NoDiffMember):
131+
diff_animation_id = diff_animation.value
132+
133+
# Nyan patch
134+
patch_target_ref = f"{game_entity_name}.{ability_name}"
135+
nyan_patch_name = f"Change{game_entity_name}{ability_name}"
136+
wrapper, anim_patch_forward_ref = create_animation_patch(
137+
converter_group,
138+
line,
139+
patch_target_ref,
140+
nyan_patch_name,
141+
container_obj_ref,
142+
ability_name,
143+
f"{command_lookup_dict[command_id][1]}_",
144+
[diff_animation_id]
145+
)
146+
patches.append(anim_patch_forward_ref)
147+
148+
if isinstance(line, GenieBuildingLineGroup):
149+
# Store building upgrades next to their game entity definition,
150+
# not in the Age up techs.
151+
wrapper.set_location(("data/game_entity/generic/"
152+
f"{name_lookup_dict[head_unit_id][1]}/"))
153+
wrapper.set_filename(f"{tech_lookup_dict[tech_id][1]}_upgrade")
154+
155+
if not isinstance(diff_comm_sound, NoDiffMember):
156+
diff_comm_sound_id = diff_comm_sound.value
157+
158+
# Nyan patch
159+
patch_target_ref = f"{game_entity_name}.{ability_name}"
160+
nyan_patch_name = f"Change{game_entity_name}{ability_name}"
161+
wrapper, sound_patch_forward_ref = create_command_sound_patch(
162+
converter_group,
163+
line,
164+
patch_target_ref,
165+
nyan_patch_name,
166+
container_obj_ref,
167+
ability_name,
168+
f"{command_lookup_dict[command_id][1]}_",
169+
[diff_comm_sound_id]
170+
)
171+
patches.append(sound_patch_forward_ref)
172+
173+
if isinstance(line, GenieBuildingLineGroup):
174+
# Store building upgrades next to their game entity definition,
175+
# not in the Age up techs.
176+
wrapper.set_location(("data/game_entity/generic/"
177+
f"{name_lookup_dict[head_unit_id][1]}/"))
178+
wrapper.set_filename(f"{tech_lookup_dict[tech_id][1]}_upgrade")
179+
180+
if data_changed:
181+
patch_target_ref = f"{game_entity_name}.{ability_name}"
182+
patch_target_forward_ref = ForwardRef(line, patch_target_ref)
183+
184+
# Wrapper
185+
wrapper_name = f"Change{game_entity_name}{ability_name}Wrapper"
186+
wrapper_ref = f"{container_obj_ref}.{wrapper_name}"
187+
wrapper_raw_api_object = RawAPIObject(wrapper_ref,
188+
wrapper_name,
189+
dataset.nyan_api_objects)
190+
wrapper_raw_api_object.add_raw_parent("engine.util.patch.Patch")
191+
192+
if isinstance(line, GenieBuildingLineGroup):
193+
# Store building upgrades next to their game entity definition,
194+
# not in the Age up techs.
195+
wrapper_raw_api_object.set_location(("data/game_entity/generic/"
196+
f"{name_lookup_dict[head_unit_id][1]}/"))
197+
wrapper_raw_api_object.set_filename(f"{tech_lookup_dict[tech_id][1]}_upgrade")
198+
199+
else:
200+
wrapper_raw_api_object.set_location(ForwardRef(converter_group, container_obj_ref))
201+
202+
# Nyan patch
203+
nyan_patch_name = f"Change{game_entity_name}{ability_name}"
204+
nyan_patch_ref = f"{container_obj_ref}.{wrapper_name}.{nyan_patch_name}"
205+
nyan_patch_location = ForwardRef(converter_group, wrapper_ref)
206+
nyan_patch_raw_api_object = RawAPIObject(nyan_patch_ref,
207+
nyan_patch_name,
208+
dataset.nyan_api_objects,
209+
nyan_patch_location)
210+
nyan_patch_raw_api_object.add_raw_parent("engine.util.patch.NyanPatch")
211+
nyan_patch_raw_api_object.set_patch_target(patch_target_forward_ref)
212+
213+
if not isinstance(diff_frame_delay, NoDiffMember):
214+
if not isinstance(diff_animation, NoDiffMember):
215+
attack_graphic_id = diff_animation.value
216+
217+
else:
218+
attack_graphic_id = diff_animation.ref.value
219+
220+
attack_graphic = dataset.genie_graphics[attack_graphic_id]
221+
frame_rate = attack_graphic.get_frame_rate()
222+
frame_delay = diff_frame_delay.value
223+
application_delay = frame_rate * frame_delay
224+
225+
nyan_patch_raw_api_object.add_raw_patch_member(
226+
"application_delay",
227+
application_delay,
228+
"engine.ability.type.ApplyContinuousEffect",
229+
MemberOperator.ASSIGN
230+
)
231+
232+
patch_forward_ref = ForwardRef(converter_group, nyan_patch_ref)
233+
wrapper_raw_api_object.add_raw_member("patch",
234+
patch_forward_ref,
235+
"engine.util.patch.Patch")
236+
237+
converter_group.add_raw_api_object(wrapper_raw_api_object)
238+
converter_group.add_raw_api_object(nyan_patch_raw_api_object)
239+
240+
wrapper_forward_ref = ForwardRef(converter_group, wrapper_ref)
241+
patches.append(wrapper_forward_ref)
242+
243+
return patches

0 commit comments

Comments
 (0)