Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
69d50e7
Pre Player Attack Entity
MrScopes Dec 23, 2025
d049dd2
optional 'event-' prefix to entity/victim in CondWillBeAttacked
MrScopes Dec 23, 2025
c12db82
better descriptions
MrScopes Dec 23, 2025
847986b
update description and syntax
MrScopes Dec 23, 2025
025bebc
remove cond will be attacked
MrScopes Jan 1, 2026
5bffa90
update exprattacked conventions
MrScopes Jan 1, 2026
a1acd88
update @events temporarily, at least until we come up with better syn…
MrScopes Jan 1, 2026
a048c7b
update exprattacker to new conventions + add pre attack event
MrScopes Jan 1, 2026
cc39815
remove from event values as it's unnecessary
MrScopes Jan 1, 2026
08925b8
add preplayerattackentity to supported events for ExprAttacker
MrScopes Jan 1, 2026
3d8e2cb
update exprattacker conventions
MrScopes Jan 1, 2026
cdb8794
update example in event
MrScopes Jan 1, 2026
154983b
move import down in both exprattacked and exprattacker
MrScopes Jan 1, 2026
5265711
separate attempt attack intos own file. adopt new syntax from pre att…
MrScopes Jan 3, 2026
ab198ac
remove all changes to simpleevents
MrScopes Jan 3, 2026
279c247
pre attack -> attempt attack in events mention
MrScopes Jan 3, 2026
652dd2b
remove bracket from null check
MrScopes Jan 3, 2026
b4b9da6
actually remove change to simpleevents?
MrScopes Jan 3, 2026
9a84f4b
revert to old simpleevents file
MrScopes Jan 3, 2026
a3dcd8a
remove space in the tostring on exprattacked
MrScopes Jan 3, 2026
ae8d658
try suggested fix by Efnilite
MrScopes Jan 3, 2026
96a30cf
Update src/main/java/ch/njol/skript/events/EvtAttemptAttack.java
MrScopes Jan 3, 2026
8309f67
Update src/main/java/ch/njol/skript/events/EvtAttemptAttack.java
MrScopes Jan 3, 2026
3bb1396
Update src/main/java/ch/njol/skript/events/EvtAttemptAttack.java
MrScopes Jan 3, 2026
f732e80
Update src/main/java/ch/njol/skript/events/EvtAttemptAttack.java
MrScopes Jan 3, 2026
fe6c6fb
Update src/main/java/ch/njol/skript/events/EvtAttemptAttack.java
MrScopes Jan 3, 2026
1bc866a
Update src/main/java/ch/njol/skript/events/EvtAttemptAttack.java
MrScopes Jan 3, 2026
ad7367c
Update src/main/java/ch/njol/skript/expressions/ExprAttacker.java
MrScopes Jan 3, 2026
561bcf8
remove unnecessary old version mention
MrScopes Jan 3, 2026
ba553b5
Merge branch 'preplayerattack' of https://github.com/MrScopes/Skript …
MrScopes Jan 3, 2026
74143c9
e -> event
MrScopes Jan 3, 2026
f76f1f9
change other obscure variables
MrScopes Jan 3, 2026
9e4237b
several examples instead of one big block
MrScopes Jan 3, 2026
5cf7306
requested change to use pattern variables
MrScopes Jan 3, 2026
3adb50a
use SyntaxStringBuilder
MrScopes Jan 3, 2026
3d33542
Merge branch 'dev/feature' into preplayerattack
sovdeeth Jan 3, 2026
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
83 changes: 83 additions & 0 deletions src/main/java/ch/njol/skript/events/EvtAttemptAttack.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package ch.njol.skript.events;

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

import ch.njol.skript.Skript;
import ch.njol.skript.entity.EntityData;
import ch.njol.skript.lang.Literal;
import ch.njol.skript.lang.SkriptEvent;
import ch.njol.skript.lang.SkriptParser.ParseResult;
import ch.njol.skript.lang.SyntaxStringBuilder;
import ch.njol.skript.registrations.Classes;
import io.papermc.paper.event.player.PrePlayerAttackEntityEvent;

public class EvtAttemptAttack extends SkriptEvent {
static {
Skript.registerEvent("Attempt Attack", EvtAttemptAttack.class, PrePlayerAttackEntityEvent.class, "attack attempt", "attempt[ing] to attack %entitydatas%")
.description("""
Called when a player attempts to attack an entity.
The event will be cancelled as soon as it is fired for non-living entities.
Cancelling this event will prevent the attack and any sounds from being played when attacking.
Any damage events will not be called if this is cancelled.
""")
.examples("""
on attack attempt:
if event is cancelled:
broadcast "%attacker% failed to attack %victim%!"
else:
broadcast "%attacker% damaged %victim%!"
""",
"""
on attempt to attack an animal:
cancel event
""",
"""
on attempting to attack an entity:
if victim is a creeper:
cancel event
""",
"""
on attempt to attack a zombie or creeper:
attacker isn't holding a diamond sword
cancel event
""")
.since("INSERT VERSION");
}

private @Nullable EntityData<?>[] types;

@Override
public boolean init(Literal<?>[] args, int matchedPattern, ParseResult parser) {
types = args.length == 0 ? null : ((Literal<EntityData<?>>) args[0]).getAll();
return true;
}

@Override
public boolean check(Event event) {
if (types == null)
return true;

if (!(event instanceof PrePlayerAttackEntityEvent preEvent))
return false;
Entity entity = preEvent.getAttacked();

for (final EntityData<?> data : types) {
if (data.isInstance(entity))
return true;
}
return false;
}

@Override
public String toString(@Nullable Event event, boolean debug) {
SyntaxStringBuilder builder = new SyntaxStringBuilder(event, debug);
builder.append("attempt attack");
if (types != null) {
builder.append("of", Classes.getDebugMessage(types));
}
return builder.toString();
}

}
34 changes: 21 additions & 13 deletions src/main/java/ch/njol/skript/expressions/ExprAttacked.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import ch.njol.skript.lang.EventRestrictedSyntax;
import ch.njol.util.coll.CollectionUtils;

import org.bukkit.entity.Entity;
import org.bukkit.event.Event;
import org.bukkit.event.entity.EntityDamageEvent;
Expand All @@ -13,6 +14,7 @@
import org.bukkit.event.vehicle.VehicleDamageEvent;
import org.bukkit.event.vehicle.VehicleDestroyEvent;
import org.bukkit.event.vehicle.VehicleEvent;
import io.papermc.paper.event.player.PrePlayerAttackEntityEvent;
import org.jetbrains.annotations.Nullable;

import ch.njol.skript.Skript;
Expand All @@ -31,15 +33,14 @@
import ch.njol.util.Kleenean;

@Name("Attacked")
@Description("The victim of a damage event, e.g. when a player attacks a zombie this expression represents the zombie. " +
"When using Minecraft 1.11+, this also covers the hit entity in a projectile hit event.")
@Description("The victim of a damage event, e.g. when a player attacks a zombie this expression represents the zombie.")
@Example("""
on damage:
victim is a creeper
damage the attacked by 1 heart
""")
@Since("1.3, 2.6.1 (projectile hit event)")
@Events({"damage", "death", "projectile hit"})
@Events({"damage", "death", "projectile hit", "attempt attack"})
public class ExprAttacked extends SimpleExpression<Entity> implements EventRestrictedSyntax {

private static final boolean SUPPORT_PROJECTILE_HIT = Skript.methodExists(ProjectileHitEvent.class, "getHitEntity");
Expand Down Expand Up @@ -70,27 +71,34 @@ public boolean init(Expression<?>[] vars, int matchedPattern, Kleenean isDelayed
@Override
public Class<? extends Event>[] supportedEvents() {
return CollectionUtils.array(EntityDamageEvent.class, EntityDeathEvent.class,
VehicleDamageEvent.class, VehicleDestroyEvent.class, ProjectileHitEvent.class);
VehicleDamageEvent.class, VehicleDestroyEvent.class, ProjectileHitEvent.class, PrePlayerAttackEntityEvent.class);
}

@Override
@Nullable
protected Entity[] get(Event e) {
protected Entity[] get(Event event) {
Entity[] one = (Entity[]) Array.newInstance(type.getType(), 1);
Entity entity;
if (e instanceof EntityEvent)
if (SUPPORT_PROJECTILE_HIT && e instanceof ProjectileHitEvent)
entity = ((ProjectileHitEvent) e).getHitEntity();
else
entity = ((EntityEvent) e).getEntity();
else if (e instanceof VehicleEvent)
entity = ((VehicleEvent) e).getVehicle();
else

if (event instanceof EntityEvent entityEvent) {
if (SUPPORT_PROJECTILE_HIT && event instanceof ProjectileHitEvent projectileHitEvent) {
entity = projectileHitEvent.getHitEntity();
} else {
entity = entityEvent.getEntity();
}
} else if (event instanceof VehicleEvent vehicleEvent) {
entity = vehicleEvent.getVehicle();
} else if (event instanceof PrePlayerAttackEntityEvent preAttackEvent) {
entity = preAttackEvent.getAttacked();
} else {
return null;
}

if (type.isInstance(entity)) {
one[0] = entity;
return one;
}

return null;
}

Expand Down
61 changes: 34 additions & 27 deletions src/main/java/ch/njol/skript/expressions/ExprAttacker.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import ch.njol.skript.lang.EventRestrictedSyntax;
import ch.njol.util.coll.CollectionUtils;

import org.bukkit.entity.Entity;
import org.bukkit.entity.Projectile;
import org.bukkit.event.Event;
Expand All @@ -10,6 +11,7 @@
import org.bukkit.event.entity.EntityDeathEvent;
import org.bukkit.event.vehicle.VehicleDamageEvent;
import org.bukkit.event.vehicle.VehicleDestroyEvent;
import io.papermc.paper.event.player.PrePlayerAttackEntityEvent;
import org.jetbrains.annotations.Nullable;

import ch.njol.skript.Skript;
Expand All @@ -22,24 +24,22 @@
import ch.njol.skript.lang.ExpressionType;
import ch.njol.skript.lang.SkriptParser.ParseResult;
import ch.njol.skript.lang.util.SimpleExpression;
import ch.njol.skript.log.ErrorQuality;
import ch.njol.skript.registrations.Classes;
import ch.njol.util.Kleenean;

/**
* @author Peter Güttinger
*/
@Name("Attacker")
@Description({"The attacker of a damage event, e.g. when a player attacks a zombie this expression represents the player.",
"Please note that the attacker can also be a block, e.g. a cactus or lava, but this expression will not be set in these cases."})
@Description("""
The attacker of a damage event, e.g. when a player attacks a zombie this expression represents the player.",
Please note that the attacker can also be a block, e.g. a cactus or lava, but this expression will not be set in these cases.
""")
@Example("""
on damage:
attacker is a player
health of attacker is less than or equal to 2
damage victim by 1 heart
""")
@Since("1.3")
@Events({"damage", "death", "vehicle destroy"})
@Events({"damage", "death", "vehicle destroy", "attempt attack"})
public class ExprAttacker extends SimpleExpression<Entity> implements EventRestrictedSyntax {

static {
Expand All @@ -54,7 +54,7 @@ public boolean init(Expression<?>[] exprs, int matchedPattern, Kleenean isDelaye
@Override
public Class<? extends Event>[] supportedEvents() {
return CollectionUtils.array(EntityDamageEvent.class, EntityDeathEvent.class,
VehicleDamageEvent.class, VehicleDestroyEvent.class);
VehicleDamageEvent.class, VehicleDestroyEvent.class, PrePlayerAttackEntityEvent.class);
}

@Override
Expand All @@ -63,31 +63,38 @@ protected Entity[] get(Event e) {
}

@Nullable
static Entity getAttacker(@Nullable Event e) {
if (e == null)
static Entity getAttacker(@Nullable Event event) {
if (event == null) {
return null;
if (e instanceof EntityDamageByEntityEvent) {
EntityDamageByEntityEvent edbee = (EntityDamageByEntityEvent) e;
if (edbee.getDamager() instanceof Projectile) {
Projectile p = (Projectile) edbee.getDamager();
Object o = p.getShooter();
if (o instanceof Entity)
return (Entity) o;
}

if (event instanceof EntityDamageByEntityEvent damageEvent) {
Entity damager = damageEvent.getDamager();

if (damager instanceof Projectile projectile) {
Object shooter = projectile.getShooter();
if (shooter instanceof Entity shooterEntity) {
return shooterEntity;
}
return null;
}
return edbee.getDamager();
// } else if (e instanceof EntityDamageByBlockEvent) {
// return ((EntityDamageByBlockEvent) e).getDamager();
} else if (e instanceof EntityDeathEvent) {
return getAttacker(((EntityDeathEvent) e).getEntity().getLastDamageCause());
} else if (e instanceof VehicleDamageEvent) {
return ((VehicleDamageEvent) e).getAttacker();
} else if (e instanceof VehicleDestroyEvent) {
return ((VehicleDestroyEvent) e).getAttacker();

return damager;
// } else if (event instanceof EntityDamageByBlockEvent blockDamageEvent) {
// return blockDamageEvent.getDamager();
} else if (event instanceof EntityDeathEvent deathEvent) {
return getAttacker(deathEvent.getEntity().getLastDamageCause());
} else if (event instanceof VehicleDamageEvent vehicleDamageEvent) {
return vehicleDamageEvent.getAttacker();
} else if (event instanceof VehicleDestroyEvent vehicleDestroyEvent) {
return vehicleDestroyEvent.getAttacker();
} else if (event instanceof PrePlayerAttackEntityEvent preAttackEvent) {
return preAttackEvent.getPlayer();
}

return null;
}

@Override
public Class<? extends Entity> getReturnType() {
return Entity.class;
Expand Down