Skip to content

Commit a9ffefb

Browse files
committed
convert: Add support for newest DE2 version .dat file.
1 parent d0d2f59 commit a9ffefb

File tree

6 files changed

+98
-40
lines changed

6 files changed

+98
-40
lines changed

openage/convert/value_object/read/media/datfile/civ.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright 2013-2023 the openage authors. See copying.md for legal info.
1+
# Copyright 2013-2025 the openage authors. See copying.md for legal info.
22

33
# TODO pylint: disable=C,R
44
from __future__ import annotations
@@ -71,9 +71,10 @@ def get_data_format_members(
7171
(READ_GEN, "units", StorageType.ARRAY_CONTAINER, MultisubtypeMember(
7272
type_name = "unit_types",
7373
subtype_definition = (READ_GEN, "unit_type", StorageType.ID_MEMBER, EnumLookupMember(
74-
type_name = "unit_type_id",
75-
lookup_dict = unit.unit_type_lookup,
76-
raw_type = "int8_t",
74+
raw_type = "int8_t",
75+
type_name = "unit_type_id",
76+
lookup_dict = unit.unit_type_lookup,
77+
unknown_lookup_prefix = "UNKNOWN_UNIT_TYPE"
7778
)),
7879
class_lookup = unit.unit_type_class_lookup,
7980
length = "unit_count",

openage/convert/value_object/read/media/datfile/graphic.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright 2013-2023 the openage authors. See copying.md for legal info.
1+
# Copyright 2013-2025 the openage authors. See copying.md for legal info.
22

33
# TODO pylint: disable=C,R
44
from __future__ import annotations
@@ -173,7 +173,8 @@ def get_data_format_members(
173173
(READ_GEN, "layer", StorageType.ID_MEMBER, EnumLookupMember( # originally 40 layers, higher -> drawn on top
174174
raw_type = "int8_t", # -> same layer -> order according to map position.
175175
type_name = "graphics_layer",
176-
lookup_dict = GRAPHICS_LAYER
176+
lookup_dict = GRAPHICS_LAYER,
177+
unknown_lookup_prefix="UNKNOWN_GRAPHICS_LAYER"
177178
)),
178179
(SKIP, "player_color_force_id", StorageType.ID_MEMBER,
179180
"int8_t"), # force given player color

openage/convert/value_object/read/media/datfile/lookup_dicts.py

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright 2021-2024 the openage authors. See copying.md for legal info.
1+
# Copyright 2021-2025 the openage authors. See copying.md for legal info.
22

33
"""
44
Lookup dicts for the EnumLookupMember instances.
@@ -341,9 +341,13 @@
341341
103: "TECH_TIME_MODIFY", # a == research_id, if c == 0: d==absval else d==relval
342342

343343
# unknown; used in DE2 BfG
344-
199: "UNKNOWN",
345-
200: "UNKNOWN",
346-
201: "UNKNOWN",
344+
# used in DE2: BfG and specific to the unique town center upgrades
345+
# same as 0
346+
# 200: "DE2_TOWN_CENTER_ATTRIBUTE_ABSSET",
347+
# same as 4
348+
# 201: "DE2_TOWN_CENTER_ATTRIBUTE_RELSET",
349+
# same as 5
350+
# 202: "DE2_TOWN_CENTER_ATTRIBUTE_MUL",
347351

348352
# attribute_id:
349353
# 0: hit points
@@ -441,6 +445,8 @@
441445
153: "RESOURCE_FOLLOW",
442446
154: "LOOT", # Chieftains tech; looting on killing villagers, monks, trade carts
443447
155: "BOOST_MOVE_AND_ATTACK",
448+
157: "DE2_CHARGE",
449+
158: "DE2_JIAN_SHIELD", # Jian swordsman unique ability; when HP is low: change stats
444450
768: "UNKNOWN_768",
445451
1024: "UNKNOWN_1024",
446452
}
@@ -635,6 +641,7 @@
635641
0x1E: "DE2_UNKNOWN",
636642
0x1F: "SWGB_WATER2",
637643
0x20: "SWGB_ROCK4",
644+
0x31: "DE2_ROCKET_CART_PROJECTILE", # probably created for projectiles to decay properly
638645
}
639646

640647
BLAST_DEFENSE_TYPES = {
@@ -699,6 +706,7 @@
699706
3: "BERSERK",
700707
5: "UNIT",
701708
10: "MOUNTAIN", # mountain (matches occlusion_mask)
709+
13: "DE2_PASTURE", # pasture construction site (from DE2: TTK)
702710
}
703711

704712
SELECTION_EFFECTS = {
@@ -736,6 +744,7 @@
736744
3: "TARGET_ONLY",
737745
6: "UNKNOWN_6",
738746
10: "UNKNOWN_10",
747+
11: "DE2_GRENADIER",
739748
18: "UNKNOWN_18",
740749
34: "UNKNOWN_34",
741750
66: "UNKNOWN_66",

openage/convert/value_object/read/media/datfile/research.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright 2013-2023 the openage authors. See copying.md for legal info.
1+
# Copyright 2013-2025 the openage authors. See copying.md for legal info.
22

33
# TODO pylint: disable=C,R
44
from __future__ import annotations
@@ -33,7 +33,8 @@ def get_data_format_members(
3333
(READ_GEN, "type_id", StorageType.ID_MEMBER, EnumLookupMember(
3434
raw_type="int16_t",
3535
type_name="resource_types",
36-
lookup_dict=RESOURCE_TYPES
36+
lookup_dict=RESOURCE_TYPES,
37+
unknown_lookup_prefix="UNKNOWN_RESOURCE_TYPE"
3738
)), # see unit/resource_cost
3839
(READ_GEN, "amount", StorageType.INT_MEMBER, "int16_t"),
3940
(READ_GEN, "enabled", StorageType.BOOLEAN_MEMBER, "int8_t"),

openage/convert/value_object/read/media/datfile/tech.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright 2013-2024 the openage authors. See copying.md for legal info.
1+
# Copyright 2013-2025 the openage authors. See copying.md for legal info.
22

33
# TODO pylint: disable=C,R
44
from __future__ import annotations
@@ -33,7 +33,8 @@ def get_data_format_members(
3333
(READ_GEN, "type_id", StorageType.ID_MEMBER, EnumLookupMember(
3434
raw_type="uint8_t",
3535
type_name="effect_apply_type",
36-
lookup_dict=EFFECT_APPLY_TYPE
36+
lookup_dict=EFFECT_APPLY_TYPE,
37+
unknown_lookup_prefix="UNKNOWN_EFFECT_APPLY_TYPE"
3738
)),
3839
(READ_GEN, "attr_a", StorageType.INT_MEMBER, "int16_t"),
3940
(READ_GEN, "attr_b", StorageType.INT_MEMBER, "int16_t"),
@@ -93,7 +94,8 @@ def get_data_format_members(
9394
(READ_GEN, "other_connection", StorageType.ID_MEMBER, EnumLookupMember( # mode for unit_or_research0
9495
raw_type="int32_t",
9596
type_name="connection_mode",
96-
lookup_dict=CONNECTION_MODE
97+
lookup_dict=CONNECTION_MODE,
98+
unknown_lookup_prefix="UNKNOWN_CONNECTION_MODE"
9799
)),
98100
]
99101

openage/convert/value_object/read/media/datfile/unit.py

Lines changed: 69 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright 2013-2024 the openage authors. See copying.md for legal info.
1+
# Copyright 2013-2025 the openage authors. See copying.md for legal info.
22

33
# TODO pylint: disable=C,R,too-many-lines
44
from __future__ import annotations
@@ -46,7 +46,8 @@ def get_data_format_members(
4646
(READ_GEN, "type", StorageType.ID_MEMBER, EnumLookupMember(
4747
raw_type="int16_t",
4848
type_name="command_ability",
49-
lookup_dict=COMMAND_ABILITY
49+
lookup_dict=COMMAND_ABILITY,
50+
unknown_lookup_prefix="UNKNOWN_COMBAT_ABILITY"
5051
)),
5152
(READ_GEN, "class_id", StorageType.ID_MEMBER, "int16_t"),
5253
(READ_GEN, "unit_id", StorageType.ID_MEMBER, "int16_t"),
@@ -69,7 +70,8 @@ def get_data_format_members(
6970
# what can be selected as a target for the unit command?
7071
raw_type="int8_t",
7172
type_name="selection_type",
72-
lookup_dict=OWNER_TYPE
73+
lookup_dict=OWNER_TYPE,
74+
unknown_lookup_prefix="UNKNOWN_OWNER_TYPE"
7375
)),
7476
# checks if the targeted unit has > 0 resources
7577
(SKIP, "carry_check", StorageType.BOOLEAN_MEMBER, "int8_t"),
@@ -161,7 +163,8 @@ def get_data_format_members(
161163
(SKIP, "used_mode", StorageType.ID_MEMBER, EnumLookupMember(
162164
raw_type="int8_t",
163165
type_name="resource_handling",
164-
lookup_dict=RESOURCE_HANDLING
166+
lookup_dict=RESOURCE_HANDLING,
167+
unknown_lookup_prefix="UNKNOWN_RESOURCE_HANDLING"
165168
)),
166169
]
167170

@@ -187,7 +190,8 @@ def get_data_format_members(
187190
(SKIP, "apply_mode", StorageType.ID_MEMBER, EnumLookupMember(
188191
raw_type="int8_t",
189192
type_name="damage_draw_type",
190-
lookup_dict=DAMAGE_DRAW_TYPE
193+
lookup_dict=DAMAGE_DRAW_TYPE,
194+
unknown_lookup_prefix="UNKNOWN_DAMAGE_DRAW_TYPE"
191195
)),
192196
]
193197

@@ -209,7 +213,8 @@ def get_data_format_members(
209213
(READ_GEN, "type_id", StorageType.ID_MEMBER, EnumLookupMember(
210214
raw_type="int16_t",
211215
type_name="hit_class",
212-
lookup_dict=ARMOR_CLASS
216+
lookup_dict=ARMOR_CLASS,
217+
unknown_lookup_prefix="UNKNOWN_ARMOR_CLASS"
213218
)),
214219
(READ_GEN, "amount", StorageType.INT_MEMBER, "int16_t"),
215220
]
@@ -232,7 +237,8 @@ def get_data_format_members(
232237
(READ_GEN, "type_id", StorageType.ID_MEMBER, EnumLookupMember(
233238
raw_type="int16_t",
234239
type_name="resource_types",
235-
lookup_dict=RESOURCE_TYPES
240+
lookup_dict=RESOURCE_TYPES,
241+
unknown_lookup_prefix="UNKNOWN_RESOURCE_TYPE"
236242
)),
237243
(READ_GEN, "amount", StorageType.INT_MEMBER, "int16_t"),
238244
(READ_GEN, "enabled", StorageType.BOOLEAN_MEMBER, "int16_t"),
@@ -301,7 +307,8 @@ def get_data_format_members(
301307
(READ_GEN, "unit_class", StorageType.ID_MEMBER, EnumLookupMember(
302308
raw_type="int16_t",
303309
type_name="unit_classes",
304-
lookup_dict=UNIT_CLASSES
310+
lookup_dict=UNIT_CLASSES,
311+
unknown_lookup_prefix="UNKNOWN_UNIT_CLASS"
305312
)),
306313
(READ_GEN, "idle_graphic0", StorageType.ID_MEMBER, "int16_t"),
307314
])
@@ -372,17 +379,20 @@ def get_data_format_members(
372379
(READ_GEN, "elevation_mode", StorageType.ID_MEMBER, EnumLookupMember(
373380
raw_type="int8_t",
374381
type_name="elevation_modes",
375-
lookup_dict=ELEVATION_MODES
382+
lookup_dict=ELEVATION_MODES,
383+
unknown_lookup_prefix="UNKNOWN_ELEVATION_MODE"
376384
)),
377385
(READ_GEN, "visible_in_fog", StorageType.ID_MEMBER, EnumLookupMember(
378386
raw_type="int8_t",
379387
type_name="fog_visibility",
380-
lookup_dict=FOG_VISIBILITY
388+
lookup_dict=FOG_VISIBILITY,
389+
unknown_lookup_prefix="UNKNOWN_FOG_VISIBILITY"
381390
)),
382391
(READ_GEN, "terrain_restriction", StorageType.ID_MEMBER, EnumLookupMember(
383392
raw_type="int16_t", # determines on what type of ground the unit can be placed/walk
384393
type_name="ground_type", # is actually the id of the terrain_restriction entry!
385-
lookup_dict=TERRAIN_RESTRICTIONS
394+
lookup_dict=TERRAIN_RESTRICTIONS,
395+
unknown_lookup_prefix="UNKNOWN_TERRAIN_RESTRICTION"
386396
)),
387397
# determines whether the unit can fly
388398
(READ_GEN, "fly_mode", StorageType.BOOLEAN_MEMBER, "int8_t"),
@@ -394,30 +404,35 @@ def get_data_format_members(
394404
# blast_attack_level.
395405
raw_type="int8_t",
396406
type_name="blast_types",
397-
lookup_dict=BLAST_DEFENSE_TYPES
407+
lookup_dict=BLAST_DEFENSE_TYPES,
408+
unknown_lookup_prefix="UNKNOWN_BLAST_DEFENSE_TYPE"
398409
)),
399410
(SKIP, "combat_level", StorageType.ID_MEMBER, EnumLookupMember(
400411
raw_type="int8_t",
401412
type_name="combat_levels",
402-
lookup_dict=COMBAT_LEVELS
413+
lookup_dict=COMBAT_LEVELS,
414+
unknown_lookup_prefix="UNKNOWN_COMBAT_LEVEL"
403415
)),
404416
(READ_GEN, "interaction_mode", StorageType.ID_MEMBER, EnumLookupMember(
405417
# what can be done with this unit?
406418
raw_type="int8_t",
407419
type_name="interaction_modes",
408-
lookup_dict=INTERACTION_MODES
420+
lookup_dict=INTERACTION_MODES,
421+
unknown_lookup_prefix="UNKNOWN_INTERACTION_MODE"
409422
)),
410423
(SKIP, "map_draw_level", StorageType.ID_MEMBER, EnumLookupMember(
411424
# how does the unit show up on the minimap?
412425
raw_type="int8_t",
413426
type_name="minimap_modes",
414-
lookup_dict=MINIMAP_MODES
427+
lookup_dict=MINIMAP_MODES,
428+
unknown_lookup_prefix="UNKNOWN_MINIMAP_MODE"
415429
)),
416430
(SKIP, "unit_level", StorageType.ID_MEMBER, EnumLookupMember(
417431
# selects the available ui command buttons for the unit
418432
raw_type="int8_t",
419433
type_name="command_attributes",
420-
lookup_dict=UNIT_LEVELS
434+
lookup_dict=UNIT_LEVELS,
435+
unknown_lookup_prefix="UNKNOWN_UNIT_LEVEL"
421436
)),
422437
(SKIP, "attack_reaction", StorageType.FLOAT_MEMBER, "float"),
423438
# palette color id for the minimap
@@ -443,7 +458,8 @@ def get_data_format_members(
443458
(READ_GEN, "obstruction_type", StorageType.ID_MEMBER, EnumLookupMember(
444459
raw_type="int8_t",
445460
type_name="obstruction_types",
446-
lookup_dict=OBSTRUCTION_TYPES
461+
lookup_dict=OBSTRUCTION_TYPES,
462+
unknown_lookup_prefix="UNKNOWN_OBSTRUCTION_TYPE"
447463
)),
448464
(READ_GEN, "obstruction_class", StorageType.ID_MEMBER, "int8_t"),
449465

@@ -466,7 +482,8 @@ def get_data_format_members(
466482
(READ_GEN, "obstruction_type", StorageType.ID_MEMBER, EnumLookupMember(
467483
raw_type="int8_t",
468484
type_name="obstruction_types",
469-
lookup_dict=OBSTRUCTION_TYPES
485+
lookup_dict=OBSTRUCTION_TYPES,
486+
unknown_lookup_prefix="UNKNOWN_OBSTRUCTION_TYPE"
470487
)),
471488
(READ_GEN, "obstruction_class", StorageType.ID_MEMBER, "int8_t"),
472489
])
@@ -476,7 +493,8 @@ def get_data_format_members(
476493
# things that happen when the unit was selected
477494
raw_type="int8_t",
478495
type_name="selection_effects",
479-
lookup_dict=SELECTION_EFFECTS
496+
lookup_dict=SELECTION_EFFECTS,
497+
unknown_lookup_prefix="UNKNOWN_SELECTION_EFFECT"
480498
)),
481499
# 0: default, -16: fish trap, farm, 52: deadfarm, OLD-*, 116: flare,
482500
# whale, dolphin -123: fish
@@ -518,7 +536,8 @@ def get_data_format_members(
518536
(SKIP, "old_attack_mode", StorageType.ID_MEMBER, EnumLookupMember( # obsolete, as it's copied when converting the unit
519537
raw_type="int8_t", # things that happen when the unit was selected
520538
type_name="attack_modes",
521-
lookup_dict=ATTACK_MODES
539+
lookup_dict=ATTACK_MODES,
540+
unknown_lookup_prefix="UNKNOWN_ATTACK_MODE"
522541
)),
523542
# leftover from alpha. would et units change terrain under them
524543
(SKIP, "convert_terrain", StorageType.INT_MEMBER, "int8_t"),
@@ -781,7 +800,8 @@ def get_data_format_members(
781800
# the accessible values on the specified terrain restriction
782801
raw_type="int16_t",
783802
type_name="boundary_ids",
784-
lookup_dict=BOUNDARY_IDS
803+
lookup_dict=BOUNDARY_IDS,
804+
unknown_lookup_prefix="UNKNOWN_BOUNDARY_ID"
785805
)),
786806
])
787807

@@ -807,7 +827,8 @@ def get_data_format_members(
807827
# blasts damage units that have higher or same blast_defense_level
808828
raw_type="uint8_t",
809829
type_name="range_damage_type",
810-
lookup_dict=BLAST_OFFENSE_TYPES
830+
lookup_dict=BLAST_OFFENSE_TYPES,
831+
unknown_lookup_prefix="UNKNOWN_BLAST_OFFENSE_TYPE"
811832
)),
812833
# minimum range that this projectile requests for display
813834
(READ_GEN, "weapon_range_min", StorageType.FLOAT_MEMBER, "float"),
@@ -825,7 +846,14 @@ def get_data_format_members(
825846
])
826847

827848
if game_version.edition.game_id == "AOE2DE":
828-
data_format.append((READ_GEN, "blast_damage", StorageType.FLOAT_MEMBER, "float"))
849+
data_format.extend([
850+
(READ_GEN, "blast_damage", StorageType.FLOAT_MEMBER, "float"),
851+
(SKIP, "damage_reflect", StorageType.FLOAT_MEMBER, "float"),
852+
(SKIP, "friendly_fire_damage", StorageType.FLOAT_MEMBER, "float"),
853+
(SKIP, "interrupt_frame", StorageType.INT_MEMBER, "int16_t"),
854+
(SKIP, "garrison_firepower", StorageType.FLOAT_MEMBER, "float"),
855+
(SKIP, "attack_graphic1", StorageType.ID_MEMBER, "int16_t"),
856+
])
829857

830858
return data_format
831859

@@ -923,7 +951,8 @@ def get_data_format_members(
923951
(READ_GEN, "creatable_type", StorageType.ID_MEMBER, EnumLookupMember(
924952
raw_type="uint8_t",
925953
type_name="creatable_types",
926-
lookup_dict=CREATABLE_TYPES
954+
lookup_dict=CREATABLE_TYPES,
955+
unknown_lookup_prefix="UNKNOWN_CREATABLE_TYPE"
927956
)),
928957
# if building: "others" tab in editor, if living unit: "heroes" tab,
929958
# regenerate health + monk immunity
@@ -939,10 +968,24 @@ def get_data_format_members(
939968
(READ_GEN, "spawn_graphic_id", StorageType.ID_MEMBER, "int16_t"),
940969
(READ_GEN, "upgrade_graphic_id", StorageType.ID_MEMBER, "int16_t"),
941970
(READ_GEN, "hero_glow_graphic_id", StorageType.ID_MEMBER, "int16_t"),
971+
(READ_GEN, "idle_attack_graphic_id", StorageType.ID_MEMBER, "int16_t"),
942972
(READ_GEN, "max_charge", StorageType.FLOAT_MEMBER, "float"),
943973
(READ_GEN, "charge_regen_rate", StorageType.FLOAT_MEMBER, "float"),
944974
(READ_GEN, "charge_cost", StorageType.ID_MEMBER, "int16_t"),
945975
(READ_GEN, "charge_type", StorageType.ID_MEMBER, "int16_t"),
976+
977+
(READ_GEN, "charge_target", StorageType.ID_MEMBER, "int16_t"),
978+
(READ_GEN, "charge_projectile_id", StorageType.ID_MEMBER, "int32_t"),
979+
(READ_GEN, "attack_priority", StorageType.ID_MEMBER, "int8_t"),
980+
(READ_GEN, "invulnerability_level", StorageType.FLOAT_MEMBER, "float"),
981+
982+
(READ_GEN, "button_icon_id", StorageType.ID_MEMBER, "int16_t"),
983+
# Short tooltip
984+
(READ_GEN, "button_tooltip_id0", StorageType.ID_MEMBER, "int32_t"),
985+
# Extended tooltip
986+
(READ_GEN, "button_tooltip_id1", StorageType.ID_MEMBER, "int32_t"),
987+
(READ_GEN, "button_hotkey_action", StorageType.ID_MEMBER, "int16_t"),
988+
946989
(READ_GEN, "min_convert_mod", StorageType.FLOAT_MEMBER, "float"),
947990
(READ_GEN, "max_convert_mod", StorageType.FLOAT_MEMBER, "float"),
948991
(READ_GEN, "convert_chance_mod", StorageType.FLOAT_MEMBER, "float"),
@@ -1054,7 +1097,8 @@ def get_data_format_members(
10541097
(READ_GEN, "garrison_type", StorageType.BITFIELD_MEMBER, EnumLookupMember(
10551098
raw_type="int8_t",
10561099
type_name="garrison_types",
1057-
lookup_dict=GARRISON_TYPES
1100+
lookup_dict=GARRISON_TYPES,
1101+
unknown_lookup_prefix="UNKNOWN_GARRISON_TYPE"
10581102
)),
10591103
(READ_GEN, "garrison_heal_rate", StorageType.FLOAT_MEMBER, "float"),
10601104
(SKIP, "garrison_repair_rate", StorageType.FLOAT_MEMBER, "float"),

0 commit comments

Comments
 (0)