96 lines
3.3 KiB
Java
96 lines
3.3 KiB
Java
package com.jdh.microcraft.entity.ai;
|
|
|
|
import com.jdh.microcraft.Global;
|
|
import com.jdh.microcraft.entity.Entity;
|
|
import com.jdh.microcraft.level.Level;
|
|
import com.jdh.microcraft.level.tile.Tile;
|
|
import com.jdh.microcraft.level.tile.TileLava;
|
|
import com.jdh.microcraft.util.Direction;
|
|
import com.jdh.microcraft.util.FMath;
|
|
import com.jdh.microcraft.util.Time;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.stream.Collectors;
|
|
|
|
public abstract class AIHostileMob extends AI {
|
|
protected final double sightDistance;
|
|
protected final int targetPermanenceTicks;
|
|
|
|
protected final double strength;
|
|
protected int ticksSinceTargetSeen;
|
|
public Entity target;
|
|
|
|
public AIHostileMob(Entity entity, double strength) {
|
|
super(entity);
|
|
this.strength = strength;
|
|
this.sightDistance = (16 * 10) * this.strength;
|
|
this.targetPermanenceTicks = (int) (180 * this.strength);
|
|
}
|
|
|
|
// avoid really dangerous stuff
|
|
protected boolean shouldMove(int dx, int dy) {
|
|
int cx = this.entity.getCenterX() + dx,
|
|
cy = this.entity.getCenterY() + dy,
|
|
tx = Level.toTile(cx),
|
|
ty = Level.toTile(cy);
|
|
|
|
return !(Tile.TILES[this.entity.level.getTile(tx, ty)] instanceof TileLava);
|
|
}
|
|
|
|
protected abstract void moveTowards(int x, int y);
|
|
|
|
@Override
|
|
public void tick() {
|
|
super.tick();
|
|
|
|
if (this.entity.level.player != null &&
|
|
FMath.norm(this.entity.x - this.entity.level.player.x,
|
|
this.entity.y - this.entity.level.player.y) <= this.sightDistance) {
|
|
this.target = this.entity.level.player;
|
|
this.ticksSinceTargetSeen = 0;
|
|
} else {
|
|
this.ticksSinceTargetSeen++;
|
|
|
|
// lose target if it has been too long
|
|
if (this.ticksSinceTargetSeen >= this.targetPermanenceTicks) {
|
|
this.target = null;
|
|
}
|
|
}
|
|
|
|
if (this.target != null) {
|
|
int tcx = this.target.x + (this.target.width / 2),
|
|
tcy = this.target.y + (this.target.height / 2),
|
|
tdx = tcx - this.entity.x,
|
|
tdy = tcy - this.entity.y;
|
|
|
|
double pd = this.getPreferredTargetDistance(),
|
|
pdt = this.getPreferredTargetDistanceThreshold();
|
|
|
|
if (Math.abs(tdx) - pd > pdt ||
|
|
Math.abs(tdy) - pd > pdt) {
|
|
this.moveTowards(this.target.x, this.target.y);
|
|
} else if (pd != 0.0 && pdt != 0.0) {
|
|
// ranged mobs: strafe in directions not towards the target
|
|
Global.random.setSeed(Global.ticks / Time.TPS);
|
|
if (Global.random.nextInt(3) == 0) {
|
|
Direction td = Direction.get(tdx, tdy);
|
|
Direction strafeDir = new ArrayList<>(Direction.ALL)
|
|
.stream()
|
|
.filter(d -> d != td && d != td.opposite())
|
|
.collect(Collectors.toList())
|
|
.get(Global.random.nextInt(2));
|
|
this.moveTowards(this.entity.x + strafeDir.x, this.entity.y + strafeDir.y);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
protected double getPreferredTargetDistance() {
|
|
return 0.0;
|
|
}
|
|
|
|
protected double getPreferredTargetDistanceThreshold() {
|
|
return 0.0;
|
|
}
|
|
}
|