1# Copyright 2013-2017 the openage authors. See copying.md for legal info. 2 3# TODO pylint: disable=C,R 4 5from ..dataformat.exportable import Exportable 6from ..dataformat.members import SubdataMember, EnumLookupMember 7from ..dataformat.member_access import READ, READ_EXPORT 8 9 10class Effect(Exportable): 11 name_struct = "tech_effect" 12 name_struct_file = "tech" 13 struct_description = "applied effect for a research technology." 14 15 data_format = [ 16 (READ, "type_id", EnumLookupMember( 17 raw_type = "int8_t", 18 type_name = "effect_apply_type", 19 lookup_dict = { 20 # unused assignage: a = -1, b = -1, c = -1, d = 0 21 -1: "DISABLED", 22 0: "ATTRIBUTE_ABSSET", # if a != -1: a == unit_id, else b == unit_class_id; c = attribute_id, d = new_value 23 1: "RESOURCE_MODIFY", # a == resource_id, if b == 0: then d = absval, else d = relval (for inc/dec) 24 2: "UNIT_ENABLED", # a == unit_id, if b == 0: disable unit, else b == 1: enable unit 25 3: "UNIT_UPGRADE", # a == old_unit_id, b == new_unit_id 26 4: "ATTRIBUTE_RELSET", # if a != -1: unit_id, else b == unit_class_id; c=attribute_id, d=relval 27 5: "ATTRIBUTE_MUL", # if a != -1: unit_id, else b == unit_class_id; c=attribute_id, d=factor 28 6: "RESOURCE_MUL", # a == resource_id, d == factor 29 30 # may mean something different in aok:hd: 31 10: "TEAM_ATTRIBUTE_ABSSET", 32 11: "TEAM_RESOURCE_MODIFY", 33 12: "TEAM_UNIT_ENABLED", 34 13: "TEAM_UNIT_UPGRADE", 35 14: "TEAM_ATTRIBUTE_RELSET", 36 15: "TEAM_ATTRIBUTE_MUL", 37 16: "TEAM_RESOURCE_MUL", 38 39 # these are only used in technology trees, 103 even requires one 40 101: "TECHCOST_MODIFY", # a == research_id, b == resource_id, if c == 0: d==absval else: d == relval 41 102: "TECH_TOGGLE", # d == research_id 42 103: "TECH_TIME_MODIFY", # a == research_id, if c == 0: d==absval else d==relval 43 44 # attribute_id: 45 # 0: hit points 46 # 1: line of sight 47 # 2: garrison capacity 48 # 3: unit size x 49 # 4: unit size y 50 # 5: movement speed 51 # 6: rotation speed 52 # 7: unknown 53 # 8: armor # real_val = val + (256 * armor_id) 54 # 9: attack # real_val = val + (256 * attack_id) 55 # 10: attack reloading time 56 # 11: accuracy percent 57 # 12: max range 58 # 13: working rate 59 # 14: resource carriage 60 # 15: default armor 61 # 16: projectile unit 62 # 17: upgrade graphic (icon), graphics angle 63 # 18: terrain restriction to multiply damage received (always sets) 64 # 19: intelligent projectile aim 1=on, 0=off 65 # 20: minimum range 66 # 21: first resource storage 67 # 22: blast width (area damage) 68 # 23: search radius 69 # 80: boarding energy reload speed 70 # 100: resource cost 71 # 101: creation time 72 # 102: number of garrison arrows 73 # 103: food cost 74 # 104: wood cost 75 # 105: stone cost 76 # 106: gold cost 77 # 107: max total projectiles 78 # 108: garrison healing rate 79 # 109: regeneration rate 80 }, 81 )), 82 (READ, "unit", "int16_t"), # == a 83 (READ, "unit_class_id", "int16_t"), # == b 84 (READ, "attribute_id", "int16_t"), # == c 85 (READ, "amount", "float"), # == d 86 ] 87 88 89class Tech(Exportable): # also called techage in some other tools 90 name_struct = "tech" 91 name_struct_file = "tech" 92 struct_description = "a technology definition." 93 94 data_format = [ 95 (READ, "name", "char[31]"), # always CHUN4 (change unit 4-arg) 96 (READ, "effect_count", "uint16_t"), 97 (READ, "effects", SubdataMember( 98 ref_type=Effect, 99 length="effect_count", 100 )), 101 ] 102 103 104# TODO: add common tech class 105 106class Mode(Exportable): 107 name_struct = "age_tech_tree" 108 name_struct_file = "tech" 109 struct_description = "items available when this age was reached." 110 111 data_format = [ 112 (READ, "mode", EnumLookupMember( # mode for unit_or_research0 113 raw_type = "int32_t", 114 type_name = "building_connection_mode", 115 lookup_dict = { 116 0: "NOTHING", 117 1: "BUILDING", 118 2: "UNIT", 119 3: "RESEARCH", 120 } 121 )), 122 ] 123 124 125class AgeTechTree(Exportable): 126 name_struct = "age_tech_tree" 127 name_struct_file = "tech" 128 struct_description = "items available when this age was reached." 129 130 data_format = [ 131 (READ, "total_unit_tech_groups", "int32_t"), 132 (READ, "id", "int32_t"), 133 # 0=generic 134 # 1=TODO 135 # 2=default 136 # 3=marks as not available 137 # 4=upgrading, constructing, creating 138 # 5=research completed, building built 139 (READ, "status", "int8_t"), 140 ] 141 142 # TODO: Enable conversion for AOE1; replace 6 values below 143 # =========================================================================== 144 # if (GameVersion.aoe_1 or GameVersion.aoe_ror) not in game_versions: 145 # data_format.extend([ 146 # (READ, "building_count", "int8_t"), 147 # (READ, "buildings", "int32_t[building_count]"), 148 # (READ, "unit_count", "int8_t"), 149 # (READ, "units", "int32_t[unit_count]"), 150 # (READ, "research_count", "int8_t"), 151 # (READ, "researches", "int32_t[research_count]"), 152 # ]) 153 # else: 154 # data_format.extend([ 155 # (READ, "building_count", "int8_t"), 156 # (READ, "buildings", "int32_t[40]"), 157 # (READ, "unit_count", "int8_t"), 158 # (READ, "units", "int32_t[40]"), 159 # (READ, "research_count", "int8_t"), 160 # (READ, "researches", "int32_t[40]"), 161 # ]) 162 # =========================================================================== 163 data_format.extend([ 164 (READ, "building_count", "int8_t"), 165 (READ, "buildings", "int32_t[building_count]"), 166 (READ, "unit_count", "int8_t"), 167 (READ, "units", "int32_t[unit_count]"), 168 (READ, "research_count", "int8_t"), 169 (READ, "researches", "int32_t[research_count]"), 170 ]) 171 # =========================================================================== 172 173 data_format.extend([ 174 (READ, "slots_used", "int32_t"), 175 (READ, "unit_researches", "int32_t[10]"), 176 (READ, "modes", SubdataMember( 177 ref_type=Mode, 178 length=10, # number of tile types * 12 179 )), 180 181 (READ, "building_level_count", "int8_t"), 182 ]) 183 184 # TODO: Enable conversion for SWGB; replace "buildings_per_zone", "group_length_per_zone" 185 # =========================================================================== 186 # if (GameVersion.swgb_10 or GameVersion.swgb_cc) in game_versions: 187 # data_format.extend([ 188 # (READ, "buildings_per_zone", "int8_t[20]"), 189 # (READ, "group_length_per_zone", "int8_t[20]"), 190 # ]) 191 # else: 192 # data_format.extend([ 193 # (READ, "buildings_per_zone", "int8_t[10]"), 194 # (READ, "group_length_per_zone", "int8_t[10]"), 195 # ]) 196 # =========================================================================== 197 data_format.extend([ 198 (READ, "buildings_per_zone", "int8_t[10]"), 199 (READ, "group_length_per_zone", "int8_t[10]"), 200 ]) 201 202 data_format.append((READ, "max_age_length", "int8_t")) 203 204 205class BuildingConnection(Exportable): 206 name_struct = "building_connection" 207 name_struct_file = "tech" 208 struct_description = "new available buildings/units/researches when this building was created." 209 210 data_format = [ 211 (READ_EXPORT, "id", "int32_t"), # unit id of the current building 212 # 0=generic 213 # 1=TODO 214 # 2=default 215 # 3=marks as not available 216 # 4=upgrading, constructing, creating 217 # 5=research completed, building built 218 (READ, "status", "int8_t"), # maybe always 2 because we got 2 of them hardcoded below (unit_or_research, mode) 219 ] 220 221 # TODO: Enable conversion for AOE1; replace 6 values below 222 # =========================================================================== 223 # if (GameVersion.aoe_1 or GameVersion.aoe_ror) not in game_versions: 224 # data_format.extend([ 225 # (READ_EXPORT, "building_count", "int8_t"), 226 # (READ, "buildings", "int32_t[building_count]"), # new buildings available when this building was created 227 # (READ_EXPORT, "unit_count", "int8_t"), 228 # (READ, "units", "int32_t[unit_count]"), # new units 229 # (READ_EXPORT, "research_count", "int8_t"), 230 # (READ, "researches", "int32_t[research_count]"), # new researches 231 # ]) 232 # else: 233 # data_format.extend([ 234 # (READ_EXPORT, "building_count", "int8_t"), 235 # (READ, "buildings", "int32_t[40]"), 236 # (READ_EXPORT, "unit_count", "int8_t"), 237 # (READ, "units", "int32_t[40]"), 238 # (READ_EXPORT, "research_count", "int8_t"), 239 # (READ, "researches", "int32_t[40]"), 240 # ]) 241 # =========================================================================== 242 data_format.extend([ 243 (READ_EXPORT, "building_count", "int8_t"), 244 (READ, "buildings", "int32_t[building_count]"), # new buildings available when this building was created 245 (READ_EXPORT, "unit_count", "int8_t"), 246 (READ, "units", "int32_t[unit_count]"), # new units 247 (READ_EXPORT, "research_count", "int8_t"), 248 (READ, "researches", "int32_t[research_count]"), # new researches 249 ]) 250 # =========================================================================== 251 252 data_format.extend([ 253 (READ, "slots_used", "int32_t"), 254 (READ, "unit_researches", "int32_t[10]"), 255 (READ, "modes", SubdataMember( 256 ref_type=Mode, 257 length=10, # number of tile types * 12 258 )), 259 260 (READ, "location_in_age", "int8_t"), # minimum age, in which this building is available 261 (READ, "unit_techs_total", "int8_t[5]"), # total techs for each age (5 ages, post-imp probably counts as one) 262 (READ, "unit_techs_first", "int8_t[5]"), 263 (READ_EXPORT, "line_mode", "int32_t"), # 5: >=1 connections, 6: no connections 264 (READ, "enabled_by_research_id", "int32_t"), # current building is unlocked by this research id, -1=no unlock needed 265 ]) 266 267 268class UnitConnection(Exportable): 269 name_struct = "unit_connection" 270 name_struct_file = "tech" 271 struct_description = "unit updates to apply when activating the technology." 272 273 data_format = [ 274 (READ, "id", "int32_t"), 275 # 0=generic 276 # 1=TODO 277 # 2=default 278 # 3=marks as not available 279 # 4=upgrading, constructing, creating 280 # 5=research completed, building built 281 (READ, "status", "int8_t"), # always 2: default 282 (READ, "upper_building", "int32_t"), # building, where this unit is created 283 284 (READ, "slots_used", "int32_t"), 285 (READ, "unit_researches", "int32_t[10]"), 286 (READ, "modes", SubdataMember( 287 ref_type=Mode, 288 length=10, # number of tile types * 12 289 )), 290 291 (READ, "vertical_lines", "int32_t"), 292 ] 293 294 # TODO: Enable conversion for AOE1; replace "unit_count", "units" 295 # =========================================================================== 296 # if (GameVersion.aoe_1 or GameVersion.aoe_ror) not in game_versions: 297 # data_format.extend([ 298 # (READ, "unit_count", "int8_t"), 299 # (READ, "units", "int32_t[unit_count]"), 300 # ]) 301 # else: 302 # data_format.extend([ 303 # (READ, "unit_count", "int8_t"), 304 # (READ, "units", "int32_t[40]"), 305 # ]) 306 # =========================================================================== 307 data_format.extend([ 308 (READ, "unit_count", "int8_t"), 309 (READ, "units", "int32_t[unit_count]"), 310 ]) 311 312 data_format.extend([ 313 (READ, "location_in_age", "int32_t"), # 0=hidden, 1=first, 2=second 314 (READ, "required_research", "int32_t"), # min amount of researches to be discovered for this unit to be available 315 (READ, "line_mode", "int32_t"), # 0=independent/new in its line, 3=depends on a previous research in its line 316 (READ, "enabling_research", "int32_t"), 317 ]) 318 319 320class ResearchConnection(Exportable): 321 name_struct = "research_connection" 322 name_struct_file = "tech" 323 struct_description = "research updates to apply when activating the technology." 324 325 data_format = [ 326 (READ, "id", "int32_t"), 327 # 0=generic 328 # 1=TODO 329 # 2=default 330 # 3=marks as not available 331 # 4=upgrading, constructing, creating 332 # 5=research completed, building built 333 (READ, "status", "int8_t"), 334 (READ, "upper_building", "int32_t"), 335 ] 336 337 # TODO: Enable conversion for AOE1; replace 6 values below 338 # =========================================================================== 339 # if (GameVersion.aoe_1 or GameVersion.aoe_ror) not in game_versions: 340 # data_format.extend([ 341 # (READ, "building_count", "int8_t"), 342 # (READ, "buildings", "int32_t[building_count]"), 343 # (READ, "unit_count", "int8_t"), 344 # (READ, "units", "int32_t[unit_count]"), 345 # (READ, "research_count", "int8_t"), 346 # (READ, "researches", "int32_t[research_count]"), 347 # ]) 348 # else: 349 # data_format.extend([ 350 # (READ, "building_count", "int8_t"), 351 # (READ, "buildings", "int32_t[40]"), 352 # (READ, "unit_count", "int8_t"), 353 # (READ, "units", "int32_t[40]"), 354 # (READ, "research_count", "int8_t"), 355 # (READ, "researches", "int32_t[40]"), 356 # ]) 357 # =========================================================================== 358 data_format.extend([ 359 (READ, "building_count", "int8_t"), 360 (READ, "buildings", "int32_t[building_count]"), 361 (READ, "unit_count", "int8_t"), 362 (READ, "units", "int32_t[unit_count]"), 363 (READ, "research_count", "int8_t"), 364 (READ, "researches", "int32_t[research_count]"), 365 ]) 366 # =========================================================================== 367 368 data_format.extend([ 369 (READ, "slots_used", "int32_t"), 370 (READ, "unit_researches", "int32_t[10]"), 371 (READ, "modes", SubdataMember( 372 ref_type=Mode, 373 length=10, # number of tile types * 12 374 )), 375 376 (READ, "vertical_line", "int32_t"), 377 (READ, "location_in_age", "int32_t"), # 0=hidden, 1=first, 2=second 378 (READ, "line_mode", "int32_t"), # 0=first age, else other ages. 379 ]) 380