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 6 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,62 +1,70 @@
package ch.njol.skript.expressions;

import ch.njol.skript.doc.*;
import ch.njol.skript.lang.SyntaxStringBuilder;
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;
import org.joml.Quaternionf;
import org.joml.Vector3f;


/**
* @author bi0qaw
*/
@Name("Vectors - Location Vector Offset")
@Description("Returns the location offset by vectors.")
@Examples({"set {_loc} to {_loc} ~ {_v}"})
@Since("2.2-dev28")
@Description("Returns the location offset by vectors. Supports both global and local axes. " +
"When using local axes, the vector is applied relative to the direction the location is facing.")
@Example("set {_loc} to {_loc} ~ {_v}")
@Example("""
# spawn a tnt 5 blocks in front 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 (local axes)")
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) {
// noinspection unchecked
location = (Expression<Location>) exprs[0];
// noinspection unchecked
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);
return CollectionUtils.array(clone);

Location clone = location.clone();

for (Vector vector : vectors.getArray(event)) {
if (usingLocalAxes) {
clone = getFacingRelativeOffset(clone, vector);
} else {
clone.add(vector);
}
}
return new Location[]{ clone };
}

@Override
Expand All @@ -70,8 +78,36 @@ 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 new SyntaxStringBuilder(event, debug)
.append(location)
.append("offset by")
.append(vectors)
.append(usingLocalAxes ? "using local axes" : "")
.toString();
}

/**
* 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) {
float yawRad = (float) Math.toRadians(-loc.getYaw());
float pitchRad = (float) Math.toRadians(loc.getPitch());
float rollRad = 0f;

Quaternionf rotation = new Quaternionf().rotateYXZ(yawRad, pitchRad, rollRad);
Vector3f localOffset = offset.toVector3f();
rotation.transform(localOffset);

return loc.add(localOffset.x, localOffset.y, localOffset.z);
Comment on lines +108 to +117
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it'd make the code a bit nicer and standard if this returned a vector instead of a location, so the .add is done in the same spot as the normal add.

}

}