Skip to content

EffForceAttack Damage Entity By Amount #7878

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 11 commits into
base: dev/feature
Choose a base branch
from
Open
104 changes: 70 additions & 34 deletions src/main/java/ch/njol/skript/effects/EffForceAttack.java
Original file line number Diff line number Diff line change
@@ -1,67 +1,103 @@
package ch.njol.skript.effects;

import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity;
import org.bukkit.event.Event;
import org.jetbrains.annotations.Nullable;

import ch.njol.skript.Skript;
import ch.njol.skript.doc.Description;
import ch.njol.skript.doc.Examples;
import ch.njol.skript.doc.Name;
import ch.njol.skript.doc.RequiredPlugins;
import ch.njol.skript.doc.Since;
import ch.njol.skript.doc.*;
import ch.njol.skript.lang.Effect;
import ch.njol.skript.lang.Expression;
import ch.njol.skript.lang.SkriptParser.ParseResult;
import ch.njol.skript.lang.SyntaxStringBuilder;
import ch.njol.util.Kleenean;
import org.bukkit.entity.Damageable;
import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity;
import org.bukkit.event.Event;
import org.jetbrains.annotations.Nullable;

@Name("Force Attack")
@Description("Makes a living entity attack an entity with a melee attack.")
@Description({
"Makes a living entity attack an entity with a melee attack.",
"Using 'attack' will make the attacker use the item in their main hand "
+ "and will apply extra data from the item, including enchantments and attributes.",
"Using 'damage' with a number of hearts will not account for the item in the main hand "
+ "and will always be the number provided.",
"Both use cases will make the entity doing the attacking be the 'attacker' in an "
+ "'on damage' or 'on death' event."
})
@Example("""
spawn a wolf at location(0, 0, 0)
make last spawned wolf attack all players
""")
@Example("""
spawn a zombie at location(0, 0, 0)
make player damage last spawned zombie by 2
""")
@Examples({"spawn a wolf at player's location",
"make last spawned wolf attack player"})
@Since("2.5.1")
@Since("2.5.1, INSERT VERSION (multiple, amount)")
@RequiredPlugins("Minecraft 1.15.2+")
public class EffForceAttack extends Effect {

static {
Skript.registerEffect(EffForceAttack.class,
"make %livingentities% attack %entity%",
"force %livingentities% to attack %entity%");
"make %livingentities% attack %entities%",
"force %livingentities% to attack %entities%",
"make %livingentities% damage %entities% by %number% [heart[s]]",
"force %livingentities% to damage %entities% by %number% [heart[s]]");
}

private static final boolean ATTACK_IS_SUPPORTED = Skript.methodExists(LivingEntity.class, "attack", Entity.class);

@SuppressWarnings("null")
private Expression<LivingEntity> entities;
@SuppressWarnings("null")
private Expression<Entity> target;

private Expression<LivingEntity> attackers;
private Expression<Entity> victims;
private @Nullable Expression<Number> amount;

@SuppressWarnings("unchecked")
@Override
public boolean init(Expression<?>[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) {
if (!ATTACK_IS_SUPPORTED) {
Skript.error("The force attack effect requires Minecraft 1.15.2 or newer");
return false;
}
entities = (Expression<LivingEntity>) exprs[0];
target = (Expression<Entity>) exprs[1];
attackers = (Expression<LivingEntity>) exprs[0];
victims = (Expression<Entity>) exprs[1];
if (matchedPattern >= 2)
amount = (Expression<Number>) exprs[2];
return true;
}

@Override
protected void execute(Event e) {
Entity target = this.target.getSingle(e);
if (target != null) {
for (LivingEntity entity : entities.getArray(e)) {
entity.attack(target);
protected void execute(Event event) {
Double amount = null;
if (this.amount != null) {
Number number = this.amount.getSingle(event);
if (number == null)
return;
amount = number.doubleValue() * 2; // hearts
}

LivingEntity[] attackers = this.attackers.getArray(event);
Entity[] victims = this.victims.getArray(event);
if (amount == null) {
for (Entity victim : victims) {
for (LivingEntity attacker : attackers) {
attacker.attack(victim);
}
}
} else {
for (Entity victim : victims) {
if (!(victim instanceof Damageable damageable))
continue;
for (LivingEntity attacker : attackers) {
damageable.damage(amount, attacker);
}
}
}
}

@Override
public String toString(@Nullable Event e, boolean debug) {
return "make " + entities.toString(e, debug) + " attack " + target.toString(e, debug);
public String toString(Event event, boolean debug) {
SyntaxStringBuilder builder = new SyntaxStringBuilder(event, debug);
builder.append("make", attackers);
if (amount == null) {
builder.append("attack", victims);
} else {
builder.append("damage", victims, "by", amount);
}
return builder.toString();
}

}