2024-10-26 01:13:09 +02:00

137 lines
4.5 KiB
Java

package com.hbm.entity.mob.ai;
import com.hbm.handler.HbmKeybinds.EnumKeybind;
import com.hbm.items.weapon.sedna.GunConfig;
import com.hbm.items.weapon.sedna.ItemGunBaseNT;
import com.hbm.items.weapon.sedna.Receiver;
import com.hbm.items.weapon.sedna.ItemGunBaseNT.GunState;
import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.ai.EntityAIBase;
import net.minecraft.item.ItemStack;
public class EntityAIFireGun extends EntityAIBase {
private final EntityLiving host;
private double attackMoveSpeed = 1.0D; // how fast we move while in this state
private double maxRange = 20; // how far our target can be before we stop shooting
private int burstTime = 10; // maximum number of ticks in a burst (for automatic weapons)
private int minWait = 10; // minimum number of ticks to wait between bursts/shots
private int maxWait = 40; // maximum number of ticks to wait between bursts/shots
private float inaccuracy = 30; // how many degrees of inaccuracy does the AI have
// state timers
private int attackTimer = 0;
private FireState state = FireState.IDLE;
private int stateTimer = 0;
private static enum FireState {
IDLE,
WAIT,
FIRING,
RELOADING,
}
public EntityAIFireGun(EntityLiving host) {
this.host = host;
}
@Override
public boolean shouldExecute() {
return host.getAttackTarget() != null && getYerGun() != null;
}
@Override
public void updateTask() {
EntityLivingBase target = host.getAttackTarget();
ItemStack stack = host.getHeldItem();
ItemGunBaseNT gun = getYerGun();
gun.onUpdate(stack, host.worldObj, host, 0, true);
double distanceToTargetSquared = host.getDistanceSq(target.posX, target.posY, target.posZ);
boolean canSeeTarget = host.getEntitySenses().canSee(target);
if(canSeeTarget) {
attackTimer++;
} else {
attackTimer = 0;
}
if(distanceToTargetSquared < maxRange * maxRange && attackTimer > 20) {
host.getNavigator().clearPathEntity();
} else {
host.getNavigator().tryMoveToEntityLiving(target, attackMoveSpeed);
}
host.getLookHelper().setLookPositionWithEntity(target, 30.0F, 30.0F);
stateTimer--;
if(stateTimer < 0) {
stateTimer = 0;
if(state == FireState.WAIT) {
updateState(FireState.IDLE, 0, gun, stack);
} else if(state != FireState.IDLE) {
updateState(FireState.WAIT, host.worldObj.rand.nextInt(maxWait - minWait) + minWait, gun, stack);
}
} else if(state == FireState.FIRING) {
// Keep the trigger held throughout the duration of firing
updateKeybind(gun, stack, EnumKeybind.GUN_PRIMARY);
}
if(canSeeTarget && distanceToTargetSquared < maxRange * maxRange) {
if(state == FireState.IDLE) {
GunConfig config = gun.getConfig(stack, 0);
Receiver rec = config.getReceivers(stack)[0];
if(rec.getMagazine(stack).getAmount(stack, null) <= 0) {
updateState(FireState.RELOADING, 20, gun, stack);
} else if(ItemGunBaseNT.getState(stack, 0) == GunState.IDLE) {
updateState(FireState.FIRING, host.worldObj.rand.nextInt(burstTime), gun, stack);
}
}
}
}
private void updateState(FireState toState, int time, ItemGunBaseNT gun, ItemStack stack) {
state = toState;
stateTimer = time;
switch(state) {
case FIRING: updateKeybind(gun, stack, EnumKeybind.GUN_PRIMARY);
case RELOADING: updateKeybind(gun, stack, EnumKeybind.RELOAD);
default: clearKeybinds(gun, stack); break;
}
}
private void clearKeybinds(ItemGunBaseNT gun, ItemStack stack) {
updateKeybind(gun, stack, null);
}
private void updateKeybind(ItemGunBaseNT gun, ItemStack stack, EnumKeybind bind) {
// Turn body to face firing direction, since the gun is attached to that, not the head
// Also apply accuracy debuff just before firing
if(bind != null && bind != EnumKeybind.RELOAD) {
host.rotationYawHead += (host.worldObj.rand.nextFloat() - 0.5F) * inaccuracy;
host.rotationPitch += (host.worldObj.rand.nextFloat() - 0.5F) * inaccuracy;
host.rotationYaw = host.rotationYawHead;
}
gun.handleKeybind(host, null, stack, EnumKeybind.GUN_PRIMARY, bind == EnumKeybind.GUN_PRIMARY);
gun.handleKeybind(host, null, stack, EnumKeybind.GUN_SECONDARY, bind == EnumKeybind.GUN_SECONDARY);
gun.handleKeybind(host, null, stack, EnumKeybind.GUN_TERTIARY, bind == EnumKeybind.GUN_TERTIARY);
gun.handleKeybind(host, null, stack, EnumKeybind.RELOAD, bind == EnumKeybind.RELOAD);
}
public ItemGunBaseNT getYerGun() {
ItemStack stack = host.getHeldItem();
if(stack == null || !(stack.getItem() instanceof ItemGunBaseNT)) return null;
return (ItemGunBaseNT) stack.getItem();
}
}