コード例 #1
0
    def ConstructHitObject(self, player, dummy, Do):
        """
        Constructs the Hit object depending on the type of hit.

        :param player: The Player object
        :param Do: The DoList object
        :return: Nothing
        """

        if player.PerkReflexes and self.Name == 'Anticipation':
            self.cdMax = 12

        if player.PerkPlantedFeet and self.Name in {
                'Sunshine', 'Death\'s Swiftness'
        }:
            self.Bleed = False
            self.BoostTime = 63
            return

        if self.Standard or self.Channeled:
            DamAvg = AVGCalc.StandardChannelDamAvgCalc(self, player, Do)

            if self.Standard:
                for i in range(0, self.nS):
                    self.Hits.append(self.Hit(self, DamAvg, 1, 1, i, i))

                if self.StunBindDam:
                    StunBindDamAvg = AVGCalc.StandardChannelDamAvgCalc(
                        self, player, Do, 'StunBind', 0)

                    for i in range(0, self.nS):
                        self.HitsStunBind.append(
                            self.Hit(self, StunBindDamAvg, 5, 1, i, i))

            else:
                for i in range(0, self.nS):
                    self.Hits.append(self.Hit(self, DamAvg, 2, 1, i, i))

            if self.SideTarget:
                SideTargetAvg = AVGCalc.StandardChannelDamAvgCalc(
                    self, player, Do, 'SideTarget', 0)

                for i in range(0, self.nS):
                    self.SideTargetAvg.append(
                        self.Hit(self, SideTargetAvg, 6, 1, i, i))

        if self.Bleed:
            DoTAvg = AVGCalc.BleedDamAvgCalc(self, player, Do)

            for i in range(0, self.nD):
                self.DoTHits.append(
                    self.Hit(self, DoTAvg, 3, 1, i, self.nS + i))

        if self.Puncture:
            DoTAvg = AVGCalc.PunctureDamAvgCalc(self, player, Do)

            for i in range(0, self.nD):
                self.DoTHits.append(
                    self.Hit(self, DoTAvg, 4, 1, i, self.nS + i))
コード例 #2
0
def CalcNewAvg(bar, dummy, player, Do, i):

    ##############################################################
    ############# Calculate new avg depending on type ############
    ##############################################################

    if dummy.PHits[i].Type in {7, 8}:
        return dummy.PHits[i].Damage

    IDX = bar.AbilNames.index(
        dummy.PHits[i].Name)  # Spot of the ability on the bar

    if dummy.PHits[i].Name == 'Salt the Wound':
        Avg = AVGCalc.StandardChannelDamAvgCalc(bar.Rotation[IDX], player, Do,
                                                'Salt the Wound',
                                                dummy.PHits[i].Index,
                                                dummy.LastStack)
        dummy.LastStack = 0

    elif dummy.PHits[i].Type in {1, 2}:

        # if dummy.PHits[i].Name == 'Greater Ricochet' and dummy.PHits[i].Target == 1:
        #     nRedundantHits = 3 + player.Cr - dummy.nTarget
        #     Avg = bar.Rotation[IDX].StandardChannelDamAvgCalc(player, Do, 'Greater Ricochet', 0, nRedundantHits)

        if not all(
            [bar.Rotation[IDX].StunBindDam,
             any([dummy.Stun, dummy.Bind])]):
            Avg = AVGCalc.StandardChannelDamAvgCalc(bar.Rotation[IDX], player,
                                                    Do, 'Normal',
                                                    dummy.PHits[i].Index)
        else:
            Avg = AVGCalc.StandardChannelDamAvgCalc(bar.Rotation[IDX], player,
                                                    Do, 'StunBind',
                                                    dummy.PHits[i].Index)

    elif dummy.PHits[i].Type in {3, 4}:

        Avg = AVGCalc.BleedDamAvgCalc(bar.Rotation[IDX], player, Do)

    ##############################################################
    ########### Return the new Average if its not None ###########
    ##############################################################

    if Avg is not None:
        return Avg[0]
    else:
        return None
コード例 #3
0
def PostAttackCleanUp(bar, player, dummy, Do):
    """
    Check for special effects of abilities and clears the current attack cycle list.

    :param bar: The Bar object.
    :param dummy:  The Dummy object.
    :param player: The Player object.
    :param Do: The DoList object.
    """

    # Special effect of Greater Flurry
    if 'Greater Flurry' in dummy.DamageNames and 'Berserk' in bar.AbilNames:
        IDX = bar.AbilNames.index('Berserk')

        if bar.Rotation[IDX].cdStatus:
            bar.Rotation[IDX].cdTime -= 2

    # Special effect of Needle Strike: 1.07x if next abil is standard or channeled hit
    if 'Needle Strike' in dummy.DamageNames:
        IDX = bar.AbilNames.index('Needle Strike')
        player.Boost1 = True
        player.Boost1X = bar.Rotation[IDX].Boost1X

        if Do.HTMLwrite:
            Do.Text += f'<li style="color: {Do.att_color};">Needle Strike boost active!</li>\n'

    # Special effect of Greater Ricochet
    if player.GreaterRicochet:
        IDX = bar.AbilNames.index('Greater Ricochet')  # Spot of the ability on the bar

        Avg = AVGCalc.StandardChannelDamAvgCalc(bar.Rotation[IDX], player, Do, 'Greater Ricochet', -1)
        GRNew = deepcopy(bar.Rotation[IDX])
        GRHit = GRNew.Hit(GRNew, Avg, 7, 1, 0, 0)
        GRHit.Time += 1  # Hit on target delayed with 1 tick

        for i in range(0, player.nGreaterRicochet):
            dummy.PHits[dummy.nPH] = deepcopy(GRHit)  # Apply the hit on main target
            dummy.nPH += 1

        player.GreaterRicochet = False
        player.nGreaterRicochet = 0

    # Clear the list of abilities which have inflicted damage on the dummy in the current tick
    dummy.DamageNames.clear()
コード例 #4
0
def AttackDummy(bar, player, dummy, Do, loop):
    """
    Puts all the hits from the current activated ability on the dummy with timers.

    :param bar: The Bar object.
    :param player: The Player object.
    :param dummy: The Dummy object.
    :param Do: The DoList object.
    :param loop: The Loop object.
    :return: The Ability activated in the current attack cycle.
    """

    FA = bar.Rotation[
        bar.FireN]  # FireAbility: ability to be fired in the current tick

    if loop.CycleFound or not loop.FindCycle:
        player.AbilInfo[FA.Name]['activations'] += 1

    if Do.HTMLwrite:
        if not all([FA.StunBindDam, any([dummy.Stun, dummy.Bind])]):
            Do.Text += f'<li style="color: {Do.att_color};">{FA.Name} activated (normal)\n'
        else:
            Do.Text += f'<li style="color: {Do.imp_color};">{FA.Name} activated (stun&bind)\n'

        Do.Text += f'<li style="color: {Do.att_color};">Adrenaline: {round(bar.Adrenaline, 0)}</li>\n'

    # Depending on the type of ability, get its hits
    if FA.Standard or FA.Channeled:
        if not all([FA.StunBindDam, any([dummy.Stun, dummy.Bind])]):
            dummy.PHits[dummy.nPH:dummy.nPH + FA.nS] = deepcopy(FA.Hits)
        else:
            dummy.PHits[dummy.nPH:dummy.nPH + FA.nS] = deepcopy(
                FA.HitsStunBind)

        if any([FA.Bleed, FA.Puncture]):
            EffectCheck(bar, dummy, player, FA, Do)

    elif FA.Bleed:
        EffectCheck(bar, dummy, player, FA, Do)

    else:  # The ability doesn't do any damage: end this function
        return FA

    # Determine amount of hits pending for dummy, some abilities are cut short to maximise dps
    if not player.Afk and FA.Name == 'Concentrated Blast':
        dummy.nPH += FA.nT - 1
    else:
        dummy.nPH += FA.nT

    # Check for AoE shenanigans
    if any(
        [FA.Name == 'Greater Ricochet',
         all([dummy.nTarget > 1 and FA.AoE])]):
        AoECheck(bar, dummy, player, FA, Do)

    # Check for Greater Chain effect
    if player.GreaterChain and FA.Name != 'Greater Chain':
        if not FA.Bleed:
            Avg = AVGCalc.StandardChannelDamAvgCalc(FA, player, Do, 'Normal',
                                                    0)
            NewHit = deepcopy(FA.Hits[0])
            NewHit.Damage = Avg[0] / 2
        else:
            NewHit = deepcopy(FA.DoTHits[0])
            NewHit.Damage = FA.DoTHits[0].Damage / 2

        NewHit.Name = 'Greater Chain'
        NewHit.Type = 8

        for target in player.GreaterChainTargets:
            NewHit.Target = target
            dummy.PHits[dummy.nPH] = deepcopy(NewHit)
            dummy.nPH += 1

        if not FA.Channeled:
            player.GreaterChain = False
            player.GreaterChainTargets = []
            player.GreaterChainDuration = 0
            player.GreaterChainHitN = 0

    # Attack the dummy if a timer equals 0
    DummyDamage(bar, dummy, player, Do, loop)

    return FA
コード例 #5
0
def DummyDamage(bar, dummy, player, Do, loop):
    """
    Checks if a timer of a hit reached 0, if so, damages the target and checks effects.

    :param bar: The Bar object.
    :param player: The Player object.
    :param dummy: The Dummy object.
    :param Do: The DoList object.
    :param loop: The Loop object.
    """

    for i in range(dummy.nPH - 1, -1, -1):
        if dummy.PHits[i].Time == 0:
            if all([player.GreaterChain, player.ChanAbil]):
                IDX = bar.AbilNames.index(dummy.PHits[i].Name)
                player.GreaterChainHitN += 1

                Avg = AVGCalc.StandardChannelDamAvgCalc(
                    bar.Rotation[IDX], player, Do, 'Normal',
                    player.GreaterChainHitN)

                NewHit = deepcopy(dummy.PHits[i])
                NewHit.Damage = Avg[0] / 2

                NewHit.Name = 'Greater Chain'
                NewHit.Type = 8

                for target in player.GreaterChainTargets:
                    NewHit.Target = target
                    dummy.PHits[dummy.nPH] = deepcopy(NewHit)
                    dummy.nPH += 1

    # Check if dummy takes a hit
    for i in range(dummy.nPH - 1, -1, -1):
        if dummy.PHits[i].Time == 0:

            # Determine bleed damage multiplier
            if dummy.PHits[i].Type == 3 and dummy.Movement and not any(
                [dummy.Stun, dummy.Bind]):
                IDX = bar.AbilNames.index(dummy.PHits[i].Name)
                dummy.PHits[i].Damage *= bar.Rotation[IDX].BleedOnMove

            # Determine average hit damage
            if dummy.PHits[i].Type in {1, 2} and any(
                [player.AbilCritBuff > 0, player.Boost, player.Boost1]):
                HitDamage = CalcNewAvg(bar, dummy, player, Do, i)

                if Do.HTMLwrite and any([player.Boost, player.Boost1]):
                    Do.Text += f'<li style="color: {Do.att_color};">{dummy.PHits[i].Name} hit boosted {player.BoostX * player.Boost1X}x</li>'

                # The single hit damage boost works on the first 2 hits on rapid fire fore some reason
                if any([
                        dummy.PHits[i].Name not in ['Rapid Fire', 'Snap Shot']
                        and player.Boost1, player.Boost1
                        and int(dummy.PHits[i].Index) == 1
                ]):
                    player.Boost1 = False
                    player.Boost1X = 1

            elif dummy.PHits[i].Type in {
                    3, 4
            } and player.BaseBoost > 1 and player.Boost:
                if dummy.PHits[i].Index == 0 and player.Boost1:
                    player.Boost1 = False
                    player.Boost1X = 1

                HitDamage = CalcNewAvg(bar, dummy, player, Do, i)

            else:
                HitDamage = dummy.PHits[i].Damage

            # Add the damage to the total damage
            if dummy.PHits[i].Type != 4:
                dummy.Damage += HitDamage
            else:
                dummy.PunctureDamage += HitDamage

            if loop.CycleFound or not loop.FindCycle:  # If a cycle has been found
                player.AbilInfo[dummy.PHits[i].Name]['damage'] += HitDamage / (
                    (1 + player.AbilCritBuff) * player.BoostX * player.Boost1X)
                player.AbilInfo['Boosted']['damage'] += HitDamage - (
                    HitDamage / ((1 + player.AbilCritBuff) * player.BoostX *
                                 player.Boost1X))

                if dummy.PHits[i].Type != 4:
                    loop.CycleDamage += HitDamage
                else:
                    loop.CyclePunctureDamage += HitDamage

            if Do.HTMLwrite:
                if dummy.nTarget == 1:
                    Do.Text += f'<li style="color: {Do.dam_color};">{dummy.PHits[i].Name} ({Do.TypeDict[dummy.PHits[i].Type]}) damage applied: {round(HitDamage, 3)}</li>\n'
                else:
                    Do.Text += f'<li style="color: {Do.dam_color};">{dummy.PHits[i].Name} ({Do.TypeDict[dummy.PHits[i].Type]}) damage applied on target #{int(dummy.PHits[i].Target)}: {round(HitDamage, 3)}</li>\n'

            # Critical hit chance checks
            if dummy.PHits[i].Name in {'Concentrated Blast', 'Fury'}:
                if player.CritStack == 3:  # If the stack reached 3, reset
                    player.CritStack = 0
                else:  # Increase AbilCritBuff
                    if player.AbilCritBuff < 0.15:  # If the AbilCritBuff is smaller than 15%, increase by 5%
                        player.AbilCritBuff += 0.05
                player.CritStack += 1  # Increase stack

            elif dummy.PHits[i].Name == 'Greater Fury' or all([
                    player.CritAdrenalineBuffTime > 0, dummy.PHits[i].Type
                    in {1, 2}
            ]):
                player.CritStack = 0  # Reset stack

                if player.CritAdrenalineBuffTime > 0:
                    player.CritAdrenalineBuff = True  # We need to perform a check
                    CalcNewAvg(bar, dummy, player, Do, i)
                    bar.Adrenaline += round(player.BasicAdrenalineGain / 1, 0)

                    if Do.HTMLwrite:
                        Do.Text += f'<li style="color: {Do.att_color};">Adrenaline increased by: {round(player.BasicAdrenalineGain / 1, 0)} to: {round(bar.Adrenaline, 0)}</li>\n'

                    player.BasicAdrenalineGain -= round(
                        player.BasicAdrenalineGain / 1, 0)
                    player.AbilCritBuff = 0  # Reset crit buff

                if dummy.PHits[i].Name == 'Greater Fury':
                    player.AbilCritBuff = 0  # Reset crit buff
                    player.GreaterFuryCritCheck = True  # We need to perform a check
                    CalcNewAvg(bar, dummy, player, Do, i)

            elif dummy.PHits[i].Type in {1, 2}:
                player.CritStack = 0  # Reset stack
                player.AbilCritBuff = 0  # Reset crit buff

            # Delete the Hit
            dummy.DamageNames.append(dummy.PHits[i].Name)
            # Shift the current hit to the right and others after that 1 place to the left
            dummy.PHits[i:dummy.nPH - 1], dummy.PHits[
                dummy.nPH - 1] = dummy.PHits[i + 1:dummy.nPH], dummy.PHits[i]
            dummy.nPH -= 1

    # Determine if dummy takes damage outside attack cycle
    if dummy.nPH == 0:
        dummy.PH = False
    else:
        dummy.PH = True

    return None
コード例 #6
0
def EffectCheck(bar, dummy, player, FA, Do):
    """
    Puts the hits from the current activated ability on the dummy with timers (only
    bleeds and punctures).

    :param bar: The Bar object.
    :param player: The Player object.
    :param dummy: The Dummy object.
    :param FA: The Ability activated in the current attack cycle.
    :param Do: The DoList object.
    """

    # Determine whether ability has bleed or puncture effect
    if FA.Bleed:
        dummy.PHits[dummy.nPH + FA.nS:dummy.nPH + FA.nT] = deepcopy(FA.DoTHits)

    elif FA.Puncture:
        # Delete puncture effect from pending hits
        # Standard attack already has been added, thus add it to nDoT during the removal
        dummy.nPH += FA.nS

        # Check every ability for puncture type, if so move the hit to idx dummy.nPH - 1 and move i + 1: dummy.nPH 1 slot to the left
        for i in range(dummy.nPH - 1, -1, -1):
            if dummy.PHits[i].Type == 4:
                dummy.PHits[i:dummy.nPH - 1], dummy.PHits[
                    dummy.nPH - 1] = dummy.PHits[i +
                                                 1:dummy.nPH], dummy.PHits[i]
                dummy.nPH -= 1

        # Decrease nDoT by 1 again for consistency with other effects
        dummy.nPH -= FA.nS

        # Salt the Wound ability effect
        if FA.Name == 'Salt the Wound':
            IDX = bar.AbilNames.index(
                FA.Name)  # Spot of the ability on the bar
            Hit = deepcopy(FA.Hits[0])  # Copy the hit from the ability to fire

            # Calculate its new average
            Hit.Damage = AVGCalc.StandardChannelDamAvgCalc(
                bar.Rotation[IDX], player, Do, 'Salt the Wound',
                FA.Hits[0].Index, dummy.nPuncture)[0]
            dummy.PHits[
                dummy.
                nPH] = Hit  # Put the hit with the new average in the pending hits
            dummy.LastStack = dummy.nPuncture
            dummy.nPuncture = 0  # Reset stack
            dummy.PunctureDuration = 0
            dummy.Puncture = False

            if Do.HTMLwrite:
                Do.Text += f'<li style="color: {Do.stat_color};">Dummy puncture stack reset to 0</li>\n'

            return
        else:  # Else the Greater Dazing Shot ability has been used, change stack value accordingly
            dummy.PunctureDuration = 15
            dummy.Puncture = True

            # Set puncture stack
            if dummy.nPuncture < 10:  # Stacks are capped at 10
                dummy.nPuncture += 1

            if Do.HTMLwrite:
                Do.Text += f'<li style="color: {Do.stat_color};">Dummy puncture stack: {dummy.nPuncture}</li>\n'

        dummy.PHits[dummy.nPH + FA.nS:dummy.nPH + FA.nT] = deepcopy(FA.DoTHits)