diff --git a/src/main/java/ch/njol/skript/events/EvtEntityShootBow.java b/src/main/java/ch/njol/skript/events/EvtEntityShootBow.java new file mode 100644 index 00000000000..5ec74625f09 --- /dev/null +++ b/src/main/java/ch/njol/skript/events/EvtEntityShootBow.java @@ -0,0 +1,94 @@ +package ch.njol.skript.events; + +import ch.njol.skript.Skript; +import ch.njol.skript.entity.EntityData; +import ch.njol.skript.lang.Literal; +import ch.njol.skript.lang.LiteralList; +import ch.njol.skript.lang.SkriptEvent; +import ch.njol.skript.lang.SkriptParser.ParseResult; +import ch.njol.skript.registrations.EventConverter; +import ch.njol.skript.registrations.EventValues; +import ch.njol.skript.util.slot.EquipmentSlot; +import ch.njol.skript.util.slot.Slot; +import org.bukkit.entity.Entity; +import org.bukkit.entity.LivingEntity; +import org.bukkit.event.Event; +import org.bukkit.event.entity.EntityShootBowEvent; +import org.bukkit.inventory.EntityEquipment; +import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class EvtEntityShootBow extends SkriptEvent { + + static { + Skript.registerEvent("Entity Shoot Bow", EvtEntityShootBow.class, EntityShootBowEvent.class, + "%entitydatas% shoot[ing] (bow|projectile)") + .description(""" + Called when an entity shoots a bow. + event-entity refers to the shot projectile/entity. + """) + .examples(""" + on player shoot bow: + chance of 30%: + damage event-slot by 10 + send "Your bow has taken increased damage!" to shooter + + on stray shooting bow: + set {_e} to event-entity + spawn a cow at {_e}: + set velocity of entity to velocity of {_e} + set event-entity to last spawned entity + """) + .since("INSERT VERSION"); + + EventValues.registerEventValue(EntityShootBowEvent.class, ItemStack.class, EntityShootBowEvent::getBow); + + EventValues.registerEventValue(EntityShootBowEvent.class, Entity.class, new EventConverter<>() { + @Override + public void set(EntityShootBowEvent event, @Nullable Entity entity) { + if (entity == null) + return; + event.setProjectile(entity); + } + + @Override + public @NotNull Entity convert(EntityShootBowEvent from) { + return from.getProjectile(); + } + }); + + EventValues.registerEventValue(EntityShootBowEvent.class, Slot.class, event -> { + EntityEquipment equipment = event.getEntity().getEquipment(); + if (equipment == null) + return null; + return new EquipmentSlot(equipment, event.getHand()); + }); + + } + + private Literal> entityDatas; + + @Override + public boolean init(Literal[] args, int matchedPattern, ParseResult parseResult) { + //noinspection unchecked + entityDatas = (Literal>) args[0]; + if (entityDatas instanceof LiteralList> list && list.getAnd()) + list.invertAnd(); + return true; + } + + @Override + public boolean check(Event event) { + if (!(event instanceof EntityShootBowEvent shootBowEvent)) + return false; + LivingEntity eventEntity = shootBowEvent.getEntity(); + return entityDatas.check(event, entityData -> entityData.isInstance(eventEntity)); + } + + @Override + public String toString(@Nullable Event event, boolean debug) { + return this.entityDatas.toString(event, debug) + " shoot bow"; + } + +} diff --git a/src/main/java/ch/njol/skript/expressions/ExprConsumedItem.java b/src/main/java/ch/njol/skript/expressions/ExprConsumedItem.java new file mode 100644 index 00000000000..1c6a758b7b4 --- /dev/null +++ b/src/main/java/ch/njol/skript/expressions/ExprConsumedItem.java @@ -0,0 +1,100 @@ +package ch.njol.skript.expressions; + +import ch.njol.skript.Skript; +import ch.njol.skript.classes.Changer; +import ch.njol.skript.doc.*; +import ch.njol.skript.lang.EventRestrictedSyntax; +import ch.njol.skript.lang.Expression; +import ch.njol.skript.lang.ExpressionType; +import ch.njol.skript.lang.SkriptParser.ParseResult; +import ch.njol.skript.lang.util.SimpleExpression; +import ch.njol.util.Kleenean; +import ch.njol.util.coll.CollectionUtils; +import org.bukkit.event.Event; +import org.bukkit.event.entity.EntityShootBowEvent; +import org.bukkit.event.player.PlayerItemConsumeEvent; +import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.Nullable; + +@Name("Consumed Item") +@Description("Represents the item consumed within an entity shoot bow and item consume event.") +@Example(""" + on player or skeleton shoot projectile: + if the consumed item is an arrow: + cancel event + send "You're now allowed to shoot your arrows." to shooter + """) +@Example(""" + on player consume: + if the consumed item is cooked porkchop: + send "Well aren't you just a little piggy wiggly!" to player + if player has scoreboard tag "vegetarian": + set the consumed item to a carrot + """) +@Since("INSERT VERSION") +public class ExprConsumedItem extends SimpleExpression implements EventRestrictedSyntax { + + static { + Skript.registerExpression(ExprConsumedItem.class, ItemStack.class, ExpressionType.SIMPLE, + "[the] consumed item"); + } + + private boolean allowsSettingConsumedItem; + + @Override + public boolean init(Expression[] expressions, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) { + this.allowsSettingConsumedItem = getParser().isCurrentEvent(PlayerItemConsumeEvent.class); + return true; + } + + @Override + protected ItemStack @Nullable [] get(Event event) { + if (event instanceof EntityShootBowEvent shootBowEvent) { + return new ItemStack[]{shootBowEvent.getConsumable()}; + } else if (event instanceof PlayerItemConsumeEvent consumeEvent) { + return new ItemStack[]{consumeEvent.getItem()}; + } + return null; + } + + @Override + public Class @Nullable [] acceptChange(Changer.ChangeMode mode) { + if (!allowsSettingConsumedItem) { + Skript.error("You may only set the consumed item in a player consume item event."); + return null; + } + return switch (mode) { + case SET -> CollectionUtils.array(ItemStack.class); + case DELETE -> CollectionUtils.array(); + default -> null; + }; + } + + @Override + public void change(Event event, Object @Nullable [] delta, Changer.ChangeMode mode) { + if (!(event instanceof PlayerItemConsumeEvent consumeEvent) || !allowsSettingConsumedItem) + return; + consumeEvent.setItem(delta == null ? null : (ItemStack) delta[0]); + } + + @Override + public Class[] supportedEvents() { + return CollectionUtils.array(EntityShootBowEvent.class, PlayerItemConsumeEvent.class); + } + + @Override + public boolean isSingle() { + return true; + } + + @Override + public Class getReturnType() { + return ItemStack.class; + } + + @Override + public String toString(@Nullable Event event, boolean debug) { + return "the consumed item"; + } + +} diff --git a/src/main/java/ch/njol/skript/expressions/ExprProjectileForce.java b/src/main/java/ch/njol/skript/expressions/ExprProjectileForce.java new file mode 100644 index 00000000000..46ed0c097e4 --- /dev/null +++ b/src/main/java/ch/njol/skript/expressions/ExprProjectileForce.java @@ -0,0 +1,62 @@ +package ch.njol.skript.expressions; + +import ch.njol.skript.Skript; +import ch.njol.skript.doc.*; +import ch.njol.skript.lang.EventRestrictedSyntax; +import ch.njol.skript.lang.Expression; +import ch.njol.skript.lang.ExpressionType; +import ch.njol.skript.lang.SkriptParser.ParseResult; +import ch.njol.skript.lang.util.SimpleExpression; +import ch.njol.util.Kleenean; +import ch.njol.util.coll.CollectionUtils; +import org.bukkit.event.Event; +import org.bukkit.event.entity.EntityShootBowEvent; +import org.jetbrains.annotations.Nullable; + +@Name("Projectile Force") +@Description("Returns the force at which a projectile was shot within an entity shoot bow event.") +@Example(""" + on entity shoot projectile: + set the velocity of shooter to vector(0,1,0) * projectile force + """) +@Since("INSERT VERSION") +public class ExprProjectileForce extends SimpleExpression implements EventRestrictedSyntax { + + static { + Skript.registerExpression(ExprProjectileForce.class, Float.class, ExpressionType.SIMPLE, + "[the] projectile force"); + } + + @Override + public boolean init(Expression[] expressions, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) { + return true; + } + + @Override + protected Float @Nullable [] get(Event event) { + if (!(event instanceof EntityShootBowEvent shotBowEvent)) + return null; + return new Float[]{shotBowEvent.getForce()}; + } + + @Override + public Class[] supportedEvents() { + return CollectionUtils.array(EntityShootBowEvent.class); + } + + @Override + public boolean isSingle() { + return true; + } + + @Override + public Class getReturnType() { + return Float.class; + } + + @Override + public String toString(@Nullable Event event, boolean debug) { + return "projectile force"; + } + +} diff --git a/src/main/java/ch/njol/skript/expressions/ExprShooter.java b/src/main/java/ch/njol/skript/expressions/ExprShooter.java index 48da301d59a..69e4d6ea5d4 100644 --- a/src/main/java/ch/njol/skript/expressions/ExprShooter.java +++ b/src/main/java/ch/njol/skript/expressions/ExprShooter.java @@ -2,10 +2,7 @@ import ch.njol.skript.Skript; import ch.njol.skript.classes.Changer.ChangeMode; -import ch.njol.skript.doc.Description; -import ch.njol.skript.doc.Examples; -import ch.njol.skript.doc.Name; -import ch.njol.skript.doc.Since; +import ch.njol.skript.doc.*; import ch.njol.skript.expressions.base.PropertyExpression; import ch.njol.skript.lang.Expression; import ch.njol.skript.lang.ExpressionType; @@ -15,16 +12,14 @@ import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Projectile; import org.bukkit.event.Event; +import org.bukkit.event.entity.EntityShootBowEvent; import org.bukkit.projectiles.ProjectileSource; import org.jetbrains.annotations.Nullable; -/** - * @author Peter Güttinger - */ @Name("Shooter") @Description("The shooter of a projectile.") -@Examples({"shooter is a skeleton"}) -@Since("1.3.7") +@Example("shooter is a skeleton") +@Since("1.3.7, INSERT VERSION (entity shoot bow event)") public class ExprShooter extends PropertyExpression { static { Skript.registerExpression(ExprShooter.class, LivingEntity.class, ExpressionType.SIMPLE, "[the] shooter [of %projectile%]"); @@ -41,6 +36,8 @@ public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelaye protected LivingEntity @Nullable [] get(Event event, Projectile[] source) { if (event instanceof EffSecShoot.ShootEvent shootEvent && getExpr().isDefault() && !(shootEvent.getProjectile() instanceof Projectile)) { return new LivingEntity[]{shootEvent.getShooter()}; + } else if (event instanceof EntityShootBowEvent shootBowEvent && getExpr().isDefault()) { + return new LivingEntity[]{shootBowEvent.getEntity()}; } return get(source, projectile -> {