{bolts && bolts.map((value, index) => {
                  if (!value) {
                    return null;
                  }

                  return (
                    <tr>
                      <td style={{ width: '30%', paddingLeft: 50 }}>
                        <SpellLink id={ability.guid} icon={false}>
                          <Icon icon={ability.abilityIcon} />{' '}
                          {ability.name} bolt {index + 1}
                        </SpellLink>
                      </td>
                      <td style={{ paddingRight: 5, textAlign: 'right', whiteSpace: 'nowrap' }}>
                        {formatPercentage(value.effective / currentTotal)} %
                      </td>
                      <td style={{ width: '70%', paddingLeft: 50 }}>
                        <div
                          className="performance-bar"
                          style={{ width: `${value.effective / healing.effective * 100}%` }}
                        />
                      </td>
                      <td style={{ textAlign: 'right', whiteSpace: 'nowrap' }}>
                        <dfn data-tip={`Total: ${formatNumber(value)}`}>
                          {formatNumber(value.effective / parser.fightDuration * 1000)} HPS
                        </dfn>
                      </td>
                      <td style={{ textAlign: 'right', whiteSpace: 'nowrap' }}>
                        {formatPercentage(value.overheal / healing.raw)} %
                      </td>
                    </tr>
                  );
                })}
Esempio n. 2
0
 const row = (abilityData) => {
   const { ability, totalDmg, largestSpike } = abilityData;
   return (
     <tr key={ability.guid}>
       <td>
         <div className="flex performance-bar-container"
           data-tip={`Total Damage Taken: ${formatNumber(totalDmg)} of ${formatNumber(this.props.total)}.`} >
           <div
             className={`flex-sub performance-bar ${specClassName}-bg`}
             style={{ width: `${(totalDmg - largestSpike) / this.props.total * 100}%` }}
           />
           <div
             className="flex-sub performance-bar Hunter-bg"
             style={{ width: `${(largestSpike / this.props.total * 100)}%`, opacity: 0.4 }}
           />
         </div>
       </td>
       <td>
         <SpellLink id={ability.guid} icon={false}>
           <Icon icon={ability.abilityIcon} alt={ability.name} /> {ability.name}
         </SpellLink>
       </td>
       <td>
         {formatNumber(totalDmg)}
       </td>
       <td>
         {formatNumber(largestSpike)}
       </td>
     </tr>
   );
 };
Esempio n. 3
0
  item() {
    const damageAbilities = [[SPELLS.MULTISHOT.id], [SPELLS.ARCANE_SHOT.id], [SPELLS.SIDEWINDERS_DAMAGE.id]];
    const generatingAbilities = [[SPELLS.MULTISHOT_FOCUSMODULE.id], [SPELLS.ARCANE_SHOT_FOCUSMODULE.id], [SPELLS.SIDEWINDERS_TALENT.id]];

    const totalDamageIncrease = damageAbilities.reduce((total, ability) => total + this.damageFromGenerators[ability].bonusDmg, 0);
    const totalExtraFocusGenerated = generatingAbilities.reduce((total, ability) => total + this.focusGeneratorCasts[ability].actualGain, 0);
    const totalPotentialFocusGain = generatingAbilities.reduce((total, ability) => total + this.focusGeneratorCasts[ability].potentialGain, 0);

    let tooltipText = `This shows a breakdown of T21 <ul>`;
    tooltipText += (this.arcaneBonusDamage > 0 || this.arcanePotentialFocusGain > 0) ? `<li>Arcane Shot: <ul><li>Damage gain: ${formatNumber(this.arcaneBonusDamage)}</li><li>Focus gain: ${formatNumber(this.arcaneActualFocusGain)} out of ${formatNumber(this.arcanePotentialFocusGain)} possible</li></ul></li>` : '';
    tooltipText += (this.multiBonusDamage > 0 || this.multiPotentialFocusGain > 0) ? `<li>Multishot: <ul><li>Damage gain: ${formatNumber(this.multiBonusDamage)}</li><li>Focus gain: ${formatNumber(this.multiActualFocusGain)} out of ${formatNumber(this.multiPotentialFocusGain)} possible</li></ul></li>` : '';
    tooltipText += (this.sidewindersBonusDamage > 0 || this.sidewindersPotentialFocusGain > 0) ? `<li>Sidewinders: <ul><li>Damage gain: ${formatNumber(this.sidewindersBonusDamage)}</li><li>Focus gain: ${formatNumber(this.sidewindersActualFocusGain)} out of ${formatNumber(this.sidewindersPotentialFocusGain)} possible</li></ul></li>` : '';
    tooltipText += `</ul>`;
    return {
      id: `spell-${SPELLS.HUNTER_MM_T21_2P_BONUS.id}`,
      icon: <SpellIcon id={SPELLS.HUNTER_MM_T21_2P_BONUS.id} />,
      title: <SpellLink id={SPELLS.HUNTER_MM_T21_2P_BONUS.id} icon={false} />,
      result: (
        <dfn data-tip={tooltipText}>
          Focus gain: {formatNumber(totalExtraFocusGenerated)} / {formatNumber(totalPotentialFocusGain)} possible<br />
          <ItemDamageDone amount={totalDamageIncrease} />
        </dfn>
      ),
    };
  }
Esempio n. 4
0
  statistic() {
    const erPercHPS = formatPercentage(this.owner.getPercentageOfTotalHealingDone(this.healing));
    const erHPS = formatNumber(this.healing / this.owner.fightDuration * 1000);
    const erGainPerRefresh = Math.round(this.secsGained / this.refreshedRenews * 100) / 100;

    //
    return this.active && (
      <StatisticBox
        icon={<SpellIcon id={SPELLS.ENDURING_RENEWAL_TALENT.id} />}
        value={`${erHPS} HPS`}
        label={(
          <dfn data-tip={`
            Healing done on targets as a result of Enduring Renewal's refresh.
            This did ${formatNumber(this.healing)} healing and was ${erPercHPS}% of your total healing.
            <br/><br/>
            You refreshed renews ${this.refreshedRenews} times for a total of ${formatNumber(this.secsGained)} additional seconds of Renew.
            (+${erGainPerRefresh}s per refresh on average).
          `}
          >
            Enduring Renewal
          </dfn>
        )}
      />
    );
    //
  }
Esempio n. 5
0
    this.bsCasts.forEach((cast, index) => {
      const avgDamage = formatNumber(cast.hits.reduce((a, b) => { return a + b; }, 0) / cast.hits.length);
      const totalDamage = formatNumber(cast.hits.reduce((a, b) => { return a + b; }, 0));
      const avgHits = formatNumber(cast.hits.length / cast.cost * 100, 1);
      const rpCost = formatNumber(cast.cost / 10);

      tooltip += `Cast #${ index + 1 } (for ${ rpCost } RP) hit an average of ${ avgHits } target${ avgHits <= 1 ? '' : 's' } for ${ avgDamage } per hit. (${ totalDamage } total)<br>`;
    });
Esempio n. 6
0
  statistic() {
    if (!this.showStatistic) return null;

    const healingWithoutAbsorbs = this.total.regular - this.healingByAbsorbs.regular;

    return (
      <StatisticBox
        icon={(
          <img
            src="/img/healing.png"
            style={{ border: 0 }}
            alt="Healing"
          />
        )}
        value={`${formatNumber(this.total.effective / this.owner.fightDuration * 1000)} HPS`}
        label="Healing done"
        tooltip={`Total healing done: <b>${formatThousands(this.total.effective)}</b>`}
        footer={(
          <div className="statistic-bar">
            <div
              className="stat-healing-bg"
              style={{ width: `${healingWithoutAbsorbs / this.total.raw * 100}%` }}
              data-tip={`Regular healing done, not including absorbs. You did a total of ${formatNumber(healingWithoutAbsorbs)} regular healing (${formatPercentage(healingWithoutAbsorbs / this.total.raw)}% of raw healing).`}
            >
              <img src="/img/healing.png" alt="Healing" />
            </div>
            {this.healingByAbsorbs.regular > 0 && (
              <div
                className="stat-healing-absorbs-bg"
                style={{ width: `${this.healingByAbsorbs.regular / this.total.raw * 100}%` }}
                data-tip={`Healing by absorbs. This only includes damage prevented by absorbs. You did a total of ${formatNumber(this.healingByAbsorbs.regular)} healing with absorbs (${formatPercentage(this.healingByAbsorbs.regular / this.total.raw)}% of raw healing).`}
              >
                <img src="/img/absorbed.png" alt="Absorb Healing" />
              </div>
            )}
            {this.total.absorbed > 0 && (
              <div
                className="stat-negative-absorbs-bg"
                style={{ width: `${this.total.absorbed / this.total.raw * 100}%` }}
                data-tip={`Absorbed healing. This only includes healing that gets absorbed by debuffs. You had a total of ${formatNumber(this.total.absorbed)} healing absorbed (${formatPercentage(this.total.absorbed / this.total.raw)}% of raw healing).`}
              >
                <img src="/img/negative-absorbed.png" alt="Absorbed Healing" />
              </div>
            )}
            <div
              className="remainder stat-overhealing-bg"
              data-tip={`Overhealing. You did a total of ${formatNumber(this.total.overheal)} overhealing (${formatPercentage(this.total.overheal / this.total.raw)} % of raw healing). Overhealing can be caused by playing poorly such as selecting the wrong targets or casting abilities at the wrong time, other healers sniping, and/or bringing too many healers.`}
            >
              <img src="/img/overhealing.png" alt="Overhealing" />
            </div>
          </div>
        )}
        footerStyle={{ overflow: 'hidden' }}
      />
    );
  }
 item() {
   return {
     item: ITEMS.ULLRS_FEATHER_SNOWSHOES,
     result: (
       <dfn data-tip={`You wasted ${formatNumber(this.wastedTrueshotReductionMs / 1000)} seconds of CDR.<br/> `}>
         reduced <SpellLink id={SPELLS.TRUESHOT.id} /> CD by {formatNumber(this.effectiveTrueshotReductionMs / 1000)}s in total.
       </dfn>
     ),
   };
 }
	item() {
		return {
			item: ITEMS.RADDONS_CASCADING_EYES,
			result: (
				<dfn data-tip={`You wasted ${formatNumber(this.wastedEyeBeamReduction / 1000)} seconds of CDR.<br/>`}>
					reduced <SpellLink id={SPELLS.EYE_BEAM.id} icon /> cooldown by {formatNumber(this.effectiveEyeBeamReduction / 1000)}s in total
				</dfn>
			),
		};
	}
 item() {
   return {
     item: ITEMS.LIADRINS_FURY_UNLEASHED,
     result: (
       <dfn data-tip={`Total Holy Power Gained: ${formatNumber(this.holyPowerGenerated)}`}>
         {formatNumber(this.holyPowerGenerated / this.owner.fightDuration * 60000)} Holy Power gained per minute.
       </dfn>
     ),
   };
 }
Esempio n. 10
0
	item() {
		return {
			item: ITEMS.CHAOS_THEORY,
			result: (
				<dfn data-tip={`You had <b>${this.procs}</b> procs (<b>${formatNumber(this.expectedProcs)}</b> expected procs)</br> Total Damage: <b>${formatNumber(this.bonusDamage)}</b>`}>
					<ItemDamageDone amount={this.bonusDamage} />
				</dfn>
			),
		};
	}
Esempio n. 11
0
 statistic() {
   return (
     <StatisticBox
       icon={<SpellIcon id={SPELLS.RETRIBUTION_BUFF.id} />}
       value={`${formatNumber(this.bonusDmg / this.owner.fightDuration * 1000)} DPS`}
       label="Damage contributed"
       tooltip={`Retribution contributed ${formatNumber(this.bonusDmg)} total damage (${formatPercentage(this.owner.getPercentageOfTotalDamageDone(this.bonusDmg))} %).`}
     />
   );
 }
Esempio n. 12
0
 when(this.suggestionThresholds).addSuggestion((suggest, actual, recommended) => {
   return suggest(
     <React.Fragment>
       The healing done by your <SpellLink id={SPELLS.AURA_OF_SACRIFICE_TALENT.id} /> is low. Try to find a better moment to cast it, improve your usage or consider changing to <SpellLink id={SPELLS.AURA_OF_MERCY_TALENT.id} /> or <SpellLink id={SPELLS.DEVOTION_AURA_TALENT.id} /> which can be more reliable and often do as much healing with less effort.
     </React.Fragment>
   )
     .icon(SPELLS.AURA_OF_SACRIFICE_TALENT.icon)
     .actual(`${formatNumber(actual)} HPS`)
     .recommended(`>${formatNumber(recommended)} HPS is recommended`);
 });
Esempio n. 13
0
 statistic() {
   return (
     <StatisticBox
       icon={<SpellIcon id={SPELLS.DEATHS_EMBRACE_TALENT.id} />}
       value={`${formatNumber(this.bonusDmg / this.owner.fightDuration * 1000)} DPS`}
       label="Damage contributed"
       tooltip={`Your Death's Embrace talent contributed ${formatNumber(this.bonusDmg)} total damage (${formatPercentage(this.owner.getPercentageOfTotalDamageDone(this.bonusDmg))} %).`}
     />
   );
 }
Esempio n. 14
0
 item() {
   return {
     item: ITEMS.QAPLA_EREDUN_WAR_ORDER,
     result: (
       <dfn data-tip={`You wasted ${formatNumber(this.wastedKillCommandReductionMs / 1000)} (${formatPercentage(this.wastedKillCommandCDRPercent())}%) seconds of CDR by using Dire Beast when Kill Command wasn't on cooldown or had less than 3 seconds remaning on CD.`}>
         reduced <SpellLink id={SPELLS.KILL_COMMAND.id} /> CD by {formatNumber(this.effectiveKillCommandReductionMs / 1000)}s in total.
       </dfn>
     ),
   };
 }
Esempio n. 15
0
 when(this.suggestionThresholds).addSuggestion((suggest, actual, recommended) => {
     return suggest(
       <React.Fragment>
         Your current spell usage is not taking full advantage of the <SpellLink id={SPELLS.LIFECYCLES_TALENT.id} /> talent. You should be trying to alternate the use of these spells as often as possible to take advantage of the buff.
       </React.Fragment>
     )
       .icon(SPELLS.LIFECYCLES_TALENT.icon)
       .actual(`${formatNumber(this.manaSaved)} mana saved through Lifecycles`)
       .recommended(`${formatNumber(recommended)} is the recommended amount of mana savings`);
   });
Esempio n. 16
0
	statistic() {
		return (
			<StatisticBox
  icon={<SpellIcon id={SPELLS.FEAST_ON_THE_SOULS.id} />}
  value={`${formatNumber(this.totalCooldownReduction / 1000)} seconds`}
  label={<React.Fragment>Cooldown Reduction on <SpellLink id={SPELLS.EYE_BEAM.id} icon /></React.Fragment>}
  tooltip={`You wasted ${formatNumber(this.totalCooldownReductionWasted / 1000)} seconds of cooldown reduction`}
			/>
		);
	}
Esempio n. 17
0
 statistic() {
   return (
     <StatisticBox
       icon={<SpellIcon id={SPELLS.LANDSLIDE_TALENT.id} />}
       value={`${formatPercentage(this.damagePercent)} %`}
       label="Of total damage"
       tooltip={`Contributed ${formatNumber(this.damagePerSecond)} DPS (${formatNumber(this.damageGained)} total damage).`}
     />
   );
 }
Esempio n. 18
0
 item() {
   const tkcCasts = this.abilityTracker.getAbility(SPELLS.THALKIELS_CONSUMPTION_CAST.id).casts || 1; // it's for averages, so 1 in denominator as a default value
   return {
     item: ITEMS.WAKENERS_LOYALTY,
     result: (
       <dfn data-tip={`Total bonus damage: ${formatNumber(this.bonusDmg)}<br />Average bonus damage per TKC cast: ${formatNumber(this.bonusDmg / tkcCasts)}<br />Average stacks of Wakener's Loyalty per TKC cast: ${(this._totalUsedStacks / tkcCasts).toFixed(2)}`}>
         <ItemDamageDone amount={this.bonusDmg} />
       </dfn>
     ),
   };
 }
Esempio n. 19
0
 statistic() {
   return (
     <StatisticBox
       icon={<SpellIcon id={SPELLS.PURIFYING_BREW.id} />}
       value={`${formatNumber(this.meanPurify)}`}
       label="Avg. Mitigation per Purifying Brew"
       tooltip={`Purifying Brew removed <b>${formatNumber(this.totalPurified)}</b> damage in total over ${this.totalPurifies} casts.<br/>
                 The smallest purify removed <b>${formatNumber(this.minPurify)}</b> and the largest purify removed <b>${formatNumber(this.maxPurify)}</b>.<br/>
                 You purified <b>${this.badPurifies}</b> (${formatPercentage(this.badPurifies / this.totalPurifies)}%) times without reaching Heavy Stagger.`}
     />
   );
 }
Esempio n. 20
0
 item() {
   return {
     id: `spell-${SPELLS.BLOOD_DEATH_KNIGHT_T21_2SET_BONUS_BUFF.id}`,
     icon: <SpellIcon id={SPELLS.BLOOD_DEATH_KNIGHT_T21_2SET_BONUS_BUFF.id} />,
     title: <SpellLink id={SPELLS.BLOOD_DEATH_KNIGHT_T21_2SET_BONUS_BUFF.id} icon={false} />,
     result: (
       <dfn data-tip={`${formatNumber(this.effectiveReduction / 1000)} sec total effective reduction and ${formatNumber(this.wastedReduction / 1000)} sec (${formatPercentage(this.wastedPercent)}%) wasted reduction.`}>
         <React.Fragment>Reduced the cooldown of <SpellLink id={SPELLS.DANCING_RUNE_WEAPON.id} /> by an average of {formatNumber(this.averageReduction)} seconds.</React.Fragment>
       </dfn>
     ),
   };
 }
Esempio n. 21
0
 // labels an item in the tooltip
 function labelItem(tooltipItem, data) {
   const { index } = tooltipItem;
   const dataset = data.datasets[tooltipItem.datasetIndex];
   switch (dataset.label) {
     case DEATH_LABEL:
       return `Player died when hit by ${safeAbilityName(deathsBySeconds[index].ability)} at ${formatNumber(deathsBySeconds[index].hp)} HP.`;
     case PURIFY_LABEL:
       return `Purifying Brew cast with ${formatNumber(tooltipItem.yLabel)} damage staggered.`;
     default:
       return `${dataset.label}: ${formatNumber(tooltipItem.yLabel)}`;
   }
 }
Esempio n. 22
0
 item() {
   return {
     id: `spell-${SPELLS.HUNTER_MM_T19_2P_BONUS.id}`,
     icon: <SpellIcon id={SPELLS.TRUESHOT.id} />,
     title: <SpellLink id={SPELLS.HUNTER_MM_T19_2P_BONUS.id} icon={false} />,
     result: (
       <dfn data-tip={`You wasted ${formatNumber(this.wastedTrueshotReductionMs / 1000)} seconds of CDR.<br/> `}>
         reduced <SpellLink id={SPELLS.TRUESHOT.id} /> CD by {formatNumber(this.effectiveTrueshotReductionMs / 1000)}s in total.
       </dfn>
     ),
   };
 }
Esempio n. 23
0
 statistic() {
   // TODO: Add other Grimoire pets (but realistically this is enough)
   const grimoireFelguardDamage = this.demoPets.getTotalPetDamage(PETS.GRIMOIRE_FELGUARD.id);
   return (
     <StatisticBox
       icon={<SpellIcon id={SPELLS.GRIMOIRE_OF_SERVICE_TALENT.id} />}
       value={`${formatNumber(grimoireFelguardDamage / this.owner.fightDuration * 1000)} DPS`}
       label="Grimoire of Service damage"
       tooltip={`Your Grimoire of Service: Felguard did ${formatNumber(grimoireFelguardDamage)} damage (${formatPercentage(this.owner.getPercentageOfTotalDamageDone(grimoireFelguardDamage))} %).`}
     />
   );
 }
Esempio n. 24
0
 item() {
   return {
     id: `spell-${SPELLS.RET_PALADIN_T21_4SET_BONUS.id}`,
     icon: <SpellIcon id={SPELLS.RET_PALADIN_T21_4SET_BONUS.id} />,
     title: <SpellLink id={SPELLS.RET_PALADIN_T21_4SET_BONUS.id} icon={false} />,
     result: (
       <dfn data-tip={`Total Holy Power Gained: ${formatNumber(this.holyPowerGained)}`}>
         {formatNumber(this.holyPowerGained / this.owner.fightDuration * 60000)} Holy Power gained per minute.
       </dfn>
     ),
   };
 }
Esempio n. 25
0
 statistic() {
   return (
     <StatisticBox
       icon={<SpellIcon id={SPELLS.RIGHTEOUS_VERDICT_TALENT.id} />}
       value={formatNumber(this.damageDone)}
       label="Damage Done"
       tooltip={`
          The effective damage contributed by Righteous Verdict.<br/>
          Total Damage: ${formatNumber(this.damageDone)} (${formatPercentage(this.owner.getPercentageOfTotalDamageDone(this.damageDone))} %)<br/>
          Buffed Casts: ${formatNumber(this.spendersInsideBuff)} (${formatPercentage(this.spendersInsideBuff / this.totalSpenders)}%)`}
     />
   );
 }
Esempio n. 26
0
 statistic() {
   return (
     <StatisticBox
       icon={<SpellIcon id={SPELLS.PUNISH_TALENT.id} />}
       value={`${formatNumber(this.bonusDmg / this.owner.fightDuration * 1000)} DPS`}
       label="Damage contributed"
       tooltip={`
         Punish added a total of ${formatNumber(this.bonusDmg)} damage to your Shield Slams (${formatPercentage(this.owner.getPercentageOfTotalDamageDone(this.bonusDmg))}%). </br>
         ${formatPercentage(this.uptime)}% debuff uptime.
       `}
     />
   );
 }
 item() {
   const perProc=this.absorb/this.umbilicusEternusCount;
   return {
     item: ITEMS.SOULFLAYERS_CORRUPTION,
     result: (
       <React.Fragment>
         <ItemHealingDone amount={this.heal} /><br />
         <ItemDamageDone amount={this.damage} /><br />
         Increased <SpellLink id={SPELLS.UMBILICUS_ETERNUS.id} /> trait absorbs by: <br />
         <b>Avg Per Proc:</b> {formatNumber(perProc)}  |  <b>Total:</b> {formatNumber(this.absorb)}
       </React.Fragment>
     ),
   };
 }
Esempio n. 28
0
 statistic() {
   return (
     <StatisticBox
       icon={<SpellIcon id={SPELLS.NEMESIS_TALENT.id} />}
       value={`${formatPercentage(this.owner.getPercentageOfTotalDamageDone(this.bonusDmg))}%`}
       label="Damage Contributed"
       tooltip={`
         Nemesis Contributed ${formatNumber(this.bonusDmg / this.owner.fightDuration * 1000)} DPS / ${formatNumber(this.bonusDmg)} total damage.
         <br/> You had ${formatPercentage(this.nemesisUptimePercent)}% uptime.
         ${this.everHadNemesisBuff ? `<br/><br/> Due to technical limitations it is not currently possible to tell if your nemesis buff type is the same as the boss type. This limitation may cause the damage contributed by nemesis to appear higher than it otherwise would.` : ''}
       `}
     />
   );
 }
 statistic() {    
   const danceDamage = Object.keys(this.danceDamageTracker.abilities)
   .map(abilityId => this.danceDamageTracker.abilities[abilityId].damageEffective || 0)
   .reduce((a,b) => a+b,0) * this.darkShadowDamageFactor / (1 + this.darkShadowDamageFactor);
    
   return (
       <StatisticBox
         icon={<SpellIcon id={SPELLS.DARK_SHADOW_TALENT.id} />}
         value={`${formatNumber(danceDamage / this.owner.fightDuration * 1000)} DPS`}
         label="Damage contribution from Dark Shadow"
         tooltip={`Total damage increase is ${formatNumber(danceDamage)} in ${this.totalShadowDanceCast} Shadow Dance casts.`}
         />
   );
 }
Esempio n. 30
0
  item() {
    const fightLengthSec = this.owner.fightDuration / 1000;
    const dps = this.damageDone / fightLengthSec;
    const hps = this.abilityTracker.getAbility(SPELLS.FURY_OF_NATURE_HEAL.id).healingEffective / fightLengthSec;

    return {
      item: ITEMS.FURY_OF_NATURE,
      result: (
        <span>
          {formatNumber(dps)} DPS / {formatNumber(hps)} HPS
        </span>
      ),
    };
  }