diff --git a/src/main/java/ch/njol/skript/conditions/CondHasLineOfSight.java b/src/main/java/ch/njol/skript/conditions/CondHasLineOfSight.java new file mode 100644 index 00000000000..dd4a18f9ab0 --- /dev/null +++ b/src/main/java/ch/njol/skript/conditions/CondHasLineOfSight.java @@ -0,0 +1,82 @@ +/** + * This file is part of Skript. + * + * Skript is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Skript is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Skript. If not, see . + * + * Copyright Peter Güttinger, SkriptLang team and contributors + */ +package ch.njol.skript.conditions; + +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.Since; +import ch.njol.skript.lang.Condition; +import ch.njol.skript.lang.Expression; +import ch.njol.skript.lang.SkriptParser.ParseResult; +import ch.njol.util.Kleenean; +import org.bukkit.Location; +import org.bukkit.entity.Entity; +import org.bukkit.entity.LivingEntity; +import org.bukkit.event.Event; +import org.eclipse.jdt.annotation.Nullable; + +@Name("Has Line of Sight") +@Description("Checks whether living entities have an unobstructed line of sight to other entities or locations.") +@Examples({ + "player has direct line of sight to location 5 blocks to the right of player", + "victim has line of sight to attacker", + "player has no line of sight to location 100 blocks in front of player" +}) +@Since("INSERT VERSION") +public class CondHasLineOfSight extends Condition { + + static { + Skript.registerCondition(CondHasLineOfSight.class, + "%livingentities% (has|have) [a] [direct] line of sight to %entities/locations%", + "%livingentities% does(n't| not) have [a] [direct] line of sight to %entities/locations%", + "%livingentities% (has|have) no [direct] line of sight to %entities/locations%"); + } + + private Expression viewers; + private Expression targets; + + @Override + public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) { + viewers = (Expression) exprs[0]; + targets = exprs[1]; + setNegated(matchedPattern > 0); + return true; + } + + @Override + public boolean check(Event event) { + return targets.check(event, (target) -> { + if (target instanceof Entity) { + return viewers.check(event, (viewer) -> viewer.hasLineOfSight((Entity) target)); + } else if (target instanceof Location) { + return viewers.check(event, (viewer) -> viewer.hasLineOfSight((Location) target)); + } else { + return false; + } + }, isNegated()); + } + + @Override + public String toString(@Nullable Event event, boolean debug) { + return viewers.toString(event, debug) + " has" + (isNegated() ? " no" : "") + " line of sight to " + targets.toString(event,debug); + } + +} diff --git a/src/test/skript/tests/syntaxes/conditions/CondHasLineOfSight.sk b/src/test/skript/tests/syntaxes/conditions/CondHasLineOfSight.sk new file mode 100644 index 00000000000..63f8faff16e --- /dev/null +++ b/src/test/skript/tests/syntaxes/conditions/CondHasLineOfSight.sk @@ -0,0 +1,18 @@ +test "line of sight": + set {_a} to (spawn of world "world") + set {_b} to {_a} ~ vector(0, 10, 0) + loop blocks between {_a} and {_b}: + set {_block::%loop-block%} to type of loop-block + set loop-block to air + spawn pig at spawn of world "world" + set {_pig1} to last spawned entity + spawn pig at {_b}: + assert pig has line of sight to {_pig1} with "Pigs should have line of sight to each other 1" + assert {_pig1} has line of sight to pig with "Pigs should have line of sight to each other 2" + set block at ({_a} ~ vector(0, 5, 0)) to stone + assert pig has no line of sight to {_pig1} with "Pigs should not have line of sight to each other 1" + assert {_pig1} has no line of sight to pig with "Pigs should not have line of sight to each other 2" + delete pig + delete entity within {_pig1} + loop blocks between {_a} and {_b}: + set loop-block to {_block::%loop-block%}