示例#1
0
    def __init__(self, name='<buff_noname>', value=0, duration=0, mtype='att', morder=None, modifier=None, hidden=False, source=None):
        self.name = name
        self.__value = value
        self.duration = duration
        self.mod_type = mtype
        self.mod_order = morder or ('chance' if self.mod_type == 'crit' else 'buff')
        self.bufftype = 'misc' if hidden else 'self'

        self.source = source
        if self.source is not None and source[0] != 's' and source[0:2] != 'ds':
            self.bufftime = self._ex_bufftime
        else:
            self.bufftime = self._bufftime
        self.buff_end_timer = Timer(self.buff_end_proc)
        if modifier:
            self.modifier = modifier
            self.get = self.modifier.get
        elif mtype != 'effect':
            self.modifier = Modifier('mod_' + self.name, self.mod_type, self.mod_order, 0)
            self.modifier.get = self.get
        else:
            self.modifier = None
        self.dmg_test_event = Event('dmg_formula')
        self.dmg_test_event.dmg_coef = 1
        self.dmg_test_event.dname = 'test'

        self.hidden = hidden

        self.__stored = 0
        self.__active = 0

        self.buffevent = Event('buff')
示例#2
0
文件: slots.py 项目: Caledor/dl
    def oninit(self, adv):
        super().oninit(adv)
        adv.styx_spirit = 0
        adv.csd_buff = SingleActionBuff("d_compounding_sd", 0.0, -1, "s",
                                        "buff")

        def add_csd(e):
            if not adv.csd_buff.get():
                adv.csd_buff.set(min(2.00, adv.csd_buff.get() + 0.50))
                adv.csd_buff.on()
            else:
                adv.csd_buff.value(min(2.00, adv.csd_buff.get() + 0.50))

        csd_timer = Timer(add_csd, 15, True).on()

        def add_spirit(e):
            if e.index == 3:
                adv.styx_spirit = min(3, adv.styx_spirit + 1)
                log("dx_spirit", adv.styx_spirit)

        Event("dx").listener(add_spirit)

        def reset_spirit(e):
            adv.styx_spirit = 0

        Event("ds").listener(reset_spirit)
        Event("dragon_end").listener(reset_spirit)
示例#3
0
文件: template.py 项目: dl-stuff/dl
 def configure_divine_shift(self,
                            shift_name,
                            max_gauge=1800,
                            shift_cost=560,
                            drain=40,
                            buffs=None):
     self.shift_name = shift_name
     self.comment = f"dragon damage does not work on {shift_name}"
     setattr(
         self,
         shift_name,
         self.dragonform.set_dragondrive(
             ModeManager(
                 group="ddrive",
                 buffs=buffs,
                 x=True,
                 s1=True,
                 s2=True,
             ),
             max_gauge=max_gauge,
             shift_cost=shift_cost,
             drain=drain,
         ),
     )
     Event("dragondrive").listener(self.a_dragondrive_on)
     Event("dragondrive_end").listener(self.a_dragondrive_off)
示例#4
0
 def set_dragondrive(self, dd_buff):
     self.is_dragondrive = True
     self.shift_event = Event('dragondrive')
     self.dragondrive_end_event = Event('dragondrive_end')
     self.max_gauge = 3000
     self.shift_cost = 1200  # does not deduct, but need to have this much pt to shift
     self.dragondrive_buff = dd_buff
     self.dragondrive_timer = Timer(self.d_dragondrive_end)
示例#5
0
 def config_actions(self):
     if self.dform_mode == 1:
         return super().config_actions()
     # should maybe take the actual shift action from the modes
     self.name = "Dragondrive"
     self.d_shift = Shift("dshift", self.name, self.conf.dshift)
     self.shift_event = Event("dragondrive")
     self.end_event = Event("dragondrive_end")
示例#6
0
文件: slots.py 项目: imxtrabored/dl
    def oninit(self, adv):
        if not super().oninit(adv):
            self.adv.blood_moon = 0
            self.adv.moonlit_rage = 0
            self.blood_moon_timer = Timer(self.d_moon_repeat, 3.5, True)
            self.dragon_strike_timer = Timer(self.add_rage, 1.0, True)

            Event("dfs_start").listener(self.dfs_start)
            Event("dfs_charged").listener(self.dfs_charged)
示例#7
0
    def __init__(self, name, conf, adv, ds_proc):
        self.name = name
        self.conf = conf
        self.adv = adv
        self.cancel_by = []
        self.interrupt_by = []
        self.disabled = False
        self.shift_event = Event('dragon')
        self.end_event = Event('dragon_end')

        self.ds_proc = ds_proc
        self.ds_reset()
        self.act_list = []
        self.act_sum = []

        self.dx_list = [
            'dx{}'.format(i) for i in range(1, 6)
            if 'dmg' in self.conf['dx{}'.format(i)]
        ]

        self.ds_event = Event('s')
        self.ds_event.name = 'ds'

        self.action_timer = None

        self.shift_start_time = 0
        self.shift_damage_sum = 0
        self.shift_end_timer = Timer(self.d_shift_end)
        self.idle_event = Event('idle')

        self.c_act_name = None
        self.c_act_conf = None
        self.dracolith_mod = self.adv.Modifier('dracolith', 'att', 'dragon', 0)
        self.dracolith_mod.off()
        self.off_ele_mod = None
        if self.adv.slots.c.ele != self.adv.slots.d.ele:
            self.off_ele_mod = self.adv.Modifier('off_ele', 'att', 'dragon',
                                                 -1 / 3)
            self.off_ele_mod.off()

        self.dragon_gauge = 0
        self.dragon_gauge_val = self.conf.gauge_val
        self.dragon_gauge_timer = Timer(self.auto_gauge,
                                        timeout=max(1, self.conf.gauge_iv),
                                        repeat=1).on()
        self.dragon_gauge_pause_timer = None
        self.dragon_gauge_timer_diff = 0
        self.max_gauge = 1000
        self.shift_cost = 500

        self.shift_count = 0
        self.shift_silence = False

        self.is_dragondrive = False
        self.can_end = True
示例#8
0
文件: modifier.py 项目: Caledor/dl
 def effect_on(self):
     value = self.get()
     if self.mod_type == "defense" and value > 0:
         db = Event("defchain")
         db.source = self.source
         db.on()
         if self.bufftype == "team":
             log("buff", "doublebuff", 15 * self.bufftime())
             if self.bufftime == self._bufftime:
                 self._static.adv.slots.c.set_need_bufftime()
     elif self.mod_type == "maxhp":
         if self._static.adv.sub_mod("maxhp", "buff") < Buff.MAXHP_BUFF_CAP:
             self.modifier.on()
         percent = value * 100
         log("heal", self.name, self._static.adv.max_hp * value,
             "team" if self.bufftype == "team" else "self")
         self._static.adv.add_hp(percent)
     # FIXME: heal formula 1day twust
     elif self.mod_type == "regen" and value != 0:
         self.set_hp_event = Event("set_hp")
         self.set_hp_event.delta = value
         self.regen_timer = Timer(self.hp_regen, 3.9, True).on()
     elif self.mod_type == "heal" and value != 0:
         self.set_hp_event = Event("heal_make")
         self.set_hp_event.name = self.name
         self.set_hp_event.delta = self._static.adv.heal_formula(
             self.source, value)
         self.set_hp_event.target = "team" if self.bufftype == "team" else "self"
         self.regen_timer = Timer(self.hp_regen, 2.9, True).on()
     else:
         return self.modifier and self.modifier.on()
示例#9
0
 def set_dragondrive(self, dd_buff, max_gauge=3000, shift_cost=1200, drain=150):
     self.disabled = False
     self.is_dragondrive = True
     self.shift_event = Event('dragondrive')
     self.dragondrive_end_event = Event('dragondrive_end')
     ratio = max_gauge / self.max_gauge
     self.dragon_gauge *= ratio
     self.dragon_gauge_val *= ratio
     self.max_gauge = max_gauge
     self.shift_cost = shift_cost # does not deduct, but need to have this much pt to shift
     self.drain = drain
     self.dragondrive_buff = dd_buff
     self.dragondrive_timer = Timer(self.d_dragondrive_end)
     return self.dragondrive_buff
示例#10
0
 def __init__(self, name, mod):
     # self.adv = adv
     # self.o_dmg_make = adv.dmg_make
     # self.adv.dmg_make = self.dmg_make
     self.name = name
     self.modifier = mod
     self.modifier.off()
     self.add_event = Event(name)
     self.end_event = Event(f"{name}_end")
     self.stack = 0
     self.queued_stack = 0
     self.has_stack = Selfbuff("has_" + self.name, 1, -1, "effect")
     self.active = set()
     self.disabled = False
     self.extra_tensionable = set()
示例#11
0
    def on(self, duration=None):
        if self.mod_type == 'maxhp':
            max_hp = self._static.adv.mod('maxhp')
            if max_hp >= Buff.MAXHP_CAP:
                return self
            value = self.__value
            mod_val = min(value, max(Buff.MAXHP_CAP - max_hp, 0))
            self._static.adv.set_hp(
                (self._static.adv.hp * max_hp + value * 100) /
                (max_hp + mod_val))

        d = max(-1, (duration or self.duration) * self.bufftime())
        if self.__active == 0:
            self.__active = 1
            if self.__stored == 0:
                self._static.all_buffs.append(self)
                self.__stored = 1
            if d >= 0:
                self.buff_end_timer.on(d)
            proc_type = 'start'
        else:
            if d >= 0:
                self.buff_end_timer.on(d)
            proc_type = 'refresh'

        self.logwrapper(
            self.name,
            f'{self.mod_type}({self.mod_order}): {self.value():.02f}',
            f'buff {proc_type} <{d:.02f}s>')
        value, stack = self.valuestack()
        if stack > 1:
            log('buff', self.name,
                f'{self.mod_type}({self.mod_order}): {value:.02f}',
                f'buff stack <{stack}>')

        if self.mod_type == 'defense':
            Event('defchain').on()
            if self.bufftype == 'team':
                log('buff', 'team_defense', 'proc team doublebuffs')

        if self.mod_type == 'regen':
            # may need to make this part global since game always regen all stacks at same ticks
            self.set_hp_event = Event('set_hp')
            self.set_hp_event.delta = self.get()
            self.regen_timer = Timer(self.hp_regen, 3.9, True)
        else:
            self.effect_on()
        return self
示例#12
0
文件: slots.py 项目: Caledor/dl
    def oninit(self, adv):
        super().oninit(adv)

        def shift_end_prep(e):
            adv.charge_p("shift_end", 100)

        Event("dragon_end").listener(shift_end_prep)
示例#13
0
文件: shadow.py 项目: pfleg/dl
    def oninit(self, adv):
        super().oninit(adv)
        from core.advbase import Event, SingleActionBuff
        Event('dragon_end').listener(self.shift_end_trickery)
        self.trickery = 15
        self.threshold = 25
        self.trickery_buff = SingleActionBuff('d_trickery_buff',
                                              1.80,
                                              1,
                                              's',
                                              'buff',
                                              end_proc=self.check_trickery)
        self.check_trickery()

        if adv.condition('always connect hits'):
            self.dmg_proc_o = adv.dmg_proc
            self.thit = 0

            def dmg_proc(name, amount):
                n_thit = adv.hits // self.threshold
                if n_thit > self.thit:
                    self.add_trickery(n_thit - self.thit)
                    self.thit = n_thit
                self.dmg_proc_o(name, amount)

            adv.dmg_proc = dmg_proc
示例#14
0
    def __init__(self, name, conf, adv, dragon):
        utp_params = adv.conf.c.utp
        # dform_modes
        # 0: ddrive as adventurer
        # 1: ddrive as dragon
        # 2: ddrive as adventurer, with servant
        super().__init__(name, conf, adv, dragon, dform_mode=utp_params[0], unique_dform=True)
        self.shift_mods = []
        self.shift_cost = 0
        self.utp_gauge = 0
        self.ds_final = None

        self.max_utp_gauge = utp_params[1]
        self.utp_shift_req = utp_params[2]
        self.utp_drain = utp_params[3]
        self.utp_infinte = False
        self.utp_event = Event("utp")
        self.log_utp = True

        if self.dform_mode == 1:
            g_logs.log_dact_as_act = True
            for ds in self.shift_skills:
                try:
                    del self.adv.conf[ds]["uses"]
                except KeyError:
                    pass
        else:
            self.ddrive_fs_list = [fsn for fsn, _ in self.adv.conf.find(f"^fs\d*_{DDRIVE}$")]
            self.shift_skills = [sn.split("_")[0] for sn, _ in self.adv.conf.find(f"^s\d*_{DDRIVE}$")]
            self.l_ddrive_end = Listener("act_end", self.d_dragondrive_end, order=0)
            self.l_ddrive_end.off()
            self.ddrive_end_reason = None
示例#15
0
    def oninit(self, adv):
        super().oninit(adv)
        adv.summer_sakuya_flowers = 0
        self.flower_buffs = Summer_Konohana_Sakuya.FLOWER_BUFFS
        if adv.nihilism:
            self.flower_buffs = dict(self.flower_buffs)
            del self.flower_buffs[1]
            del self.flower_buffs[2]
            del self.flower_buffs[3]

        def add_flower(t=None):
            if adv.summer_sakuya_flowers >= 6:
                return
            adv.summer_sakuya_flowers += 1
            try:
                adv.Selfbuff(
                    f"d_sakuya_flower_{adv.summer_sakuya_flowers}",
                    *self.flower_buffs[adv.summer_sakuya_flowers],
                ).on()
            except KeyError:
                pass

        add_flower()
        Timer(add_flower, 60, True).on()
        Event("ds").listener(add_flower)
示例#16
0
文件: slots.py 项目: Caledor/dl
    def oninit(self, adv):
        super().oninit(adv)

        def add_gauge_and_time(t):
            adv.dragonform.charge_gauge(200, dhaste=False)
            adv.dragonform.set_shift_end(5, percent=False, addition=True)

        Event("ds").listener(add_gauge_and_time)
示例#17
0
文件: slots.py 项目: imxtrabored/dl
 def oninit(self, adv):
     super().oninit(adv)
     adv.trickery = Gala_Cat_Sith.MAX_TRICKERY
     if not adv.nihilism:
         self.thit = 0
         self.trickery_buff = SingleActionBuff("d_trickery_buff", 1.80, 1,
                                               "s", "buff").on()
         self.l_hit = Event("hit").listener(self.combo_trickery)
示例#18
0
文件: slots.py 项目: Caledor/dl
 def oninit(self, adv):
     super().oninit(adv)
     sp_regen_timer = Timer(
         lambda _: adv.charge_p("ds_sp", 0.0075, target=["s1", "s2"]), 0.99,
         True)
     sp_regen_buff = EffectBuff("ds_sp", 90, lambda: sp_regen_timer.on(),
                                lambda: sp_regen_timer.off())
     Event("ds").listener(lambda _: sp_regen_buff.on())
示例#19
0
文件: modifier.py 项目: Caledor/dl
    def __init__(
        self,
        name="<buff_noname>",
        value=0,
        duration=0,
        mtype="att",
        morder=None,
        modifier=None,
        hidden=False,
        source=None,
    ):
        self.name = name
        self.__value = value
        self.duration = duration
        self.mod_type = mtype
        self.mod_order = morder or ("chance"
                                    if self.mod_type == "crit" else "buff")
        self.bufftype = "misc" if hidden else "self"

        self.source = source
        if self.source is not None and source[0] != "s" and source[0:2] != "ds":
            self.bufftime = self._ex_bufftime
        else:
            self.bufftime = self._bufftime
        self.buff_end_timer = Timer(self.buff_end_proc)
        if modifier:
            self.modifier = modifier
            self.get = self.modifier.get
        elif mtype != "effect":
            self.modifier = Modifier("mod_" + self.name, self.mod_type,
                                     self.mod_order, 0)
            self.modifier.get = self.get
        else:
            self.modifier = None
        self.dmg_test_event = Event("dmg_formula")
        self.dmg_test_event.dmg_coef = 1
        self.dmg_test_event.dname = "test"

        self.hidden = hidden

        self.__stored = 0
        self.__active = 0

        self.buffevent = Event("buff")
        self.pause_time = -1
        self.refresh_time = -1
示例#20
0
文件: slots.py 项目: imxtrabored/dl
 def oninit(self, adv, buff_name, buff_ele):
     super().oninit(adv)
     self.dp_count = 0
     Event("dp").listener(self.dp_reborn_buff)
     self.reborn_buff = adv.Selfbuff(buff_name, 0.3, 45, buff_ele,
                                     "ele").no_bufftime()
     setattr(
         adv, buff_name,
         adv.Selfbuff(buff_name, 0.3, 45, buff_ele, "ele").no_bufftime())
示例#21
0
文件: slots.py 项目: Caledor/dl
    def oninit(self, adv):
        from core.advbase import Repeat, Fs

        super().oninit(adv)
        adv.gozu_tenno_buff = adv.Selfbuff("gozu_tenno_buff", 0.3, 30, "flame",
                                           "ele").no_bufftime()

        def fs_end(e):
            fs_action = adv.action.getdoing()
            if not isinstance(fs_action, Fs):
                fs_action = adv.action.getprev()
            if isinstance(fs_action, Repeat):
                fs_action = fs_action.parent
            fs_elapsed = now() - fs_action.startup_start
            if fs_elapsed >= 3.0:
                adv.gozu_tenno_buff.on(30)

        Event("fs_end").listener(fs_end, order=0)
        Event("repeat").listener(fs_end, order=0)
示例#22
0
文件: slots.py 项目: Caledor/dl
 def oninit(self, adv):
     super().oninit(adv)
     charge_timer = Timer(
         lambda _: adv.charge_p("ds", 0.091, no_autocharge=True), 0.9, True)
     ds_buff = EffectBuff(
         "ds_sp_regen_zone",
         10,
         lambda: charge_timer.on(),
         lambda: charge_timer.off(),
     )
     Event("ds").listener(lambda _: ds_buff.on())
示例#23
0
文件: shadow.py 项目: qwewqa/dl
    def oninit(self, adv):
        super().oninit(adv)
        self.dm_count = 2

        def dragon_might(t):
            if self.dm_count > 0:
                self.dm_count -= 1
                self.adv.Buff('dc', 0.10, -1).on()

        from core.timeline import Event
        Event('dragon').listener(dragon_might)
示例#24
0
文件: slots.py 项目: imxtrabored/dl
    def oninit(self, adv):
        super().oninit(adv)
        if not adv.nihilism:
            self.joyful_radiance_buff = adv.Selfbuff("joyful_radiance", 0.8,
                                                     -1, "att",
                                                     "passive").on()
            adv.joyful_radiance = 4

            Event("buffskills").listener(self.add_joyful_radiance)

            Timer(self.expire_joyful_radiance, 20, True).on()
示例#25
0
    def __init__(self, name, conf, adv, dragon, dform_mode=-1, unique_dform=False):
        self.name = name
        self.conf = conf
        self.adv = adv
        self.dragon = dragon
        self.dform_mode = dform_mode
        self.unique_dform = unique_dform

        self.shift_start_proc = None
        self.shift_end_proc = None
        self.config_actions()
        # events
        self.status = False
        self.disabled_reasons = set()
        self.dp_event = Event("dp")
        self.shift_end_timer = Timer(self.d_shift_end)
        self.shift_silence_timer = Timer(None, 10)
        self.can_end = True
        self.l_shift = Listener("dshift", self.d_shift_start, order=2)
        self.l_s = Listener("s", self.l_ds_pause, order=0)
        self.l_s_end = Listener("s_end", self.l_ds_resume, order=0)
        self.l_s_final_end = Listener("s_end", self.d_shift_end, order=0)
        self.l_s.off()
        self.l_s_end.off()
        self.l_s_final_end.off()
        self.shift_skills = ("ds1", "ds2")

        self.allow_end_cd = self.conf.allow_end + self.dstime()
        self.shift_end_reason = None

        # mods
        self.dracolith_mod = self.adv.Modifier("dracolith", "ex", "dragon", 0)
        self.dracolith_mod.get = self.ddamage
        self.dracolith_mod.off()
        self.shift_mods = [self.dracolith_mod]
        self.shift_spd_mod = None
        self.off_ele = self.adv.slots.c.ele != self.conf.d.ele
        self.previous_x = DEFAULT

        # gauge
        self.auto_gauge_val = 0.1  # percent
        self.auto_gauge_iv = min(int(self.adv.duration / 12), 15)
        self.dragon_gauge_timer = Timer(self.auto_gauge, timeout=max(1, self.auto_gauge_iv), repeat=1).on()
        self.dragon_gauge_pause_timer = None
        self.dragon_gauge_timer_diff = 0

        self.dragon_gauge = 0
        self.max_dragon_gauge = 1000
        self.shift_cost = 500
        self.log_utp = False

        # dragonbattle
        self.is_dragonbattle = False
示例#26
0
文件: slots.py 项目: Caledor/dl
    def oninit(self, adv):
        super().oninit(adv)

        def chariot_energy(t):
            adv.energy.add(1)

        Timer(chariot_energy, 5, True).on()

        def shift_end_energy(e):
            adv.energy.add(5, team=True)

        Event("dragon_end").listener(shift_end_energy)
示例#27
0
 def oninit(self, adv):
     super().oninit(adv)
     def permanent_curse(e):
         if hasattr(adv, 'afflict_guard') and adv.afflict_guard > 0:
             adv.afflict_guard -= 1
         else:
             adv.skill._static.silence = 1
             adv.dragonform.disabled = True
             from core.log import log
             log('debug', 'permanent_curse')
     from core.timeline import Event
     Event('dragon').listener(permanent_curse)
示例#28
0
文件: modifier.py 项目: dl-stuff/dl
 def __init__(self, meta_args, amp_values, source=None):
     self.amp_id, self.publish_level, self.max_team_level, self.extend_time, self.mod_type, self.mod_order = meta_args
     self.publish_level -= 1
     self.buffs = []
     self.name = f"{self.mod_type}_amp"
     for idx, buffargs in enumerate(amp_values):
         buff = Teambuff(f"{self.name}_seq{idx}", *buffargs, self.mod_type, self.mod_order, source=source).no_bufftime()
         buff.hidden = True
         buff.modifier.buff_capped = False
         self.buffs.append(buff)
     self.max_len = self.publish_level + self.max_team_level
     self.amp_event = Event("amp")
示例#29
0
    def __init__(self, name, conf, adv):
        self.name = name
        self.conf = conf
        self.adv = adv
        self.cancel_by = []
        self.interrupt_by = []
        self.disabled = False
        self.shift_event = Event('dragon')
        self.act_event = Event('dact')
        self.end_event = Event('dragon_end')
        self.delayed = set()

        self.ds_reset()
        self.act_list = []
        self.act_sum = []
        self.repeat_act = False

        self.dx_list = [dx for dx, _ in self.conf.find(r'^dx\d+$')]

        self.ds_event = Event('ds')
        self.ds_event.name = 'ds'
        self.dx_event = Event('dx')

        self.action_timer = None

        self.shift_start_time = 0
        self.shift_end_timer = Timer(self.d_shift_end)
        self.idle_event = Event('idle')

        self.c_act_name = None
        self.c_act_conf = None
        self.dracolith_mod = self.adv.Modifier('dracolith', 'att', 'dragon', 0)
        self.dracolith_mod.get = self.ddamage
        self.dracolith_mod.off()
        self.shift_mods = [self.dracolith_mod]
        self.shift_spd_mod = None

        self.off_ele_mod = None
        if self.adv.slots.c.ele != self.adv.slots.d.ele:
            self.off_ele_mod = self.adv.Modifier('off_ele', 'att', 'dragon', -1/3)
            self.off_ele_mod.off()

        self.dragon_gauge = 0
        self.dragon_gauge_val = self.conf.gauge_val
        self.conf.gauge_iv = min(int(self.adv.duration/12), 15)
        self.dragon_gauge_timer = Timer(self.auto_gauge, timeout=max(1, self.conf.gauge_iv), repeat=1).on()
        self.dragon_gauge_pause_timer = None
        self.dragon_gauge_timer_diff = 0
        self.max_gauge = 1000
        self.shift_cost = 500

        self.shift_count = 0
        self.shift_silence = False

        self.is_dragondrive = False
        self.can_end = True

        self.allow_end_cd = self.conf.allow_end + (self.conf.ds.startup + self.conf.ds.startup) / self.speed()
        self.allow_force_end_timer = Timer(self.set_allow_end, timeout=self.allow_end_cd)
        self.allow_end = False
示例#30
0
    def config_actions(self):
        # merge confs into adv conf
        self.dx_max = 0
        for dx, dxconf in self.conf.find(r"^dx\d+$"):
            self.adv.conf[dx] = dxconf
            self.dx_max = max(self.dx_max, int(dx[2:]))
        self.default_x_loop = self.conf["default_x_loop"] or self.dx_max  # the default combo idx to end combo on
        for fs, fsconf in self.conf.find(r"^dfs\d*(_[A-Za-z0-9]+)?$"):
            self.adv.conf[fs] = fsconf
            if not self.unique_dform:
                for sfn in ("before", "proc"):
                    self.adv.rebind_function(self.dragon, f"{fs}_{sfn}", f"{fs}_{sfn}", overwrite=False)
        self.ds_final = None
        for ds, dsconf in self.conf.find(r"^ds\d*(_[A-Za-z0-9]+)?$"):
            self.adv.conf[ds] = dsconf
            ds_base = ds.split("_")[0]
            if not self.unique_dform:
                for sfn in ("before", "proc"):
                    self.adv.rebind_function(self.dragon, f"{ds_base}_{sfn}", f"{ds_base}_{sfn}", overwrite=False)
            if ds.startswith("ds99") or dsconf.get("final"):
                self.ds_final = ds.split("_")[0]
        # make separate dodge action, may want to handle forward/backward later
        self.d_dodge = Dodge("dodge", self.conf.dodge)
        self.d_shift = Shift("dshift", self.name, self.conf.dshift)
        self.d_end = Shift("dend", self.name, self.conf.dend)

        self.shift_event = Event("dragon")
        self.end_event = Event("dragon_end")

        if abs(self.dform_mode) == 1:
            try:
                self.shift_start_proc = self.dragon.shift_start_proc
            except AttributeError:
                pass
            try:
                self.shift_end_proc = self.dragon.shift_end_proc
            except AttributeError:
                pass