Skip to content

Commit

Permalink
Show reflected damage
Browse files Browse the repository at this point in the history
  • Loading branch information
xpdota committed Jan 5, 2024
1 parent b6d612d commit 348837e
Show file tree
Hide file tree
Showing 9 changed files with 114 additions and 6 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package gg.xp.xivsupport.events.actlines.events.abilityeffect;

@SuppressWarnings("AbstractClassWithoutAbstractMethods")
public abstract class AbilityEffect {

protected final long flags;
Expand Down Expand Up @@ -40,4 +41,8 @@ public final String getDescription() {
}
return String.format("%s (raw: %08x %08x)", getBaseDescription(), flags, value);
}

public boolean isDisplayed() {
return true;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package gg.xp.xivsupport.events.actlines.events.abilityeffect;

public class AbilityEffectContext {
boolean isReflect;
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,9 @@ public enum AbilityEffectType {
VFX,
HP_SET_TO,
AGGRO_INCREASE,
STATUS_REMOVED, OTHER
STATUS_REMOVED,
REFLECT_DUMMY,
REFLECTED_DAMAGE,

OTHER
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,18 @@ public final class AbilityEffects {
private AbilityEffects() {
}

// TODO: remove all null returns
public static @Nullable AbilityEffect of(long flags, long value) {
public static @Nullable AbilityEffect of(long flags, long value, AbilityEffectContext ctx) {
AbilityEffect ae = ofInner(flags, value);
if (ae instanceof ReflectFlagEffect) {
ctx.isReflect = true;
}
else if (ctx.isReflect && ae instanceof BaseDamageEffect de) {
return new ReflectedDamageEffect(flags, value, de);
}
return ae;
}

private static @Nullable AbilityEffect ofInner(long flags, long value) {
byte effectTypeByte;
byte severityByte;
byte healSeverityByte;
Expand All @@ -22,6 +32,13 @@ private AbilityEffects() {
// TODO: it's unclear which of these need the "lots of damage" calculation applied - IDs that point to an
// ability or status will probably be safe for the forseeable future, since there's nowhere close to
// 65536 statuses.
// TODO: reflected/punishment damage (vengeance, etc).
// It appears to be the case that you get something like this (not necessarily adjacent, but always in this relative order):
// 1. Original damage
// 2. 1D|70000 (or 50000, not sure what the value actually means)
// 3. Reflected damage
// e.g.:
// 21|2023-08-07T18:41:02.2330000-07:00|1024ABCD|Name Here|4784|Sonic Boom|40011BC8|Electric Aether|356003|D0E0000|1D|50000|1B|4D560000|550003|AAAA000|1B|47848000|0|0|0|0|0|0|
switch (effectTypeByte) {
case 0:
// nothing
Expand Down Expand Up @@ -115,11 +132,19 @@ private AbilityEffects() {
case 24:
return new AggroIncrease(flags, value, calcDamage(value));

case 29: //1D
// reflect
return new ReflectFlagEffect(flags, value);

// 1d,0x60000 = reflect?
case 27: //1B
// This seems to be on a lot of things that aren't involved in combos
// It's almost always either "1b" or "11b" for flags, and the value is ((abilityId << 16) + 0x8000)
// Not sure - seems to do "combo" as well as certain boss mechanics like "Subtract" from the math boss
// This is probably animation related. If the flags are just the ability ID, it's probably animation
// on the caster, while if there is a bit flipped just to the right of that (e.g. 4784 -> 47848000),
// then it's on the target?


case 32:
// Super cyclone did it
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package gg.xp.xivsupport.events.actlines.events.abilityeffect;

public class ReflectFlagEffect extends AbilityEffect {
protected ReflectFlagEffect(long flags, long value) {
super(flags, value, AbilityEffectType.REFLECT_DUMMY);
}

@Override
public boolean isDisplayed() {
return false;
}

@Override
protected String getBaseDescription() {
return "Next damage effect represents reflected damage.";
}

@Override
public String toString() {
return "Reflected Damage Flag";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package gg.xp.xivsupport.events.actlines.events.abilityeffect;

public class ReflectedDamageEffect extends AbilityEffect {
private final BaseDamageEffect reflected;

public ReflectedDamageEffect(long flags, long value, BaseDamageEffect reflected) {
super(flags, value, AbilityEffectType.REFLECTED_DAMAGE);
this.reflected = reflected;
}

public BaseDamageEffect getReflectedEffect() {
return reflected;
}

@Override
protected String getBaseDescription() {
return "Reflected: " + reflected.getBaseDescription();
}

@Override
public String toString() {
return "Reflected: " + reflected;
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package gg.xp.xivsupport.events.actlines.parsers;

import gg.xp.xivsupport.events.actlines.events.abilityeffect.AbilityEffect;
import gg.xp.xivsupport.events.actlines.events.abilityeffect.AbilityEffectContext;
import gg.xp.xivsupport.events.actlines.events.abilityeffect.AbilityEffects;
import gg.xp.xivsupport.events.state.XivState;
import gg.xp.xivsupport.models.HitPoints;
Expand Down Expand Up @@ -279,11 +280,12 @@ public List<AbilityEffect> getAbilityEffects(int startIndex, int count) {
[12:26 PM] xp: that makes more sense, thanks
[12:29 PM] Ravahn: yea, exactly, there's spots for 8 effects on the source and target. historically the first 4 were on target, last 4 on source, but SE changed that for status effects and added an 0x80 flag in byte 7 to indicate the effect is on the source.
*/
AbilityEffectContext ctx = new AbilityEffectContext();
ArrayList<AbilityEffect> out = new ArrayList<>(count);
for (int i = startIndex; i < startIndex + 2 * count; i += 2) {
long flags = getRawHex(i);
long value = getRawHex(i + 1);
AbilityEffect effect = AbilityEffects.of(flags, value);
AbilityEffect effect = AbilityEffects.of(flags, value, ctx);
if (effect != null) {
out.add(effect);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,17 @@
import gg.xp.xivdata.data.*;
import gg.xp.xivsupport.events.actlines.events.abilityeffect.AbilityEffect;
import gg.xp.xivsupport.events.actlines.events.abilityeffect.AggroIncrease;
import gg.xp.xivsupport.events.actlines.events.abilityeffect.BaseDamageEffect;
import gg.xp.xivsupport.events.actlines.events.abilityeffect.BlockedDamageEffect;
import gg.xp.xivsupport.events.actlines.events.abilityeffect.DamageEffect;
import gg.xp.xivsupport.events.actlines.events.abilityeffect.DamageTakenEffect;
import gg.xp.xivsupport.events.actlines.events.abilityeffect.DamageType;
import gg.xp.xivsupport.events.actlines.events.abilityeffect.HealEffect;
import gg.xp.xivsupport.events.actlines.events.abilityeffect.InvulnBlockedDamageEffect;
import gg.xp.xivsupport.events.actlines.events.abilityeffect.MpGain;
import gg.xp.xivsupport.events.actlines.events.abilityeffect.MpLoss;
import gg.xp.xivsupport.events.actlines.events.abilityeffect.ParriedDamageEffect;
import gg.xp.xivsupport.events.actlines.events.abilityeffect.ReflectedDamageEffect;
import gg.xp.xivsupport.events.actlines.events.abilityeffect.StatusAppliedEffect;
import gg.xp.xivsupport.events.actlines.events.abilityeffect.StatusNoEffect;
import gg.xp.xivsupport.events.actlines.parsers.StatusRemovedEffect;
Expand All @@ -25,6 +28,7 @@

public class AbilityEffectRenderer {
private final TableCellRenderer fallback = new DefaultTableCellRenderer();
private final TableCellRenderer fallbackSecondary = new DefaultTableCellRenderer();
private final boolean iconOnly;

public AbilityEffectRenderer(boolean iconOnly) {
Expand All @@ -37,9 +41,13 @@ public List<Component> getTableCellRendererComponents(JTable table, Object value
if (!(value instanceof AbilityEffect)) {
return Collections.singletonList(fallback.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column));
}
if (!((AbilityEffect) value).isDisplayed()) {
return Collections.emptyList();
}
String text;
HasIconURL icon;
boolean reverseLayout = false;
List<Component> components = new ArrayList<>();
if (value instanceof DamageTakenEffect dte) {
text = dte.getSeverity().getSymbol() + dte.getAmount();
DamageType type = dte.getDamageType();
Expand All @@ -48,7 +56,16 @@ public List<Component> getTableCellRendererComponents(JTable table, Object value
case Magic -> GeneralIcons.DAMAGE_MAGIC;
default -> GeneralIcons.DAMAGE_OTHER;
};
// icon = ActionLibrary.iconForId(9);
}
else if (value instanceof ReflectedDamageEffect rde) {
BaseDamageEffect dte = rde.getReflectedEffect();
text = dte.getSeverity().getSymbol() + dte.getAmount() + '↶';
DamageType type = dte.getDamageType();
icon = switch (type) {
case Piercing, Slashing, Blunt, Shot -> GeneralIcons.DAMAGE_PHYS;
case Magic -> GeneralIcons.DAMAGE_MAGIC;
default -> GeneralIcons.DAMAGE_OTHER;
};
}
else if (value instanceof HealEffect heal) {
text = heal.getSeverity().getSymbol() + heal.getAmount();
Expand Down Expand Up @@ -110,7 +127,6 @@ else if (value instanceof AggroIncrease ai) {
if (iconOnly) {
return Collections.singletonList(IconTextRenderer.getComponent(icon, defaultLabel, true, reverseLayout, true, null));
}
List<Component> components = new ArrayList<>();
if (reverseLayout) {
components.add(fallback.getTableCellRendererComponent(table, text, isSelected, hasFocus, row, column));
components.add(IconTextRenderer.getComponent(icon, defaultLabel, true, false, true, null));
Expand Down
5 changes: 5 additions & 0 deletions xivsupport/src/main/resources/te_changelog.html
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
<html lang="en">
<body style="margin: 5px 20px 5px 20px">
<h2>Unreleased</h2>
<ul>
<li>Damage reflected back to an attacker is now differentiated with a '↶' symbol after the damage number.</li>
<li>For addon module developers: fixed build issues when running on GitHub-supplied non-Windows runners.</li>
</ul>
<h2>Dec 29, 2023</h2>
<ul>
<li>Added ability to add cooldowns to your timeline by importing a log and recording CD usages (<a
Expand Down

0 comments on commit 348837e

Please sign in to comment.