def __init__(self, *args, **kwargs): Effect.__init__(self, *args, **kwargs) max_range_modifier = DogmaModifier( affectee_filter=ModAffecteeFilter.domain_skillrq, affectee_domain=ModDomain.target, affectee_filter_extra_arg=TypeId.gunnery, affectee_attr_id=AttrId.max_range, operator=ModOperator.post_percent, affector_attr_id=AttrId.max_range_bonus) falloff_modifier = DogmaModifier( affectee_filter=ModAffecteeFilter.domain_skillrq, affectee_domain=ModDomain.target, affectee_filter_extra_arg=TypeId.gunnery, affectee_attr_id=AttrId.falloff, operator=ModOperator.post_percent, affector_attr_id=AttrId.falloff_bonus) tracking_speed_modifier = DogmaModifier( affectee_filter=ModAffecteeFilter.domain_skillrq, affectee_domain=ModDomain.target, affectee_filter_extra_arg=TypeId.gunnery, affectee_attr_id=AttrId.tracking_speed, operator=ModOperator.post_percent, affector_attr_id=AttrId.tracking_speed_bonus) self.modifiers = ( *self.modifiers, max_range_modifier, falloff_modifier, tracking_speed_modifier)
def __init__(self, *args, **kwargs): Effect.__init__(self, *args, **kwargs) aoe_cloud_size_modifier = DogmaModifier( affectee_filter=ModAffecteeFilter.owner_skillrq, affectee_domain=ModDomain.target, affectee_filter_extra_arg=TypeId.missile_launcher_operation, affectee_attr_id=AttrId.aoe_cloud_size, operator=ModOperator.post_percent, affector_attr_id=AttrId.aoe_cloud_size_bonus) aoe_velocity_modifier = DogmaModifier( affectee_filter=ModAffecteeFilter.owner_skillrq, affectee_domain=ModDomain.target, affectee_filter_extra_arg=TypeId.missile_launcher_operation, affectee_attr_id=AttrId.aoe_velocity, operator=ModOperator.post_percent, affector_attr_id=AttrId.aoe_velocity_bonus) max_velocity_modifier = DogmaModifier( affectee_filter=ModAffecteeFilter.owner_skillrq, affectee_domain=ModDomain.target, affectee_filter_extra_arg=TypeId.missile_launcher_operation, affectee_attr_id=AttrId.max_velocity, operator=ModOperator.post_percent, affector_attr_id=AttrId.missile_velocity_bonus) explosion_delay_modifier = DogmaModifier( affectee_filter=ModAffecteeFilter.owner_skillrq, affectee_domain=ModDomain.target, affectee_filter_extra_arg=TypeId.missile_launcher_operation, affectee_attr_id=AttrId.explosion_delay, operator=ModOperator.post_percent, affector_attr_id=AttrId.explosion_delay_bonus) self.modifiers = ( *self.modifiers, aoe_cloud_size_modifier, aoe_velocity_modifier, max_velocity_modifier, explosion_delay_modifier)
def _handle_domain_mod(self, exp_row): self._mods.append(DogmaModifier( affectee_filter=ModAffecteeFilter.domain, affectee_domain=self._get_domain(exp_row.arg1.arg2.arg1), affectee_attr_id=self._get_attr_id(exp_row.arg1.arg2.arg2), operator=self._get_operator(exp_row.arg1.arg1), affector_attr_id=self._get_attr_id(exp_row.arg2)))
def _handle_domain_mod(cls, mod_info): return DogmaModifier( affectee_filter=ModAffecteeFilter.domain, affectee_domain=cls._get_domain(mod_info), affectee_attr_id=int(mod_info['modifiedAttributeID']), operator=cls._get_operator(mod_info), affector_attr_id=int(mod_info['modifyingAttributeID']))
def make_mass_modifier(): mass_modifier = DogmaModifier( affectee_filter=ModAffecteeFilter.item, affectee_domain=ModDomain.ship, affectee_attr_id=AttrId.mass, operator=ModOperator.mod_add, affector_attr_id=AttrId.mass_addition) return mass_modifier
def _handle_owner_skillrq_mod(cls, mod_info): return DogmaModifier( affectee_filter=ModAffecteeFilter.owner_skillrq, affectee_domain=cls._get_domain(mod_info), affectee_filter_extra_arg=int(mod_info['skillTypeID']), affectee_attr_id=int(mod_info['modifiedAttributeID']), operator=cls._get_operator(mod_info), affector_attr_id=int(mod_info['modifyingAttributeID']))
def _handle_item_mod(cls, mod_info): return DogmaModifier( affectee_filter=ModAffecteeFilter.item, affectee_domain=cls._get_domain(mod_info), affectee_attr_id=int(mod_info['modifiedAttributeID']), operator=cls._get_operator(mod_info), aggregate_mode=ModAggregateMode.stack, affector_attr_id=int(mod_info['modifyingAttributeID']))
def make_signature_modifier(): signature_modifier = DogmaModifier( affectee_filter=ModAffecteeFilter.item, affectee_domain=ModDomain.ship, affectee_attr_id=AttrId.signature_radius, operator=ModOperator.post_percent, affector_attr_id=AttrId.signature_radius_bonus) return signature_modifier
def _handle_owner_skillrq_mod(self, exp_row): self._mods.append(DogmaModifier( affectee_filter=ModAffecteeFilter.owner_skillrq, affectee_domain=self._get_domain(exp_row.arg1.arg2.arg1.arg1), affectee_filter_extra_arg=self._get_type_id( exp_row.arg1.arg2.arg1.arg2), affectee_attr_id=self._get_attr_id(exp_row.arg1.arg2.arg2), operator=self._get_operator(exp_row.arg1.arg1), affector_attr_id=self._get_attr_id(exp_row.arg2)))
def __modifier_decompress(self, modifier_data): """Reconstruct dogma modifier from python primitives.""" modifier = DogmaModifier(affectee_filter=modifier_data[0], affectee_domain=modifier_data[1], affectee_filter_extra_arg=modifier_data[2], affectee_attr_id=modifier_data[3], operator=modifier_data[4], affector_attr_id=modifier_data[5]) return modifier
def _handle_item_mod(self, exp_row): self._mods.append( DogmaModifier( affectee_filter=ModAffecteeFilter.item, affectee_domain=self._get_domain(exp_row.arg1.arg2.arg1), affectee_attr_id=self._get_attr_id(exp_row.arg1.arg2.arg2), operator=self._get_operator(exp_row.arg1.arg1), aggregate_mode=ModAggregateMode.stack, affector_attr_id=self._get_attr_id(exp_row.arg2)))
def __init__(self, *args, resist_attr_id=None, **kwargs): Effect.__init__(self, *args, resist_attr_id=AttrId.stasis_webifier_resistance, **kwargs) modifier = DogmaModifier(affectee_filter=ModAffecteeFilter.item, affectee_domain=ModDomain.target, affectee_attr_id=AttrId.max_velocity, operator=ModOperator.post_percent, affector_attr_id=AttrId.speed_factor) self.modifiers = (*self.modifiers, modifier)
def make_drone_dmg_modifiers(): modifiers = [] modifiers.append( DogmaModifier(affectee_filter=ModAffecteeFilter.owner_skillrq, affectee_filter_extra_arg=EosTypeId.current_self, affectee_domain=ModDomain.character, affectee_attr_id=AttrId.dmg_mult, operator=ModOperator.post_percent, aggregate_mode=ModAggregateMode.stack, affector_attr_id=AttrId.dmg_mult_bonus)) return modifiers
def make_missile_rof_modifiers(): modifiers = [] modifiers.append( DogmaModifier(affectee_filter=ModAffecteeFilter.domain_skillrq, affectee_filter_extra_arg=EosTypeId.current_self, affectee_domain=ModDomain.ship, affectee_attr_id=AttrId.speed, operator=ModOperator.post_percent, aggregate_mode=ModAggregateMode.stack, affector_attr_id=AttrId.rof_bonus)) return modifiers
def make_rah_modifiers(): rah_modifiers = tuple( DogmaModifier(affectee_filter=ModAffecteeFilter.item, affectee_domain=ModDomain.ship, affectee_attr_id=attr_id, operator=ModOperator.pre_mul, affector_attr_id=attr_id) for attr_id in (AttrId.armor_em_dmg_resonance, AttrId.armor_therm_dmg_resonance, AttrId.armor_kin_dmg_resonance, AttrId.armor_expl_dmg_resonance)) return rah_modifiers
def __init__(self, *args, resist_attr_id=None, **kwargs): Effect.__init__( self, *args, resist_attr_id=AttrId.sensor_dampener_resist, **kwargs) modifier = DogmaModifier( affectee_filter=ModAffecteeFilter.item, affectee_domain=ModDomain.target, affectee_attr_id=AttrId.max_target_range, operator=ModOperator.post_percent, aggregate_mode=ModAggregateMode.stack, affector_attr_id=AttrId.max_target_range_bonus) self.modifiers = (*self.modifiers, modifier)
def make_hardpoint_modifiers(): hardpoint_modifiers = tuple( DogmaModifier(affectee_filter=ModAffecteeFilter.item, affectee_domain=ModDomain.ship, affectee_attr_id=affectee_attr_id, operator=ModOperator.mod_add, aggregate_mode=ModAggregateMode.stack, affector_attr_id=affector_attr_id) for affector_attr_id, affectee_attr_id in ( (AttrId.turret_hardpoint_modifier, AttrId.turret_slots_left), (AttrId.launcher_hardpoint_modifier, AttrId.launcher_slots_left))) return hardpoint_modifiers
def mkmod(self, *args, **kwargs): """Shortcut to instantiating dogma modifier. Args: *args: Arguments which will be used to instantiate modifier. **kwargs: Keyword arguments which will be used to instantiate modifier. Returns: Dogma modifier. """ return DogmaModifier(*args, **kwargs)
def make_slot_modifiers(): slot_modifiers = tuple( DogmaModifier( affectee_filter=ModAffecteeFilter.item, affectee_domain=ModDomain.ship, affectee_attr_id=affectee_attr_id, operator=ModOperator.mod_add, aggregate_mode=ModAggregateMode.stack, affector_attr_id=affector_attr_id) for affector_attr_id, affectee_attr_id in ( (AttrId.hi_slot_modifier, AttrId.hi_slots), (AttrId.med_slot_modifier, AttrId.med_slots), (AttrId.low_slot_modifier, AttrId.low_slots))) return slot_modifiers
def make_missile_dmg_effect(): modifiers = [] for dmg_attr_id in (AttrId.em_dmg, AttrId.therm_dmg, AttrId.kin_dmg, AttrId.expl_dmg): modifiers.append( DogmaModifier( affectee_filter=ModAffecteeFilter.owner_skillrq, affectee_domain=ModDomain.character, affectee_filter_extra_arg=TypeId.missile_launcher_operation, affectee_attr_id=dmg_attr_id, operator=ModOperator.post_mul_immune, aggregate_mode=ModAggregateMode.stack, affector_attr_id=AttrId.missile_dmg_mult)) missile_dmg_effect = EffectFactory.make( effect_id=EosEffectId.char_missile_dmg, category_id=EffectCategoryId.passive, is_offensive=False, is_assistance=False, build_status=EffectBuildStatus.custom, modifiers=tuple(modifiers)) return missile_dmg_effect
def _handle_effects_started(self, msg): item = msg.item effect_ids = msg.effect_ids attr_changes = {} for affector_spec in self.__generate_local_affector_specs( item, effect_ids): # Register the affector spec if isinstance(affector_spec.modifier, BasePythonModifier): self.__subscribe_python_affector_spec(msg.fit, affector_spec) self.__affections.register_local_affector_spec(affector_spec) # Clear values of attributes dependent on the affector spec for affectee_item in self.__affections.get_local_affectee_items( affector_spec): attr_id = affector_spec.modifier.affectee_attr_id if affectee_item.attrs._force_recalc(attr_id): attr_ids = attr_changes.setdefault(affectee_item, set()) attr_ids.add(attr_id) # Register projectors for projector in self.__generate_projectors(item, effect_ids): self.__projections.register_projector(projector) # Register warfare buffs effect_applications = [] item_fleet = msg.fit.fleet for effect_id in effect_ids: effect = item._type_effects[effect_id] if not isinstance(effect, WarfareBuffEffect): continue projector = Projector(item, effect) for buff_id_attr_id in WARFARE_BUFF_ATTRS: try: buff_id = item.attrs[buff_id_attr_id] except KeyError: continue getter = (self.__solar_system.source.cache_handler. get_buff_templates) try: buff_templates = getter(buff_id) except BuffTemplatesFetchError: continue affector_attr_id = WARFARE_BUFF_ATTRS[buff_id_attr_id] if not buff_templates: continue for buff_template in buff_templates: modifier = DogmaModifier._make_from_buff_template( buff_template, affector_attr_id) affector_spec = AffectorSpec(item, effect, modifier) self.__warfare_buffs.add_data_entry( projector, affector_spec) tgt_ships = [] for tgt_fit in self.__solar_system.fits: if (tgt_fit is msg.fit or (item_fleet is not None and tgt_fit.fleet is item_fleet)): tgt_ship = tgt_fit.ship if tgt_ship is not None: tgt_ships.append(tgt_ship) effect_applications.append((projector, tgt_ships)) if attr_changes: self.__publish_attr_changes(attr_changes) # Apply warfare buffs if effect_applications: msgs = [] for projector, tgt_items in effect_applications: msgs.append( EffectApplied(projector.item, projector.effect.id, tgt_items)) msg.fit._publish_bulk(msgs)
def mod(self, *args, **kwargs): """Shortcut to instantiating dogma modifier.""" return DogmaModifier(*args, **kwargs)
def _revise_regular_attr_dependents(self, msg): """Remove calculated attribute values which rely on passed attribute. Removing them allows to recalculate updated value. Here we process all regular dependents, which include dependencies specified via capped attribute map and via affector specs with dogma modifiers. Affector specs with python modifiers are processed separately. """ affections = self.__affections projections = self.__projections effect_unapplications = [] # Unapply warfare buffs for item, attr_ids in msg.attr_changes.items(): for effect in item._type_effects.values(): projector = Projector(item, effect) if projector not in self.__warfare_buffs: continue if not attr_ids.intersection(WARFARE_BUFF_ATTRS): continue tgt_items = self.__projections.get_projector_tgts(projector) effect_unapplications.append((projector, tgt_items)) msgs = [] for projector, tgt_items in effect_unapplications: msgs.append( EffectUnapplied(projector.item, projector.effect.id, tgt_items)) msg.fit._publish_bulk(msgs) attr_changes = {} for item, attr_ids in msg.attr_changes.items(): # Remove values of affectee attributes capped by the changing # attribute for attr_id in attr_ids: for capped_attr_id in item.attrs._cap_map.get(attr_id, ()): if item.attrs._force_recalc(capped_attr_id): attr_changes.setdefault(item, set()).add(capped_attr_id) # Force attribute recalculation when local affector spec # modification changes for affector_spec in self.__generate_local_affector_specs( item, item._running_effect_ids): affector_modifier = affector_spec.modifier # Only dogma modifiers have source attribute specified, python # modifiers are processed separately if (not isinstance(affector_modifier, DogmaModifier) or affector_modifier.affector_attr_id not in attr_ids): continue # Remove values for affectee_item in affections.get_local_affectee_items( affector_spec): attr_id = affector_modifier.affectee_attr_id if affectee_item.attrs._force_recalc(attr_id): attr_changes.setdefault(affectee_item, set()).add(attr_id) # Force attribute recalculation when projected affector spec # modification changes for projector in self.__generate_projectors( item, item._running_effect_ids): tgt_items = projections.get_projector_tgts(projector) # When projector doesn't target any items, then we do not need # to clean anything if not tgt_items: continue for affector_spec in self.__generate_projected_affectors( item, (projector.effect.id, )): affector_modifier = affector_spec.modifier # Only dogma modifiers have source attribute specified, # python modifiers are processed separately if (not isinstance(affector_modifier, DogmaModifier) or affector_modifier.affector_attr_id not in attr_ids): continue for affectee_item in ( affections.get_projected_affectee_items( affector_spec, tgt_items)): attr_id = affector_modifier.affectee_attr_id if affectee_item.attrs._force_recalc(attr_id): attr_changes.setdefault(affectee_item, set()).add(attr_id) # Force attribute recalculation if changed attribute defines # resistance to some effect for projector in projections.get_tgt_projectors(item): effect = projector.effect if effect.resist_attr_id not in attr_ids: continue tgt_items = projections.get_projector_tgts(projector) for affector_spec in self.__generate_projected_affectors( projector.item, (effect.id, )): for affectee_item in ( affections.get_projected_affectee_items( affector_spec, tgt_items)): attr_id = affector_spec.modifier.affectee_attr_id if affectee_item.attrs._force_recalc(attr_id): attr_changes.setdefault(affectee_item, set()).add(attr_id) # Unregister warfare buffs only after composing list of attributes we # should update for projector, tgt_items in effect_unapplications: del self.__warfare_buffs[projector] if attr_changes: self.__publish_attr_changes(attr_changes) # Register warfare buffs effect_applications = [] for item, attr_ids in msg.attr_changes.items(): if not attr_ids.intersection(WARFARE_BUFF_ATTRS): continue item_fleet = item._fit.fleet for effect_id in item._running_effect_ids: effect = item._type_effects[effect_id] if not isinstance(effect, WarfareBuffEffect): continue projector = Projector(item, effect) for buff_id_attr_id in WARFARE_BUFF_ATTRS: try: buff_id = item.attrs[buff_id_attr_id] except KeyError: continue getter = (self.__solar_system.source.cache_handler. get_buff_templates) try: buff_templates = getter(buff_id) except BuffTemplatesFetchError: continue affector_attr_id = WARFARE_BUFF_ATTRS[buff_id_attr_id] if not buff_templates: continue for buff_template in buff_templates: modifier = DogmaModifier._make_from_buff_template( buff_template, affector_attr_id) affector_spec = AffectorSpec(item, effect, modifier) self.__warfare_buffs.add_data_entry( projector, affector_spec) tgt_ships = [] for tgt_fit in self.__solar_system.fits: if (tgt_fit is msg.fit or (item_fleet is not None and tgt_fit.fleet is item_fleet)): tgt_ship = tgt_fit.ship if tgt_ship is not None: tgt_ships.append(tgt_ship) effect_applications.append((projector, tgt_ships)) if attr_changes: self.__publish_attr_changes(attr_changes) # Apply warfare buffs if effect_applications: msgs = [] for projector, tgt_items in effect_applications: msgs.append( EffectApplied(projector.item, projector.effect.id, tgt_items)) msg.fit._publish_bulk(msgs)