Skip to content

Facing Relative Vector Offset #7925

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
Changes from 4 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
Original file line number Diff line number Diff line change
@@ -1,61 +1,64 @@
package ch.njol.skript.expressions;

import ch.njol.skript.doc.*;
import org.bukkit.Location;
import org.bukkit.event.Event;
import org.bukkit.util.Vector;
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.Since;
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;


/**
* @author bi0qaw
*/
@Name("Vectors - Location Vector Offset")
@Description("Returns the location offset by vectors.")
@Examples({"set {_loc} to {_loc} ~ {_v}"})
@Since("2.2-dev28")
@Example("set {_loc} to {_loc} ~ {_v}")
@Example("""
# spawn a tnt 5 blocks infront of player
set {_l} to player's location offset by vector(0, 1, 5) using local axes
spawn tnt at {_l}
""")
@Since("2.2-dev28, INSERT VERSION (facing relative)")
public class ExprLocationVectorOffset extends SimpleExpression<Location> {

static {
Skript.registerExpression(ExprLocationVectorOffset.class, Location.class, ExpressionType.COMBINED,
"%location% offset by [[the] vectors] %vectors%",
"%location% offset by [[the] vectors] %vectors% [facingrelative:using local axes]",
"%location%[ ]~[~][ ]%vectors%");
}

@SuppressWarnings("null")
private Expression<Location> location;

@SuppressWarnings("null")
private Expression<Vector> vectors;

private boolean usingLocalAxes;

@Override
@SuppressWarnings({"unchecked", "null"})
public boolean init(Expression<?>[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) {
location = (Expression<Location>) exprs[0];
vectors = (Expression<Vector>) exprs[1];
usingLocalAxes = parseResult.hasTag("facingrelative");
return true;
}

@SuppressWarnings("null")
@Override
protected Location[] get(Event e) {
Location l = location.getSingle(e);
if (l == null)
protected Location[] get(Event event) {
Location location = this.location.getSingle(event);
if (location == null)
return null;
Location clone = l.clone();
for (Vector v : vectors.getArray(e))
clone.add(v);

Location clone = location.clone();

for (Vector vector : vectors.getArray(event)) {
if (usingLocalAxes) {
clone = getFacingRelativeOffset(clone, vector);
} else {
clone.add(vector);
}
}
return CollectionUtils.array(clone);
}

Expand All @@ -70,8 +73,32 @@ public Class<? extends Location> getReturnType() {
}

@Override
public String toString(@Nullable Event e, boolean debug) {
return location.toString() + " offset by " + vectors.toString();
public String toString(@Nullable Event event, boolean debug) {
return location.toString(event, debug) + " offset by " + vectors.toString(event, debug) + (usingLocalAxes ? " using local axes" : "");
}

/**
* Returns a location offset from the given location, adjusted for the location's rotation.
* <p>
* This behaves similarly to Minecraft's {@code /summon zombie ^ ^ ^1} command,
* where the offset is applied relative to the entity's facing direction.
*
* @see <a href="https://minecraft.wiki/w/Coordinates#Local_coordinates">Local Coordinates</a>.
* @param loc The location
* @param offset The offset
* @return The offset location
*/
private static Location getFacingRelativeOffset(Location loc, Vector offset) {
Vector forward = loc.getDirection();
Vector up = new Vector(0, 1, 0);
Vector left = up.clone().crossProduct(forward).normalize();

Vector o = new Vector(0, 0, 0);
o.add(left.multiply(offset.getX()));
o.add(up.multiply(offset.getY()));
o.add(forward.multiply(offset.getZ()));

return loc.add(o);
}

}