Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
108 changes: 108 additions & 0 deletions core/src/main/java/com/nisovin/magicspells/spells/buff/ProxySpell.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
package com.nisovin.magicspells.spells.buff;

import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Collection;

import org.jetbrains.annotations.NotNull;

import org.bukkit.event.EventHandler;
import org.bukkit.entity.LivingEntity;
import org.bukkit.event.EventPriority;
import org.bukkit.event.entity.EntityDamageByEntityEvent;

import com.nisovin.magicspells.util.SpellData;
import com.nisovin.magicspells.spells.BuffSpell;
import com.nisovin.magicspells.util.MagicConfig;
import com.nisovin.magicspells.events.SpellTargetEvent;
import com.nisovin.magicspells.spelleffects.EffectPosition;

public class ProxySpell extends BuffSpell {

private final Set<UUID> redirecting = new HashSet<>();
private final Map<UUID, LivingEntity> proxies = new HashMap<>();

public ProxySpell(MagicConfig config, String spellName) {
super(config, spellName);
}

@Override
public boolean castBuff(SpellData data) {
if (data.target().equals(data.caster())) return false;
proxies.put(data.target().getUniqueId(), data.caster());
return true;
}

@Override
public boolean recastBuff(SpellData data) {
stopEffects(data.target());
Comment thread
DragonsAscent marked this conversation as resolved.
turnOffBuff(data.target());
return castBuff(data);
}

@Override
public boolean isActive(LivingEntity entity) {
return proxies.containsKey(entity.getUniqueId());
}

@Override
public void turnOffBuff(LivingEntity entity) {
proxies.remove(entity.getUniqueId());
}

@Override
protected @NotNull Collection<UUID> getActiveEntities() {
return proxies.keySet();
}

@EventHandler(ignoreCancelled = true)
public void onSpellTarget(SpellTargetEvent event) {
LivingEntity target = event.getTarget();
if (target == null || !isActive(target)) return;

LivingEntity proxyTarget = getProxyTarget(target);
if (proxyTarget == null) return;

event.setTarget(proxyTarget);
Comment thread
JasperLorelai marked this conversation as resolved.
playRedirectEffects(target, proxyTarget, event.getSpellData());

addUseAndChargeCost(target);
}

@EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST)
public void onEntityDamage(EntityDamageByEntityEvent event) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should the proxy receive damage from events not dealt by another entity?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Feel like it should be a config option

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, idk. The only purpose the damager has in this handler atm is that it's used for the spell effects. So imo, if a proxy receives any damage, it should be relayed, even if it wasn't caused by a third entity.

if (!(event.getEntity() instanceof LivingEntity target) || !isActive(target)) return;

LivingEntity proxyTarget = getProxyTarget(target);
if (proxyTarget == null) return;
if (!redirecting.add(proxyTarget.getUniqueId())) return;

SpellData subData = new SpellData(event.getDamager() instanceof LivingEntity damager ? damager : null, proxyTarget);
playRedirectEffects(target, proxyTarget, subData);

event.setCancelled(true);
try {
proxyTarget.damage(event.getFinalDamage(), event.getDamageSource());
addUseAndChargeCost(target);
} finally {
redirecting.remove(proxyTarget.getUniqueId());
}
}

private LivingEntity getProxyTarget(LivingEntity target) {
LivingEntity proxyTarget = proxies.get(target.getUniqueId());
if (proxyTarget != null && proxyTarget.isValid()) return proxyTarget;

turnOff(target);
return null;
}

private void playRedirectEffects(LivingEntity target, LivingEntity proxyTarget, SpellData data) {
playSpellEffects(EffectPosition.START_POSITION, target, data);
playSpellEffects(EffectPosition.END_POSITION, proxyTarget, data);
}

}
Loading