107 lines
3.3 KiB
Java
107 lines
3.3 KiB
Java
package net.citizensnpcs.trait;
|
|
|
|
import java.util.Collections;
|
|
import java.util.Comparator;
|
|
import java.util.List;
|
|
|
|
import net.citizensnpcs.Settings.Setting;
|
|
import net.citizensnpcs.api.abstraction.WorldVector;
|
|
import net.citizensnpcs.api.abstraction.entity.Entity;
|
|
import net.citizensnpcs.api.abstraction.entity.LandMob;
|
|
import net.citizensnpcs.api.abstraction.entity.Player;
|
|
import net.citizensnpcs.api.attachment.Attachment;
|
|
import net.citizensnpcs.api.exception.NPCLoadException;
|
|
import net.citizensnpcs.api.npc.NPC;
|
|
import net.citizensnpcs.api.util.DataKey;
|
|
|
|
public class LookClose extends Attachment implements Runnable, Toggleable {
|
|
private boolean enabled = Setting.DEFAULT_LOOK_CLOSE.asBoolean();
|
|
private Player lookingAt;
|
|
private final LandMob entity;
|
|
|
|
public LookClose(NPC npc) {
|
|
this.entity = (LandMob) npc.getEntity();
|
|
}
|
|
|
|
private void faceEntity(Entity from, Entity at) {
|
|
if (from.getWorld() != at.getWorld())
|
|
return;
|
|
WorldVector loc = from.getLocation();
|
|
|
|
double xDiff = at.getLocation().getX() - loc.getX();
|
|
double yDiff = at.getLocation().getY() - loc.getY();
|
|
double zDiff = at.getLocation().getZ() - loc.getZ();
|
|
|
|
double distanceXZ = Math.sqrt(xDiff * xDiff + zDiff * zDiff);
|
|
double distanceY = Math.sqrt(distanceXZ * distanceXZ + yDiff * yDiff);
|
|
|
|
double yaw = (Math.acos(xDiff / distanceXZ) * 180 / Math.PI);
|
|
double pitch = (Math.acos(yDiff / distanceY) * 180 / Math.PI) - 90;
|
|
if (zDiff < 0.0) {
|
|
yaw = yaw + (Math.abs(180 - yaw) * 2);
|
|
}
|
|
|
|
from.setRotation((float) yaw - 90, (float) pitch);
|
|
}
|
|
|
|
@Override
|
|
public void load(DataKey key) throws NPCLoadException {
|
|
enabled = key.getBoolean("");
|
|
}
|
|
|
|
@Override
|
|
public void run() {
|
|
if (!enabled || entity.hasDestination())
|
|
return;
|
|
if (hasInvalidTarget())
|
|
findNewTarget();
|
|
|
|
if (lookingAt != null)
|
|
faceEntity(entity, lookingAt);
|
|
}
|
|
|
|
private void findNewTarget() {
|
|
List<Entity> nearby = entity.getNearbyEntities(2.5, 5, 2.5);
|
|
Collections.sort(nearby, new Comparator<Entity>() {
|
|
@Override
|
|
public int compare(Entity o1, Entity o2) {
|
|
double d1 = o1.getLocation().distanceSquared(entity.getLocation());
|
|
double d2 = o2.getLocation().distanceSquared(entity.getLocation());
|
|
return Double.compare(d1, d2);
|
|
}
|
|
});
|
|
for (Entity entity : nearby) {
|
|
if (entity instanceof Player) {
|
|
lookingAt = (Player) entity;
|
|
return;
|
|
}
|
|
}
|
|
lookingAt = null;
|
|
}
|
|
|
|
private boolean hasInvalidTarget() {
|
|
if (lookingAt == null)
|
|
return true;
|
|
if (!lookingAt.isOnline() || lookingAt.getWorld() != entity.getWorld()
|
|
|| lookingAt.getLocation().distanceSquared(entity.getLocation()) > 5) {
|
|
lookingAt = null;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
@Override
|
|
public void save(DataKey key) {
|
|
key.setBoolean("", enabled);
|
|
}
|
|
|
|
@Override
|
|
public boolean toggle() {
|
|
return (enabled = !enabled);
|
|
}
|
|
|
|
@Override
|
|
public String toString() {
|
|
return "LookClose{" + enabled + "}";
|
|
}
|
|
} |