Skip to content

Effect

Classes

Effect

Bases: AoE2Object, TriggerComponent

Object for handling an effect.

Source code in AoE2ScenarioParser/objects/data_objects/effect.py
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
class Effect(AoE2Object, TriggerComponent):
    """Object for handling an effect."""
    hidden_attribute = 'effect_type'

    _link_list = [
        RetrieverObjectLinkGroup("Triggers", "trigger_data[__index__].effect_data[__index__]", group=[
            RetrieverObjectLink("effect_type"),
            RetrieverObjectLink("ai_script_goal"),
            RetrieverObjectLink("quantity"),
            RetrieverObjectLink("tribute_list"),
            RetrieverObjectLink("diplomacy"),
            RetrieverObjectLink("legacy_location_object_reference"),
            RetrieverObjectLink("object_list_unit_id"),
            RetrieverObjectLink("source_player"),
            RetrieverObjectLink("target_player"),
            RetrieverObjectLink("technology"),
            RetrieverObjectLink("string_id"),
            RetrieverObjectLink("display_time"),
            RetrieverObjectLink("trigger_id"),
            RetrieverObjectLink("location_x"),
            RetrieverObjectLink("location_y"),
            RetrieverObjectLink("location_object_reference"),
            RetrieverObjectLink("area_x1"),
            RetrieverObjectLink("area_y1"),
            RetrieverObjectLink("area_x2"),
            RetrieverObjectLink("area_y2"),
            RetrieverObjectLink("object_group"),
            RetrieverObjectLink("object_type"),
            RetrieverObjectLink("instruction_panel_position"),
            RetrieverObjectLink("attack_stance"),
            RetrieverObjectLink("time_unit"),
            RetrieverObjectLink("enabled"),
            RetrieverObjectLink("food"),
            RetrieverObjectLink("wood"),
            RetrieverObjectLink("stone"),
            RetrieverObjectLink("gold"),
            RetrieverObjectLink("item_id"),
            RetrieverObjectLink("flash_object"),
            RetrieverObjectLink("force_research_technology"),
            RetrieverObjectLink("visibility_state"),
            RetrieverObjectLink("scroll"),
            RetrieverObjectLink("operation"),
            RetrieverObjectLink("object_list_unit_id_2"),
            RetrieverObjectLink("button_location"),
            RetrieverObjectLink("ai_signal_value"),
            RetrieverObjectLink("object_attributes"),
            RetrieverObjectLink("_variable_ref", link="variable"),
            RetrieverObjectLink("timer"),
            RetrieverObjectLink("facet"),
            RetrieverObjectLink("play_sound"),
            RetrieverObjectLink("player_color", support=Support(since=1.40)),
            RetrieverObjectLink("color_mood", support=Support(since=1.42)),
            RetrieverObjectLink("reset_timer", support=Support(since=1.44)),
            RetrieverObjectLink("object_state", support=Support(since=1.44)),
            RetrieverObjectLink("action_type", support=Support(since=1.44)),
            RetrieverObjectLink("resource_1", support=Support(since=1.54)),
            RetrieverObjectLink("resource_1_quantity", support=Support(since=1.54)),
            RetrieverObjectLink("resource_2", support=Support(since=1.54)),
            RetrieverObjectLink("resource_2_quantity", support=Support(since=1.54)),
            RetrieverObjectLink("resource_3", support=Support(since=1.54)),
            RetrieverObjectLink("resource_3_quantity", support=Support(since=1.54)),
            RetrieverObjectLink("message", commit_callback=_add_trail_if_string_attr_is_used_in_effect),
            RetrieverObjectLink("sound_name", commit_callback=_add_trail_if_string_attr_is_used_in_effect),
            RetrieverObjectLink("selected_object_ids"),
            RetrieverObjectLink("unused_string_1", support=Support(since=1.54)),
            RetrieverObjectLink("unused_string_2", support=Support(since=1.54)),
        ])
    ]

    def __init__(
            self,
            effect_type: int = None,
            ai_script_goal: int = None,
            armour_attack_quantity: int = None,
            armour_attack_class: int = None,
            quantity: int = None,
            tribute_list: int = None,
            diplomacy: int = None,
            legacy_location_object_reference: int = None,
            object_list_unit_id: int = None,
            source_player: int = None,
            target_player: int = None,
            technology: int = None,
            string_id: int = None,
            display_time: int = None,
            trigger_id: int = None,
            location_x: int = None,
            location_y: int = None,
            location_object_reference: int = None,
            area_x1: int = None,
            area_y1: int = None,
            area_x2: int = None,
            area_y2: int = None,
            object_group: int = None,
            object_type: int = None,
            instruction_panel_position: int = None,
            attack_stance: int = None,
            time_unit: int = None,
            enabled: int = None,
            food: int = None,
            wood: int = None,
            stone: int = None,
            gold: int = None,
            item_id: int = None,  # Unused (?)
            flash_object: int = None,
            force_research_technology: int = None,
            visibility_state: int = None,
            scroll: int = None,
            operation: int = None,
            object_list_unit_id_2: int = None,
            button_location: int = None,
            ai_signal_value: int = None,
            object_attributes: int = None,
            variable: int = None,
            timer: int = None,
            facet: int = None,
            play_sound: int = None,
            player_color: int = None,
            color_mood: int = None,
            reset_timer: int = None,
            object_state: int = None,
            action_type: int = None,
            resource_1: int = None,
            resource_1_quantity: int = None,
            resource_2: int = None,
            resource_2_quantity: int = None,
            resource_3: int = None,
            resource_3_quantity: int = None,
            message: str = None,
            sound_name: str = None,
            selected_object_ids: List[int] = None,
            unused_string_1: str = None,
            unused_string_2: str = None,
            # Used for variable retrieval in armour/attack effects (source=variable only)
            _variable_ref: int = None,
            **kwargs
    ):
        super().__init__(**kwargs)

        raise_if_not_int_subclass([object_list_unit_id, technology, object_list_unit_id_2])

        if selected_object_ids is None:
            selected_object_ids = []

        # Set armour/attack flags
        self._armour_attack_source = _get_armour_attack_source(effect_type, object_attributes)

        if self._armour_attack_source == 'variable':
            # If effect created through reading scenario file
            if _variable_ref is not None and variable is None and armour_attack_class is None:
                armour_attack_class, variable = self._split_aa_value(_variable_ref)
            # If created through new_effect with variable and armour_attack_class values
            else:
                armour_attack_class = armour_attack_class or 0
        elif self._armour_attack_source == 'quantity':
            # If effect created through reading scenario file
            if quantity is not None and armour_attack_class is None and armour_attack_quantity is None:
                armour_attack_class, armour_attack_quantity = self._split_aa_value(quantity)
                quantity = None
            # If effect created through new_effect with aa values defined
            elif value_is_valid(armour_attack_class) or value_is_valid(armour_attack_quantity):
                quantity = None
            # If created through new_effect with quantity defined instead of the aa values. Handled by quantity property
            else:
                pass
        else:
            armour_attack_class = armour_attack_quantity = None

        if variable is None:
            variable = _variable_ref if _variable_ref is not None else -1

        area_x1, area_y1, area_x2, area_y2 = validate_coords(area_x1, area_y1, area_x2, area_y2)

        if value_is_valid(legacy_location_object_reference):
            location_object_reference = legacy_location_object_reference

        # Bypass the @property which causes: self._update_armour_attack_flag()
        self._effect_type: int = effect_type
        self.ai_script_goal: int = ai_script_goal
        self.armour_attack_quantity: int = armour_attack_quantity
        self.armour_attack_class: int = armour_attack_class
        self.quantity: int = quantity
        self.tribute_list: int = tribute_list
        self.diplomacy: int = diplomacy
        self.object_list_unit_id: int = object_list_unit_id
        self.source_player: int = source_player
        self.target_player: int = target_player
        self.technology: int = technology
        self.string_id: int = string_id
        self.display_time: int = display_time
        self.trigger_id: int = trigger_id
        self.location_x: int = location_x
        self.location_y: int = location_y
        self.location_object_reference: int = location_object_reference
        self.area_x1: int = area_x1
        self.area_y1: int = area_y1
        self.area_x2: int = area_x2
        self.area_y2: int = area_y2
        self.object_group: int = object_group
        self.object_type: int = object_type
        self.instruction_panel_position: int = instruction_panel_position
        self.attack_stance: int = attack_stance
        self.time_unit: int = time_unit
        self.enabled: int = enabled
        self.food: int = food
        self.wood: int = wood
        self.stone: int = stone
        self.gold: int = gold
        # self.item_id: int = item_id  # Unused (?)
        self.flash_object: int = flash_object
        self.force_research_technology: int = force_research_technology
        self.visibility_state: int = visibility_state
        self.scroll: int = scroll
        self.operation: int = operation
        self.object_list_unit_id_2: int = object_list_unit_id_2
        self.button_location: int = button_location
        self.ai_signal_value: int = ai_signal_value
        self.object_attributes: int = object_attributes
        self.variable: int = variable
        self.timer: int = timer
        self.facet: int = facet
        self.play_sound: int = play_sound
        self.player_color: int = player_color
        self.color_mood: int = color_mood
        self.reset_timer: int = reset_timer
        self.object_state: int = object_state
        self.action_type: int = action_type
        self.resource_1: int = resource_1
        self.resource_1_quantity: int = resource_1_quantity
        self.resource_2: int = resource_2
        self.resource_2_quantity: int = resource_2_quantity
        self.resource_3: int = resource_3
        self.resource_3_quantity: int = resource_3_quantity
        self.message: str = message
        self.sound_name: str = sound_name
        self.selected_object_ids: List[int] = selected_object_ids
        self.unused_string_1: str = unused_string_1
        self.unused_string_2: str = unused_string_2

    @property
    def legacy_location_object_reference(self) -> int:
        """Getter for legacy object_reference location. Always returns `-1`."""
        return -1

    @property
    def player_color(self):
        """Get the player color attribute"""
        return self._player_color

    @player_color.setter
    def player_color(self, value):
        if type(value) in [PlayerColorId, PlayerId]:
            value -= 1
        self._player_color = value

    @property
    def item_id(self):
        """Get the currently selected item_id based on other attributes"""
        if value_is_valid(self.object_list_unit_id):
            return self.object_list_unit_id
        if value_is_valid(self.technology):
            return self.technology
        if value_is_valid(self.tribute_list):
            return self.tribute_list
        return -1

    @item_id.setter
    def item_id(self, value):
        raise ValueError("The `item_id` attribute is always equal to its corresponding attribute."
                         "Please use that attribute (i.e. 'object_list_unit_id' or 'technology' or 'tribute_list').")

    @property
    def effect_type(self):
        """The type of the effect (EffectId dataset)"""
        return self._effect_type

    @effect_type.setter
    def effect_type(self, value):
        self._effect_type = value
        self._update_armour_attack_flag()

    @property
    def object_attributes(self):
        return self._object_attributes

    @object_attributes.setter
    def object_attributes(self, value):
        self._object_attributes = value
        self._update_armour_attack_flag()

    @property
    def _armour_attack_flag(self):
        return self._armour_attack_source is not None

    @property
    def armour_attack_quantity(self):
        """Helper property for handling the armour_attack related values"""
        return self._armour_attack_quantity

    @armour_attack_quantity.setter
    def armour_attack_quantity(self, value):
        if value is not None and value != [] and not self._armour_attack_flag:
            warn("Setting 'effect.armour_attack_quantity' when the effect doesn't use armour/attack attributes "
                 "might result in unintended behaviour.", category=IncorrectArmorAttackUsageWarning)
        self._armour_attack_quantity = value

    @property
    def armour_attack_class(self):
        """Helper property for handling the armour_attack related values"""
        return self._armour_attack_class

    @armour_attack_class.setter
    def armour_attack_class(self, value):
        if value is not None and value != [] and not self._armour_attack_flag:
            warn("Setting 'effect.armour_attack_class' when the effect doesn't use armour/attack attributes "
                 "might result in unintended behaviour.", category=IncorrectArmorAttackUsageWarning)
        self._armour_attack_class = value

    @property
    def quantity(self) -> int:
        """Getter for quantity, even if it is combined with `armour_attack_quantity` and `armour_attack_class`"""
        if self._armour_attack_source == 'quantity':
            return self._merge_aa_values(self.armour_attack_class, self.armour_attack_quantity)
        return self._quantity

    @quantity.setter
    def quantity(self, value):
        # Quantity by default, when unused is [], or
        if self._armour_attack_source == 'quantity' and value not in (None, []):
            warn(
                message="Setting 'effect.quantity' directly in an effect that uses armour/attack attributes "
                        "might result in unintended behaviour.\nPlease use the 'effect.armour_attack_quantity' "
                        "and 'effect.armour_attack_class' attributes instead.",
                category=IncorrectArmorAttackUsageWarning
            )
            self.armour_attack_class, self.armour_attack_quantity = self._split_aa_value(value)
        self._quantity = value

    @property
    def _variable_ref(self) -> int | None:
        """Variable only used for byte retrieval of Effect"""
        if self._armour_attack_source == 'variable':
            return self._merge_aa_values(self.armour_attack_class, self.variable)
        return self.variable

    @property
    def selected_object_ids(self) -> List[int]:
        """Get the current selected objects"""
        return self._selected_object_ids

    @selected_object_ids.setter
    def selected_object_ids(self, val: List[int]):
        if type(val) is int:
            val = [val]
        self._selected_object_ids = val

    def _should_be_displayed(self, attr: str, val: Any) -> bool:
        # Ignore the quantity value in the print statement when flag is True.
        if self._armour_attack_flag and attr == "quantity":
            return False
        if not self._armour_attack_flag and (attr == "armour_attack_quantity" or attr == "armour_attack_class"):
            return False

        return super()._should_be_displayed(attr, val)

    def get_content_as_string(self, include_effect_definition: bool = False) -> str:
        """
        Create a human-readable string showcasing all content of this effect.

        This is also the function that is called when doing: `print(effect)`

        Args:
            include_effect_definition: If the effect meta-data should be added by this function

        Returns:
            The created string
        """
        if self.effect_type not in effects.attributes:  # Unknown effect
            attributes_list = effects.empty_attributes
        else:
            attributes_list = effects.attributes[self.effect_type]

        return_string = ""
        for attribute in attributes_list:
            val = getattr(self, attribute)
            if not self._should_be_displayed(attribute, val):
                continue

            value_string = transform_effect_attr_value(self.effect_type, attribute, val, self._uuid)
            return_string += f"{attribute}: {value_string}\n"

        if return_string == "":
            return "<< No Attributes >>\n"

        if include_effect_definition:
            try:
                effect_name = effects.effect_names[self.effect_type]
            except KeyError:
                effect_name = "Unknown"

            return f"{effect_name}:\n{add_tabs(return_string, 1)}"
        return return_string

    def _update_armour_attack_flag(self):
        self._armour_attack_source = _get_armour_attack_source(self.effect_type, self.object_attributes)

    def _split_aa_value(self, quantity: int) -> Tuple[int, int]:
        """
        A function to convert the initial quantity value to the quantity and armor/attack values.
        Unfortunately this problem has to be solved in the object due to how specific this was implemented in DE.

        Args:
            quantity: the initial quantity value

        Returns:
            The one byte armor/attack class as int and one byte armor/attack quantity as int

        ----

        **Trigger Version 2.4**::

            Quantity value: (3, 5)
            00000000 00000000 00000011 000000101
                                aaq      aac

        Final 2/4 bytes are aaq (1 byte), and aac (1 byte). First 2 are unused. Max value of both is 255.

        **Trigger Version 2.5**::

            Quantity value: (3, 5)
            00000000 00000011 00000000 000000101
              aaq      aaq      aac      aac

        The 4/4 bytes are aaq (2 bytes), and aac (2 bytes). All are used. Max value of both is 65535.

        ----
        """
        trigger_version = getters.get_trigger_version(self._uuid)
        if trigger_version >= 2.5:
            return quantity >> 16, quantity & 65535
        return quantity >> 8, quantity & 255

    def _merge_aa_values(self, aa_class: int, aa_quantity: int) -> int:
        """
        A function to convert the quantity and armor/attack field to a quantity value.
        Unfortunately this problem has to be solved in the object due to how specific this was implemented in DE.

        Args:
            aa_quantity: the armor quantity value
            aa_class: the armor/attack value

        Returns:
            The one byte quantity and one byte armor/attack value
        """
        trigger_version = getters.get_trigger_version(self._uuid)
        if trigger_version >= 2.5:
            return aa_class * 65536 + aa_quantity

        # Would use `aa_class << 8` - but apparently multiplication is faster
        return aa_class * 256 + aa_quantity

    def __str__(self):
        return f"[Effect] {self.get_content_as_string(include_effect_definition=True)}"

Attributes

action_type: int = action_type instance-attribute
Type: int
Value: action_type
ai_script_goal: int = ai_script_goal instance-attribute
Type: int
Value: ai_script_goal
ai_signal_value: int = ai_signal_value instance-attribute
Type: int
Value: ai_signal_value
area_x1: int = area_x1 instance-attribute
Type: int
Value: area_x1
area_x2: int = area_x2 instance-attribute
Type: int
Value: area_x2
area_y1: int = area_y1 instance-attribute
Type: int
Value: area_y1
area_y2: int = area_y2 instance-attribute
Type: int
Value: area_y2
armour_attack_class property writable

Helper property for handling the armour_attack related values

armour_attack_quantity property writable

Helper property for handling the armour_attack related values

attack_stance: int = attack_stance instance-attribute
Type: int
Value: attack_stance
button_location: int = button_location instance-attribute
Type: int
Value: button_location
color_mood: int = color_mood instance-attribute
Type: int
Value: color_mood
diplomacy: int = diplomacy instance-attribute
Type: int
Value: diplomacy
display_time: int = display_time instance-attribute
Type: int
Value: display_time
effect_type property writable

The type of the effect (EffectId dataset)

enabled: int = enabled instance-attribute
Type: int
Value: enabled
facet: int = facet instance-attribute
Type: int
Value: facet
flash_object: int = flash_object instance-attribute
Type: int
Value: flash_object
food: int = food instance-attribute
Type: int
Value: food
force_research_technology: int = force_research_technology instance-attribute
Type: int
Value: force_research_technology
gold: int = gold instance-attribute
Type: int
Value: gold
hidden_attribute = 'effect_type' class-attribute instance-attribute
Value: 'effect_type'
instruction_panel_position: int = instruction_panel_position instance-attribute
Type: int
Value: instruction_panel_position
item_id property writable

Get the currently selected item_id based on other attributes

legacy_location_object_reference: int property
Type: int

Getter for legacy object_reference location. Always returns -1.

location_object_reference: int = location_object_reference instance-attribute
Type: int
Value: location_object_reference
location_x: int = location_x instance-attribute
Type: int
Value: location_x
location_y: int = location_y instance-attribute
Type: int
Value: location_y
message: str = message instance-attribute
Type: str
Value: message
object_attributes property writable
object_group: int = object_group instance-attribute
Type: int
Value: object_group
object_list_unit_id: int = object_list_unit_id instance-attribute
Type: int
Value: object_list_unit_id
object_list_unit_id_2: int = object_list_unit_id_2 instance-attribute
Type: int
Value: object_list_unit_id_2
object_state: int = object_state instance-attribute
Type: int
Value: object_state
object_type: int = object_type instance-attribute
Type: int
Value: object_type
operation: int = operation instance-attribute
Type: int
Value: operation
play_sound: int = play_sound instance-attribute
Type: int
Value: play_sound
player_color property writable

Get the player color attribute

quantity: int property writable
Type: int

Getter for quantity, even if it is combined with armour_attack_quantity and armour_attack_class

reset_timer: int = reset_timer instance-attribute
Type: int
Value: reset_timer
resource_1: int = resource_1 instance-attribute
Type: int
Value: resource_1
resource_1_quantity: int = resource_1_quantity instance-attribute
Type: int
Value: resource_1_quantity
resource_2: int = resource_2 instance-attribute
Type: int
Value: resource_2
resource_2_quantity: int = resource_2_quantity instance-attribute
Type: int
Value: resource_2_quantity
resource_3: int = resource_3 instance-attribute
Type: int
Value: resource_3
resource_3_quantity: int = resource_3_quantity instance-attribute
Type: int
Value: resource_3_quantity
scroll: int = scroll instance-attribute
Type: int
Value: scroll
selected_object_ids: List[int] property writable
Type: List[int]

Get the current selected objects

sound_name: str = sound_name instance-attribute
Type: str
Value: sound_name
source_player: int = source_player instance-attribute
Type: int
Value: source_player
stone: int = stone instance-attribute
Type: int
Value: stone
string_id: int = string_id instance-attribute
Type: int
Value: string_id
target_player: int = target_player instance-attribute
Type: int
Value: target_player
technology: int = technology instance-attribute
Type: int
Value: technology
time_unit: int = time_unit instance-attribute
Type: int
Value: time_unit
timer: int = timer instance-attribute
Type: int
Value: timer
tribute_list: int = tribute_list instance-attribute
Type: int
Value: tribute_list
trigger_id: int = trigger_id instance-attribute
Type: int
Value: trigger_id
unused_string_1: str = unused_string_1 instance-attribute
Type: str
Value: unused_string_1
unused_string_2: str = unused_string_2 instance-attribute
Type: str
Value: unused_string_2
variable: int = variable instance-attribute
Type: int
Value: variable
visibility_state: int = visibility_state instance-attribute
Type: int
Value: visibility_state
wood: int = wood instance-attribute
Type: int
Value: wood

Functions


def __init__(...)

Parameters:

Name Type Description Default
effect_type int - None
ai_script_goal int - None
armour_attack_quantity int - None
armour_attack_class int - None
quantity int - None
tribute_list int - None
diplomacy int - None
legacy_location_object_reference int - None
object_list_unit_id int - None
source_player int - None
target_player int - None
technology int - None
string_id int - None
display_time int - None
trigger_id int - None
location_x int - None
location_y int - None
location_object_reference int - None
area_x1 int - None
area_y1 int - None
area_x2 int - None
area_y2 int - None
object_group int - None
object_type int - None
instruction_panel_position int - None
attack_stance int - None
time_unit int - None
enabled int - None
food int - None
wood int - None
stone int - None
gold int - None
item_id int - None
flash_object int - None
force_research_technology int - None
visibility_state int - None
scroll int - None
operation int - None
object_list_unit_id_2 int - None
button_location int - None
ai_signal_value int - None
object_attributes int - None
variable int - None
timer int - None
facet int - None
play_sound int - None
player_color int - None
color_mood int - None
reset_timer int - None
object_state int - None
action_type int - None
resource_1 int - None
resource_1_quantity int - None
resource_2 int - None
resource_2_quantity int - None
resource_3 int - None
resource_3_quantity int - None
message str - None
sound_name str - None
selected_object_ids List[int] - None
unused_string_1 str - None
unused_string_2 str - None
_variable_ref int - None
kwargs ? - {}
Source code in AoE2ScenarioParser/objects/data_objects/effect.py
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
def __init__(
        self,
        effect_type: int = None,
        ai_script_goal: int = None,
        armour_attack_quantity: int = None,
        armour_attack_class: int = None,
        quantity: int = None,
        tribute_list: int = None,
        diplomacy: int = None,
        legacy_location_object_reference: int = None,
        object_list_unit_id: int = None,
        source_player: int = None,
        target_player: int = None,
        technology: int = None,
        string_id: int = None,
        display_time: int = None,
        trigger_id: int = None,
        location_x: int = None,
        location_y: int = None,
        location_object_reference: int = None,
        area_x1: int = None,
        area_y1: int = None,
        area_x2: int = None,
        area_y2: int = None,
        object_group: int = None,
        object_type: int = None,
        instruction_panel_position: int = None,
        attack_stance: int = None,
        time_unit: int = None,
        enabled: int = None,
        food: int = None,
        wood: int = None,
        stone: int = None,
        gold: int = None,
        item_id: int = None,  # Unused (?)
        flash_object: int = None,
        force_research_technology: int = None,
        visibility_state: int = None,
        scroll: int = None,
        operation: int = None,
        object_list_unit_id_2: int = None,
        button_location: int = None,
        ai_signal_value: int = None,
        object_attributes: int = None,
        variable: int = None,
        timer: int = None,
        facet: int = None,
        play_sound: int = None,
        player_color: int = None,
        color_mood: int = None,
        reset_timer: int = None,
        object_state: int = None,
        action_type: int = None,
        resource_1: int = None,
        resource_1_quantity: int = None,
        resource_2: int = None,
        resource_2_quantity: int = None,
        resource_3: int = None,
        resource_3_quantity: int = None,
        message: str = None,
        sound_name: str = None,
        selected_object_ids: List[int] = None,
        unused_string_1: str = None,
        unused_string_2: str = None,
        # Used for variable retrieval in armour/attack effects (source=variable only)
        _variable_ref: int = None,
        **kwargs
):
    super().__init__(**kwargs)

    raise_if_not_int_subclass([object_list_unit_id, technology, object_list_unit_id_2])

    if selected_object_ids is None:
        selected_object_ids = []

    # Set armour/attack flags
    self._armour_attack_source = _get_armour_attack_source(effect_type, object_attributes)

    if self._armour_attack_source == 'variable':
        # If effect created through reading scenario file
        if _variable_ref is not None and variable is None and armour_attack_class is None:
            armour_attack_class, variable = self._split_aa_value(_variable_ref)
        # If created through new_effect with variable and armour_attack_class values
        else:
            armour_attack_class = armour_attack_class or 0
    elif self._armour_attack_source == 'quantity':
        # If effect created through reading scenario file
        if quantity is not None and armour_attack_class is None and armour_attack_quantity is None:
            armour_attack_class, armour_attack_quantity = self._split_aa_value(quantity)
            quantity = None
        # If effect created through new_effect with aa values defined
        elif value_is_valid(armour_attack_class) or value_is_valid(armour_attack_quantity):
            quantity = None
        # If created through new_effect with quantity defined instead of the aa values. Handled by quantity property
        else:
            pass
    else:
        armour_attack_class = armour_attack_quantity = None

    if variable is None:
        variable = _variable_ref if _variable_ref is not None else -1

    area_x1, area_y1, area_x2, area_y2 = validate_coords(area_x1, area_y1, area_x2, area_y2)

    if value_is_valid(legacy_location_object_reference):
        location_object_reference = legacy_location_object_reference

    # Bypass the @property which causes: self._update_armour_attack_flag()
    self._effect_type: int = effect_type
    self.ai_script_goal: int = ai_script_goal
    self.armour_attack_quantity: int = armour_attack_quantity
    self.armour_attack_class: int = armour_attack_class
    self.quantity: int = quantity
    self.tribute_list: int = tribute_list
    self.diplomacy: int = diplomacy
    self.object_list_unit_id: int = object_list_unit_id
    self.source_player: int = source_player
    self.target_player: int = target_player
    self.technology: int = technology
    self.string_id: int = string_id
    self.display_time: int = display_time
    self.trigger_id: int = trigger_id
    self.location_x: int = location_x
    self.location_y: int = location_y
    self.location_object_reference: int = location_object_reference
    self.area_x1: int = area_x1
    self.area_y1: int = area_y1
    self.area_x2: int = area_x2
    self.area_y2: int = area_y2
    self.object_group: int = object_group
    self.object_type: int = object_type
    self.instruction_panel_position: int = instruction_panel_position
    self.attack_stance: int = attack_stance
    self.time_unit: int = time_unit
    self.enabled: int = enabled
    self.food: int = food
    self.wood: int = wood
    self.stone: int = stone
    self.gold: int = gold
    # self.item_id: int = item_id  # Unused (?)
    self.flash_object: int = flash_object
    self.force_research_technology: int = force_research_technology
    self.visibility_state: int = visibility_state
    self.scroll: int = scroll
    self.operation: int = operation
    self.object_list_unit_id_2: int = object_list_unit_id_2
    self.button_location: int = button_location
    self.ai_signal_value: int = ai_signal_value
    self.object_attributes: int = object_attributes
    self.variable: int = variable
    self.timer: int = timer
    self.facet: int = facet
    self.play_sound: int = play_sound
    self.player_color: int = player_color
    self.color_mood: int = color_mood
    self.reset_timer: int = reset_timer
    self.object_state: int = object_state
    self.action_type: int = action_type
    self.resource_1: int = resource_1
    self.resource_1_quantity: int = resource_1_quantity
    self.resource_2: int = resource_2
    self.resource_2_quantity: int = resource_2_quantity
    self.resource_3: int = resource_3
    self.resource_3_quantity: int = resource_3_quantity
    self.message: str = message
    self.sound_name: str = sound_name
    self.selected_object_ids: List[int] = selected_object_ids
    self.unused_string_1: str = unused_string_1
    self.unused_string_2: str = unused_string_2

def __str__(...)
Source code in AoE2ScenarioParser/objects/data_objects/effect.py
492
493
def __str__(self):
    return f"[Effect] {self.get_content_as_string(include_effect_definition=True)}"

def get_content_as_string(...)

Create a human-readable string showcasing all content of this effect.

This is also the function that is called when doing: print(effect)

Parameters:

Name Type Description Default
include_effect_definition bool

If the effect meta-data should be added by this function

False

Returns:

Type Description
str

The created string

Source code in AoE2ScenarioParser/objects/data_objects/effect.py
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
def get_content_as_string(self, include_effect_definition: bool = False) -> str:
    """
    Create a human-readable string showcasing all content of this effect.

    This is also the function that is called when doing: `print(effect)`

    Args:
        include_effect_definition: If the effect meta-data should be added by this function

    Returns:
        The created string
    """
    if self.effect_type not in effects.attributes:  # Unknown effect
        attributes_list = effects.empty_attributes
    else:
        attributes_list = effects.attributes[self.effect_type]

    return_string = ""
    for attribute in attributes_list:
        val = getattr(self, attribute)
        if not self._should_be_displayed(attribute, val):
            continue

        value_string = transform_effect_attr_value(self.effect_type, attribute, val, self._uuid)
        return_string += f"{attribute}: {value_string}\n"

    if return_string == "":
        return "<< No Attributes >>\n"

    if include_effect_definition:
        try:
            effect_name = effects.effect_names[self.effect_type]
        except KeyError:
            effect_name = "Unknown"

        return f"{effect_name}:\n{add_tabs(return_string, 1)}"
    return return_string

Functions

Modules