Files
CustomNPC-Plus/src/main/java/noppes/npcs/entity/EntityNPCInterface.java
T

1968 lines
58 KiB
Java
Raw Normal View History

2018-09-13 12:03:28 -04:00
package noppes.npcs.entity;
2023-01-12 21:33:06 -05:00
import cpw.mods.fml.common.registry.IEntityAdditionalSpawnData;
2018-09-13 12:03:28 -04:00
import io.netty.buffer.ByteBuf;
import net.minecraft.block.Block;
2022-11-12 15:53:20 -06:00
import net.minecraft.block.material.Material;
2018-09-13 12:03:28 -04:00
import net.minecraft.command.ICommandSender;
import net.minecraft.command.IEntitySelector;
import net.minecraft.entity.*;
2021-06-13 16:22:06 -04:00
import net.minecraft.entity.ai.*;
2018-09-13 12:03:28 -04:00
import net.minecraft.entity.ai.EntityAITasks.EntityAITaskEntry;
import net.minecraft.entity.boss.IBossDisplayData;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.entity.monster.EntityMob;
import net.minecraft.entity.monster.EntityZombie;
import net.minecraft.entity.passive.EntityBat;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.entity.projectile.EntityArrow;
import net.minecraft.entity.projectile.EntityThrowable;
2022-11-13 23:49:49 -06:00
import net.minecraft.init.Blocks;
2018-09-13 12:03:28 -04:00
import net.minecraft.item.Item;
2021-09-24 16:50:28 -04:00
import net.minecraft.item.ItemBow;
2018-09-13 12:03:28 -04:00
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.network.play.server.S0BPacketAnimation;
import net.minecraft.pathfinding.PathNavigate;
2018-09-13 12:03:28 -04:00
import net.minecraft.potion.Potion;
import net.minecraft.potion.PotionEffect;
import net.minecraft.server.MinecraftServer;
2023-01-12 21:33:06 -05:00
import net.minecraft.util.*;
2018-09-13 12:03:28 -04:00
import net.minecraft.world.World;
import net.minecraft.world.WorldServer;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.common.util.FakePlayer;
import net.minecraftforge.event.ServerChatEvent;
2022-03-23 03:54:06 -05:00
import noppes.npcs.*;
2018-09-13 12:03:28 -04:00
import noppes.npcs.ai.EntityAIMoveIndoors;
import noppes.npcs.ai.EntityAIPanic;
import noppes.npcs.ai.EntityAIWander;
import noppes.npcs.ai.EntityAIWatchClosest;
2023-01-12 21:33:06 -05:00
import noppes.npcs.ai.*;
import noppes.npcs.ai.pathfinder.FlyingMoveHelper;
import noppes.npcs.ai.pathfinder.PathNavigateFlying;
2018-09-13 12:03:28 -04:00
import noppes.npcs.ai.selector.NPCAttackSelector;
import noppes.npcs.ai.target.EntityAIClearTarget;
import noppes.npcs.ai.target.EntityAIClosestTarget;
import noppes.npcs.ai.target.EntityAIOwnerHurtByTarget;
import noppes.npcs.ai.target.EntityAIOwnerHurtTarget;
2023-01-12 21:33:06 -05:00
import noppes.npcs.api.entity.ICustomNpc;
2023-12-03 20:48:37 -06:00
import noppes.npcs.api.handler.data.ILine;
2023-01-12 21:33:06 -05:00
import noppes.npcs.api.item.IItemStack;
2018-09-13 12:03:28 -04:00
import noppes.npcs.client.EntityUtil;
2023-01-07 00:21:08 -05:00
import noppes.npcs.config.ConfigMain;
2023-01-12 21:33:06 -05:00
import noppes.npcs.constants.*;
2018-09-13 12:03:28 -04:00
import noppes.npcs.controllers.FactionController;
import noppes.npcs.controllers.LinkedNpcController;
import noppes.npcs.controllers.LinkedNpcController.LinkedData;
import noppes.npcs.controllers.PlayerDataController;
2023-01-12 21:33:06 -05:00
import noppes.npcs.controllers.data.*;
import noppes.npcs.entity.data.DataTimers;
2022-06-12 01:26:23 -05:00
import noppes.npcs.roles.*;
2023-03-15 23:10:03 -05:00
import noppes.npcs.scripted.NpcAPI;
import noppes.npcs.scripted.entity.ScriptNpc;
2023-01-12 21:33:06 -05:00
import noppes.npcs.scripted.event.NpcEvent;
2018-09-13 12:03:28 -04:00
import noppes.npcs.util.GameProfileAlt;
2023-01-12 21:33:06 -05:00
import java.io.IOException;
import java.util.*;
2018-09-13 12:03:28 -04:00
public abstract class EntityNPCInterface extends EntityCreature implements IEntityAdditionalSpawnData, ICommandSender, IRangedAttackMob, IBossDisplayData {
public ICustomNpc wrappedNPC;
2018-09-13 12:03:28 -04:00
public static final GameProfileAlt chateventProfile = new GameProfileAlt();
public static FakePlayer chateventPlayer;
2018-09-13 12:03:28 -04:00
public DataDisplay display;
public DataStats stats;
public DataAI ai;
public DataAdvanced advanced;
public DataInventory inventory;
public DataScript script;
2022-05-24 01:08:23 -05:00
public DataTransform transform;
public DataTimers timers;
2022-11-15 00:48:31 -05:00
public CombatHandler combatHandler = new CombatHandler(this);
2018-09-13 12:03:28 -04:00
public String linkedName = "";
public long linkedLast = 0;
public LinkedData linkedData;
2022-11-15 00:48:31 -05:00
2018-09-13 12:03:28 -04:00
public float baseHeight = 1.8f;
public float scaleX, scaleY, scaleZ;
private boolean wasKilled = false;
public RoleInterface roleInterface;
public JobInterface jobInterface;
public HashMap<Integer, DialogOption> dialogs;
public boolean hasDied = false;
public long killedtime = 0;
public long totalTicksAlive = 0;
private int taskCount = 1;
public int lastInteract = 0;
2022-06-12 01:26:23 -05:00
public int itemGiverId = 0;
2024-02-15 17:49:48 -05:00
public boolean isDrawn = false;
2021-04-29 20:42:52 -04:00
2018-09-13 12:03:28 -04:00
public Faction faction; //should only be used server side
2022-11-15 00:48:31 -05:00
2018-09-13 12:03:28 -04:00
private EntityAIRangedAttack aiRange;
private EntityAIBase aiResponse, aiLeap, aiSprint, aiAttackTarget;
2022-11-15 00:48:31 -05:00
2018-09-13 12:03:28 -04:00
public List<EntityLivingBase> interactingEntities = new ArrayList<EntityLivingBase>();
public ResourceLocation textureLocation = null;
2022-11-15 00:48:31 -05:00
2018-09-13 12:03:28 -04:00
public EnumAnimation currentAnimation = EnumAnimation.NONE;
2022-11-15 00:48:31 -05:00
2018-09-13 12:03:28 -04:00
public int npcVersion = VersionCompatibility.ModRev;
public IChatMessages messages;
public boolean updateClient = false;
public boolean updateAI = false;
2022-11-15 00:48:31 -05:00
public FlyingMoveHelper flyMoveHelper = new FlyingMoveHelper(this);
public PathNavigate flyNavigator = new PathNavigateFlying(this, worldObj);
2021-06-13 16:22:06 -04:00
2018-09-13 12:03:28 -04:00
public EntityNPCInterface(World world) {
super(world);
try{
if (canFly()) {
this.getNavigator().setCanSwim(true);
this.tasks.addTask(0, new EntityAISwimming(this));
} else {
this.tasks.addTask(0, new EntityAIWaterNav(this));
}
2018-09-13 12:03:28 -04:00
dialogs = new HashMap<Integer, DialogOption>();
2023-01-07 00:21:08 -05:00
if(!ConfigMain.DefaultInteractLine.isEmpty())
advanced.interactLines.lines.put(0, new Line(ConfigMain.DefaultInteractLine));
2022-11-15 00:48:31 -05:00
2018-09-13 12:03:28 -04:00
experienceValue = 0;
scaleX = scaleY = scaleZ = 0.9375f;
2022-11-15 00:48:31 -05:00
2018-09-13 12:03:28 -04:00
faction = getFaction();
setFaction(faction.id);
setSize(1, 1);
this.updateTasks();
2023-09-15 14:33:24 -04:00
this.func_110163_bv();
if (!this.isRemote() && this.wrappedNPC == null) {
this.wrappedNPC = new ScriptNpc<>(this);
}
2018-09-13 12:03:28 -04:00
}
catch(Exception e){
e.printStackTrace();
}
2022-11-15 00:48:31 -05:00
}
2018-09-13 12:03:28 -04:00
@Override
2022-11-15 00:48:31 -05:00
protected void applyEntityAttributes(){
super.applyEntityAttributes();
2018-09-13 12:03:28 -04:00
display = new DataDisplay(this);
stats = new DataStats(this);
2022-11-15 00:48:31 -05:00
ai = new DataAI(this);
2018-09-13 12:03:28 -04:00
advanced = new DataAdvanced(this);
inventory = new DataInventory(this);
2022-05-24 01:08:23 -05:00
transform = new DataTransform(this);
2018-09-13 12:03:28 -04:00
script = new DataScript(this);
timers = new DataTimers(this);
2022-11-15 00:48:31 -05:00
this.getAttributeMap().registerAttribute(SharedMonsterAttributes.attackDamage);
2018-09-13 12:03:28 -04:00
this.getEntityAttribute(SharedMonsterAttributes.maxHealth).setBaseValue(stats.maxHealth);
2023-01-07 00:21:08 -05:00
this.getEntityAttribute(SharedMonsterAttributes.followRange).setBaseValue(ConfigMain.NpcNavRange);
this.getEntityAttribute(SharedMonsterAttributes.movementSpeed).setBaseValue(this.getSpeed());
2022-11-15 00:48:31 -05:00
this.getEntityAttribute(SharedMonsterAttributes.attackDamage).setBaseValue(stats.getAttackStrength());
}
2018-09-13 12:03:28 -04:00
@Override
protected void entityInit() {
super.entityInit();
this.dataWatcher.addObject(13, String.valueOf(""));//faction
this.dataWatcher.addObject(14, Integer.valueOf(0)); // Animation
this.dataWatcher.addObject(15, Integer.valueOf(0)); // isWalking
this.dataWatcher.addObject(16, String.valueOf("")); // Role
}
2022-11-15 00:48:31 -05:00
protected boolean isAIEnabled(){
return true;
}
@Override
public boolean getLeashed(){
return false; //Prevents npcs from being leashed
}
@Override
public boolean isEntityAlive(){
return super.isEntityAlive() && !isKilled();
}
2018-09-13 12:03:28 -04:00
@Override
public void onUpdate(){
super.onUpdate();
if (!isRemote()) {
if (this.ticksExisted % 10 == 0) {
EventHooks.onNPCUpdate(this);
}
for(int i=1;i<3;i++){
ItemStack itemstack = inventory.prevWeapons.get(i);
ItemStack itemstack1 = inventory.weapons.get(i);
if (!ItemStack.areItemStacksEqual(itemstack1, itemstack))
{
NBTTagCompound itemNBT = new NBTTagCompound();
if(itemstack1!=null){
itemstack1.writeToNBT(itemNBT);
}
for(Object obj: MinecraftServer.getServer().getConfigurationManager().playerEntityList){
Server.sendData((EntityPlayerMP) obj, EnumPacketClient.SYNC_WEAPON, getEntityId(), i, itemNBT);
}
inventory.prevWeapons.put(i,itemstack1 == null ? null : itemstack1.copy());
}
}
this.timers.update();
2022-03-23 03:54:06 -05:00
}
2018-09-13 12:03:28 -04:00
}
2022-11-15 00:48:31 -05:00
2018-09-13 12:03:28 -04:00
public void setWorld(World world){
super.setWorld(world);
script.setWorld(world);
}
public int getMaxSafePointTries()
{
2022-11-10 03:26:32 -06:00
return 3;
}
2022-11-15 00:48:31 -05:00
@Override
public boolean attackEntityAsMob(Entity par1Entity){
float f = stats.getAttackStrength();
if (stats.attackSpeed < 10){
par1Entity.hurtResistantTime = 0;
}
if(par1Entity instanceof EntityLivingBase && !isRemote()){
NpcEvent.MeleeAttackEvent event = new NpcEvent.MeleeAttackEvent(wrappedNPC, f, (EntityLivingBase)par1Entity);
if(EventHooks.onNPCMeleeAttack(this, event))
2018-09-13 12:03:28 -04:00
return false;
f = event.getDamage();
2022-11-15 00:48:31 -05:00
}
boolean var4 = par1Entity.attackEntityFrom(new NpcDamageSource("mob", this), f);
if (var4){
if(getOwner() instanceof EntityPlayer)
NPCEntityHelper.setRecentlyHit((EntityLivingBase)par1Entity);
if (stats.knockback > 0){
par1Entity.addVelocity((double)(-MathHelper.sin(this.rotationYaw * (float)Math.PI / 180.0F) * (float)stats.knockback * 0.5F), 0.1D, (double)(MathHelper.cos(this.rotationYaw * (float)Math.PI / 180.0F) * (float)stats.knockback * 0.5F));
this.motionX *= 0.6D;
this.motionZ *= 0.6D;
}
if(advanced.role == EnumRoleType.Companion){
((RoleCompanion)roleInterface).attackedEntity(par1Entity);
}
}
if (stats.potionType != EnumPotionType.None){
if (stats.potionType != EnumPotionType.Fire)
((EntityLivingBase)par1Entity).addPotionEffect(new PotionEffect(this.getPotionEffect(stats.potionType), stats.potionDuration * 20, stats.potionAmp));
else
par1Entity.setFire(stats.potionDuration);
}
return var4;
}
@Override
public void swingItem()
{
ItemStack stack = this.getHeldItem();
if (stack != null && stack.getItem() != null)
{
Item item = stack.getItem();
if (item.onEntitySwing(this, stack))
{
return;
}
}
if (!this.isSwingInProgress || this.swingProgressInt >= this.getArmSwingAnimationEnd() / 2 || this.swingProgressInt < 0)
{
NpcEvent.SwingEvent event = new NpcEvent.SwingEvent(wrappedNPC, stack);
if(EventHooks.onNPCMeleeSwing(this, event))
return;
this.swingProgressInt = -1;
this.isSwingInProgress = true;
if (this.worldObj instanceof WorldServer)
{
((WorldServer)this.worldObj).getEntityTracker().func_151247_a(this, new S0BPacketAnimation(this, 0));
}
}
}
2022-11-15 00:48:31 -05:00
@Override
public void onLivingUpdate(){
if(CustomNpcs.FreezeNPCs)
return;
totalTicksAlive++;
this.updateArmSwingProgress();
if(this.ticksExisted % 20 == 0)
2018-09-13 12:03:28 -04:00
faction = getFaction();
if(!worldObj.isRemote){
2022-11-15 00:48:31 -05:00
if(!isKilled() && this.ticksExisted % 20 == 0){
if(this.getHealth() < this.getMaxHealth()){
if(stats.healthRegen > 0 && !isAttacking())
heal(stats.healthRegen);
if(stats.combatRegen > 0 && isAttacking())
heal(stats.combatRegen);
}
if(faction.getsAttacked && !isAttacking()){
List<EntityMob> list = this.worldObj.getEntitiesWithinAABB(EntityMob.class, this.boundingBox.expand(16, 16, 16));
for(EntityMob mob : list){
if(mob.getAttackTarget() == null && this.canSee(mob)){
if(mob instanceof EntityZombie && !mob.getEntityData().hasKey("AttackNpcs")){
mob.tasks.addTask(2, new EntityAIAttackOnCollide(mob, EntityLivingBase.class, 1.0D, false));
mob.getEntityData().setBoolean("AttackNpcs", true);
}
mob.setAttackTarget(this);
}
}
}
if(linkedData != null && linkedData.time > linkedLast){
LinkedNpcController.Instance.loadNpcData(this);
}
2018-09-13 12:03:28 -04:00
if(updateClient){
2022-11-15 00:48:31 -05:00
this.updateClient();
}
if(updateAI){
updateTasks();
updateAI = false;
}
}
2018-09-13 12:03:28 -04:00
if(getHealth() <= 0){
clearActivePotions();
setBoolFlag(true, 8);
updateTasks();
updateHitbox();
2018-09-13 12:03:28 -04:00
}
setBoolFlag(!getNavigator().noPath(), 1);
setBoolFlag(isInteracting(), 2);
combatHandler.update();
2018-09-13 12:03:28 -04:00
onCollide();
}
2022-11-15 00:48:31 -05:00
2018-09-13 12:03:28 -04:00
if(wasKilled != isKilled() && wasKilled){
reset();
}
2022-11-15 00:48:31 -05:00
2018-09-13 12:03:28 -04:00
wasKilled = isKilled();
2022-11-15 00:48:31 -05:00
2018-09-13 12:03:28 -04:00
if (this.worldObj.isDaytime() && !this.worldObj.isRemote && this.stats.burnInSun){
2022-11-15 00:48:31 -05:00
float f = this.getBrightness(1.0F);
if (f > 0.5F && this.rand.nextFloat() * 30.0F < (f - 0.4F) * 2.0F && this.worldObj.canBlockSeeTheSky(MathHelper.floor_double(this.posX), MathHelper.floor_double(this.posY), MathHelper.floor_double(this.posZ))){
this.setFire(8);
}
}
super.onLivingUpdate();
if (worldObj.isRemote){
if(roleInterface != null){
roleInterface.clientUpdate();
}
if(!display.cloakTexture.isEmpty())
cloakUpdate();
2018-09-13 12:03:28 -04:00
if(currentAnimation.ordinal() != dataWatcher.getWatchableObjectInt(14)){
currentAnimation = EnumAnimation.values()[dataWatcher.getWatchableObjectInt(14)];
updateHitbox();
}
if(advanced.job == EnumJobType.Bard)
((JobBard)jobInterface).onLivingUpdate();
2022-11-15 00:48:31 -05:00
}
}
2022-01-03 21:30:38 -06:00
@Override
protected void damageEntity(DamageSource damageSrc, float damageAmount){
super.damageEntity(damageSrc, damageAmount);
combatHandler.damage(damageSrc, damageAmount);
}
2022-01-03 21:30:38 -06:00
public void updateClient() {
NBTTagCompound compound = writeSpawnData();
compound.setInteger("EntityId", getEntityId());
Server.sendAssociatedData(this, EnumPacketClient.UPDATE_NPC, compound);
updateClient = false;
}
2018-09-13 12:03:28 -04:00
@Override
public boolean interact(EntityPlayer player) {
if(worldObj.isRemote)
return false;
ItemStack currentItem = player.inventory.getCurrentItem();
if (currentItem != null) {
Item item = currentItem.getItem();
if (item == CustomItems.cloner || item == CustomItems.wand || item == CustomItems.mount || item == CustomItems.scripter) {
setAttackTarget(null);
setRevengeTarget(null);
return true;
}
if (item == CustomItems.moving) {
setAttackTarget(null);
if(currentItem.stackTagCompound == null)
currentItem.stackTagCompound = new NBTTagCompound();
2022-11-15 00:48:31 -05:00
2018-09-13 12:03:28 -04:00
currentItem.stackTagCompound.setInteger("NPCID",this.getEntityId());
player.addChatMessage(new ChatComponentTranslation("Registered " + this.getCommandSenderName() + " to your NPC Pather"));
return true;
}
}
2022-03-23 03:54:06 -05:00
if(EventHooks.onNPCInteract(this, player) || isAttacking() || isKilled() || faction.isAggressiveToPlayer(player))
2018-09-13 12:03:28 -04:00
return false;
addInteract(player);
Dialog dialog = getDialog(player);
2023-06-05 19:35:27 -04:00
PlayerQuestData playerdata = PlayerDataController.Instance.getPlayerData(player).questData;
2018-09-13 12:03:28 -04:00
QuestData data = playerdata.getQuestCompletion(player, this);
if (data != null){
2022-06-13 04:08:36 -05:00
NoppesUtilPlayer.questCompletion((EntityPlayerMP) player, data.quest.id);
2018-09-13 12:03:28 -04:00
Server.sendData((EntityPlayerMP)player, EnumPacketClient.QUEST_COMPLETION, data.quest.writeToNBT(new NBTTagCompound()));
}
else if (dialog != null){
NoppesUtilServer.openDialog(player, this, dialog, 0);
2018-09-13 12:03:28 -04:00
}
else if(roleInterface != null)
roleInterface.interact(player);
else
say(player, advanced.getInteractLine());
2022-11-15 00:48:31 -05:00
2018-09-13 12:03:28 -04:00
return true;
}
2022-08-26 15:50:58 -04:00
@Override
public PathNavigate getNavigator() {
if(canFly())
return this.flyNavigator;
else {
return super.getNavigator();
}
}
2022-08-26 15:50:58 -04:00
@Override
public EntityMoveHelper getMoveHelper() {
if(canFly())
return this.flyMoveHelper;
else {
return super.getMoveHelper();
}
}
2022-11-12 15:53:20 -06:00
public boolean canBreathe() {
return this.isInWater() && this.stats.drowningType == 2 || !this.isInWater() && this.stats.drowningType == 1 || this.stats.drowningType == 0;
}
2022-08-26 15:50:58 -04:00
@Override
protected void updateAITasks()
{
2022-11-13 23:49:49 -06:00
this.getNavigator().onUpdateNavigation();
this.getMoveHelper().onUpdateMoveHelper();
try {
super.updateAITasks();
} catch (ConcurrentModificationException ignored){}
if (!this.canBreathe()) {
2022-06-29 12:21:30 -05:00
this.setAir(this.decreaseAirSupply(this.getAir()));
2022-05-04 03:06:40 -05:00
2022-06-29 12:21:30 -05:00
if (this.getAir() <= -20) {
this.setAir(0);
this.attackEntityFrom(DamageSource.drown, 2.0F);
}
}
}
2022-11-15 00:48:31 -05:00
2018-09-13 12:03:28 -04:00
public void addInteract(EntityLivingBase entity){
if( !ai.stopAndInteract || isAttacking() || !entity.isEntityAlive())
return;
if((ticksExisted - lastInteract) < 180)
interactingEntities.clear();
getNavigator().clearPathEntity();
lastInteract = ticksExisted;
if(!interactingEntities.contains(entity))
interactingEntities.add(entity);
}
2022-11-15 00:48:31 -05:00
2018-09-13 12:03:28 -04:00
public boolean isInteracting(){
if((ticksExisted - lastInteract) < 40 || isRemote() && getBoolFlag(2))
return true;
return ai.stopAndInteract && !interactingEntities.isEmpty() && (ticksExisted - lastInteract) < 180;
}
private Dialog getDialog(EntityPlayer player) {
for (DialogOption option : dialogs.values()) {
if (option == null)
continue;
if (!option.hasDialog())
continue;
Dialog dialog = option.getDialog();
if (dialog.availability.isAvailable(player)){
return dialog;
}
}
return null;
}
@Override
public boolean attackEntityFrom(DamageSource damagesource, float i) {
2022-11-15 00:48:31 -05:00
if (this.worldObj.isRemote || CustomNpcs.FreezeNPCs || (damagesource.damageType != null && damagesource.damageType.equals("inWall"))){
return false;
}
if(damagesource.damageType != null && damagesource.damageType.equals("outOfWorld") && isKilled()){
reset();
}
i = stats.resistances.applyResistance(damagesource, i);
if((float)this.hurtResistantTime > (float)this.maxHurtResistantTime / 2.0F && i <= this.lastDamage)
return false;
Entity entity = NoppesUtilServer.GetDamageSource(damagesource);
2018-09-13 12:03:28 -04:00
EntityLivingBase attackingEntity = null;
2022-11-15 00:48:31 -05:00
if (entity instanceof EntityLivingBase)
2018-09-13 12:03:28 -04:00
attackingEntity = (EntityLivingBase) entity;
if(attackingEntity != null && attackingEntity == getOwner())
return false;
else if (attackingEntity instanceof EntityNPCInterface){
EntityNPCInterface npc = (EntityNPCInterface) attackingEntity;
if(npc.faction.id == faction.id)
return false;
if(npc.getOwner() instanceof EntityPlayer)
this.recentlyHit = 100;
}
else if (attackingEntity instanceof EntityPlayer && faction.isFriendlyToPlayer((EntityPlayer) attackingEntity))
return false;
NpcEvent.DamagedEvent event = new NpcEvent.DamagedEvent(this.wrappedNPC, attackingEntity, i, damagesource);
if(EventHooks.onNPCDamaged(this, event) || isKilled())
2018-09-13 12:03:28 -04:00
return false;
i = event.getDamage();
2022-11-15 00:48:31 -05:00
2018-09-13 12:03:28 -04:00
if(isKilled())
return false;
2022-11-15 00:48:31 -05:00
2018-09-13 12:03:28 -04:00
if(attackingEntity == null)
return super.attackEntityFrom(damagesource, i);
2022-11-15 00:48:31 -05:00
2018-09-13 12:03:28 -04:00
try{
if (isAttacking()){
if (getAttackTarget() != null) {
if (ai.combatPolicy != EnumCombatPolicy.Brute) {
boolean closerTargetFound = this.getDistanceSqToEntity(getAttackTarget()) > this.getDistanceSqToEntity(attackingEntity);
switch (ai.combatPolicy) {
case Flip:
if (closerTargetFound) {
setAttackTarget(attackingEntity);
}
break;
case Stubborn:
if (closerTargetFound && combatHandler.shouldChangeTarget((double) ai.tacticalChance / 100)) {
2024-01-31 01:48:49 -05:00
setAttackTarget(attackingEntity);
}
break;
case Tactical:
if (attackingEntity != getAttackTarget() && combatHandler.shouldSwitchTactically(getAttackTarget(), attackingEntity)) {
setAttackTarget(attackingEntity);
}
break;
default:
break;
}
}
2018-09-13 12:03:28 -04:00
}
return super.attackEntityFrom(damagesource, i);
}
if (i > 0){
2018-09-13 12:03:28 -04:00
List<EntityNPCInterface> inRange = worldObj.getEntitiesWithinAABB(EntityNPCInterface.class, this.boundingBox.expand(32D, 16D, 32D));
for (EntityNPCInterface npc : inRange) {
if (npc.isKilled() || !npc.advanced.defendFaction || npc.faction.id != faction.id)
continue;
2022-11-15 00:48:31 -05:00
2018-09-13 12:03:28 -04:00
if (npc.canSee(this) || npc.ai.directLOS || npc.canSee(attackingEntity))
npc.onAttack(attackingEntity);
}
setAttackTarget(attackingEntity);
}
return super.attackEntityFrom(damagesource, i);
}
finally{
if(event.getClearTarget()){
2018-09-13 12:03:28 -04:00
setAttackTarget(null);
setRevengeTarget(null);
}
}
}
public void onAttack(EntityLivingBase entity) {
if (entity == null || entity == this || isAttacking() || ai.onAttack == 3 || entity == getOwner())
return;
super.setAttackTarget(entity);
}
2022-11-15 00:48:31 -05:00
2018-09-13 12:03:28 -04:00
@Override
2022-11-15 00:48:31 -05:00
public void setAttackTarget(EntityLivingBase entity){
if(entity instanceof EntityPlayer && ((EntityPlayer)entity).capabilities.disableDamage || entity != null && entity == getOwner())
return;
if (!isRemote()) {
if (getAttackTarget() != entity && entity != null) {
NpcEvent.TargetEvent event = new NpcEvent.TargetEvent(wrappedNPC,entity);
if (EventHooks.onNPCTarget(this, event))
return;
if (event.getTarget() == null)
entity = null;
else
entity = event.getTarget().getMCEntity();
} else {
if(EventHooks.onNPCTargetLost(this, getAttackTarget(), entity))
return;
}
if (entity != null && entity != this && ai.onAttack != 3 && !isAttacking()) {
Line line = advanced.getAttackLine();
if (line != null)
saySurrounding(line.formatTarget(entity));
}
2018-09-13 12:03:28 -04:00
}
2022-11-15 00:48:31 -05:00
2018-09-13 12:03:28 -04:00
super.setAttackTarget(entity);
2022-11-15 00:48:31 -05:00
}
2018-09-13 12:03:28 -04:00
@Override
public void attackEntityWithRangedAttack(EntityLivingBase entity, float f) {
2022-11-15 00:48:31 -05:00
ItemStack proj = inventory.getProjectile();
if(proj == null){
updateTasks();
return;
}
if (!isRemote()) {
NpcEvent.RangedLaunchedEvent event = new NpcEvent.RangedLaunchedEvent(wrappedNPC,stats.pDamage,entity);
if (EventHooks.onNPCRangedAttack(this, event))
return;
for (int i = 0; i < this.stats.shotCount; i++) {
EntityProjectile projectile = shoot(entity, stats.accuracy, proj, f == 1);
projectile.damage = event.getDamage();
}
this.playSound(this.stats.fireSound, 2.0F, 1.0f);
2018-09-13 12:03:28 -04:00
}
2022-11-15 00:48:31 -05:00
}
2018-09-13 12:03:28 -04:00
public EntityProjectile shoot(EntityLivingBase entity, int accuracy, ItemStack proj, boolean indirect){
return shoot(entity.posX, entity.boundingBox.minY + (double)(entity.height / 2.0F), entity.posZ, accuracy, proj, indirect);
}
2022-11-15 00:48:31 -05:00
2018-09-13 12:03:28 -04:00
public EntityProjectile shoot(double x, double y, double z, int accuracy, ItemStack proj, boolean indirect){
2022-11-15 00:48:31 -05:00
EntityProjectile projectile = new EntityProjectile(this.worldObj, this, proj.copy(), true);
//TODO calculate height of the thrower
double varX = x - this.posX;
2018-09-13 12:03:28 -04:00
double varY = y - (this.posY + this.getEyeHeight());
double varZ = z - this.posZ;
float varF = projectile.hasGravity() ? MathHelper.sqrt_double(varX * varX + varZ * varZ) : 0.0F;
float angle = projectile.getAngleForXYZ(varX, varY, varZ, varF, indirect);
float acc = 20.0F - MathHelper.floor_float(accuracy / 5.0F);
2022-11-15 00:48:31 -05:00
projectile.setThrowableHeading(varX, varY, varZ, angle, acc);
worldObj.spawnEntityInWorld(projectile);
return projectile;
2018-09-13 12:03:28 -04:00
}
2022-11-15 00:48:31 -05:00
2018-09-13 12:03:28 -04:00
private void clearTasks(EntityAITasks tasks){
2022-11-15 00:48:31 -05:00
Iterator iterator = tasks.taskEntries.iterator();
List<EntityAITaskEntry> list = new ArrayList(tasks.taskEntries);
for (EntityAITaskEntry entityaitaskentry : list)
{
tasks.removeTask(entityaitaskentry.action);
}
tasks.taskEntries = new ArrayList<EntityAITaskEntry>();
2018-09-13 12:03:28 -04:00
}
2022-07-27 18:47:20 -05:00
public void updateTasks() {
2018-09-13 12:03:28 -04:00
if (worldObj == null || worldObj.isRemote)
return;
aiLeap = aiAttackTarget = aiResponse = aiSprint = aiRange = null;
2021-06-13 16:22:06 -04:00
2018-09-13 12:03:28 -04:00
clearTasks(tasks);
clearTasks(targetTasks);
if(isKilled())
return;
2018-09-13 12:03:28 -04:00
IEntitySelector attackEntitySelector = new NPCAttackSelector(this);
this.targetTasks.addTask(0, new EntityAIClearTarget(this));
this.targetTasks.addTask(1, new EntityAIHurtByTarget(this, false));
this.targetTasks.addTask(2, new EntityAIClosestTarget(this, EntityLivingBase.class, 4, this.ai.directLOS, false, attackEntitySelector));
2022-11-15 00:48:31 -05:00
this.targetTasks.addTask(3, new EntityAIOwnerHurtByTarget(this));
this.targetTasks.addTask(4, new EntityAIOwnerHurtTarget(this));
2021-06-13 16:22:06 -04:00
if (canFly()) {
this.getNavigator().setCanSwim(true);
} else {
this.tasks.addTask(0, new EntityAIWaterNav(this));
}
2018-09-13 12:03:28 -04:00
this.taskCount = 1;
this.doorInteractType();
this.seekShelter();
this.setResponse();
this.setMoveType();
this.addRegularEntries();
}
2022-11-15 00:48:31 -05:00
2018-09-13 12:03:28 -04:00
private void removeTask(EntityAIBase task){
if(task != null)
tasks.removeTask(task);
}
2022-11-15 00:48:31 -05:00
2018-09-13 12:03:28 -04:00
/*
* Branch task function for setting how an NPC responds to a threat
*/
2022-11-15 00:48:31 -05:00
public void setResponse(){
2018-09-13 12:03:28 -04:00
removeTask(aiLeap);
removeTask(aiResponse);
removeTask(aiSprint);
removeTask(aiAttackTarget);
removeTask(aiRange);
aiLeap = aiAttackTarget = aiResponse = aiSprint = aiRange = null;
2022-11-15 00:48:31 -05:00
if (this.ai.canSprint)
this.tasks.addTask(this.taskCount++, new EntityAISprintToTarget(this));
2022-11-15 00:48:31 -05:00
if (this.ai.onAttack == 1)
this.tasks.addTask(this.taskCount++, aiResponse = new EntityAIPanic(this, 1.2F));
else if (this.ai.onAttack == 2) {
this.tasks.addTask(this.taskCount++, aiResponse = new EntityAIAvoidTarget(this));
}
else if (this.ai.onAttack == 0) {
2024-01-23 23:32:02 -05:00
this.setLeapTask();
2022-11-15 00:48:31 -05:00
if (this.inventory.getProjectile() == null || this.ai.useRangeMelee == 2)
{
switch(this.ai.tacticalVariant)
{
case Dodge : this.tasks.addTask(this.taskCount++, aiResponse = new EntityAIZigZagTarget(this, 1.0D, this.ai.tacticalRadius)); break;
case Surround : this.tasks.addTask(this.taskCount++, aiResponse = new EntityAIOrbitTarget(this, 1.0D, this.ai.tacticalRadius, true)); break;
case HitNRun : this.tasks.addTask(this.taskCount++, aiResponse = new EntityAIAvoidTarget(this)); break;
case Ambush : this.tasks.addTask(this.taskCount++, aiResponse = new EntityAIAmbushTarget(this, 1.2D, this.ai.tacticalRadius, false)); break;
case Stalk : this.tasks.addTask(this.taskCount++, aiResponse = new EntityAIStalkTarget(this, this.ai.tacticalRadius)); break;
2024-02-29 22:20:59 -05:00
case Twist: this.tasks.addTask(this.taskCount++, aiResponse = new EntityAITwistTarget(this, 1.3D, this.ai.tacticalRadius)); break;
2022-11-15 00:48:31 -05:00
default :
}
}
else
{
switch(this.ai.tacticalVariant)
{
case Dodge : this.tasks.addTask(this.taskCount++, aiResponse = new EntityAIDodgeShoot(this)); break;
case Surround : this.tasks.addTask(this.taskCount++, aiResponse = new EntityAIOrbitTarget(this, 1.0D, stats.rangedRange, false)); break;
case HitNRun : this.tasks.addTask(this.taskCount++, aiResponse = new EntityAIAvoidTarget(this)); break;
case Ambush : this.tasks.addTask(this.taskCount++, aiResponse = new EntityAIAmbushTarget(this, 1.2D, this.ai.tacticalRadius, false)); break;
case Stalk : this.tasks.addTask(this.taskCount++, aiResponse = new EntityAIStalkTarget(this, this.ai.tacticalRadius)); break;
default :
}
}
this.tasks.addTask(this.taskCount, aiAttackTarget = new EntityAIAttackTarget(this));
((EntityAIAttackTarget)aiAttackTarget).navOverride(ai.tacticalVariant == EnumNavType.None);
if(this.inventory.getProjectile() != null){
this.tasks.addTask(this.taskCount++, aiRange = new EntityAIRangedAttack(this));
aiRange.navOverride(ai.tacticalVariant == EnumNavType.None);
}
}
else if (this.ai.onAttack == 3) {
//do nothing
}
}
2018-09-13 12:03:28 -04:00
/*
* Branch task function for setting if an NPC wanders or not
*/
2022-11-15 00:48:31 -05:00
public void setMoveType(){
2018-09-13 12:03:28 -04:00
if (ai.movingType == EnumMovingType.Wandering){
this.tasks.addTask(this.taskCount++, new EntityAIWander(this));
}
if (ai.movingType == EnumMovingType.MovingPath){
this.tasks.addTask(this.taskCount++, new EntityAIMovingPath(this));
}
}
/*
* Branch task function for adjusting NPC door interactivity
*/
2021-06-13 16:22:06 -04:00
public void doorInteractType(){
if(canFly()) //currently flying does not support opening doors
return;
2018-09-13 12:03:28 -04:00
EntityAIBase aiDoor = null;
if (this.ai.doorInteract == 1)
{
this.tasks.addTask(this.taskCount++, aiDoor = new EntityAIOpenDoor(this, true));
}
else if (this.ai.doorInteract == 0)
{
this.tasks.addTask(this.taskCount++, aiDoor = new EntityAIBustDoor(this));
}
this.getNavigator().setBreakDoors(aiDoor != null);
}
2022-11-15 00:48:31 -05:00
2018-09-13 12:03:28 -04:00
/*
* Branch task function for finding shelter under the appropriate conditions
*/
public void seekShelter() {
if (this.ai.findShelter == 0)
{
this.tasks.addTask(this.taskCount++, new EntityAIMoveIndoors(this));
}
else if (this.ai.findShelter == 1)
{
2021-06-13 16:22:06 -04:00
if(!canFly()) // doesnt work when flying
this.tasks.addTask(this.taskCount++, new EntityAIRestrictSun(this));
2018-09-13 12:03:28 -04:00
this.tasks.addTask(this.taskCount++, new EntityAIFindShade(this));
}
}
2022-11-15 00:48:31 -05:00
2018-09-13 12:03:28 -04:00
/*
* Branch task function for leaping
*/
2024-01-23 23:32:02 -05:00
public void setLeapTask() {
if (this.ai.leapType == 1)
2018-09-13 12:03:28 -04:00
this.tasks.addTask(this.taskCount++, aiLeap = new EntityAILeapAtTarget(this, 0.4F));
2024-01-23 23:32:02 -05:00
if (this.ai.leapType == 2)
this.tasks.addTask(this.taskCount++, aiLeap = new EntityAIPounceTarget(this));
2018-09-13 12:03:28 -04:00
}
2022-11-15 00:48:31 -05:00
2018-09-13 12:03:28 -04:00
/*
* Add immutable task entries.
*/
public void addRegularEntries() {
this.tasks.addTask(this.taskCount++, new EntityAIFollow(this));
2022-07-20 13:33:21 -05:00
this.tasks.addTask(this.taskCount++, new EntityAIReturn(this));
2018-09-13 12:03:28 -04:00
if (this.ai.standingType != EnumStandingType.NoRotation && this.ai.standingType != EnumStandingType.HeadRotation)
this.tasks.addTask(this.taskCount++, new EntityAIWatchClosest(this, EntityLivingBase.class, 5.0F));
this.tasks.addTask(this.taskCount++, new EntityAILook(this));
this.tasks.addTask(this.taskCount++, new EntityAIWorldLines(this));
this.tasks.addTask(this.taskCount++, new EntityAIJob(this));
this.tasks.addTask(this.taskCount++, new EntityAIRole(this));
this.tasks.addTask(this.taskCount++, new EntityAIAnimation(this));
if(transform.isValid())
this.tasks.addTask(this.taskCount++, new EntityAITransform(this));
}
2022-11-15 00:48:31 -05:00
2018-09-13 12:03:28 -04:00
/*
* Function for getting proper move speeds. This way we don't have to modify them every time we use them.
*/
public float getSpeed() {
return (float)ai.getWalkingSpeed() / 20.0F;
}
2022-11-15 00:48:31 -05:00
@Override
2018-09-13 12:03:28 -04:00
public float getBlockPathWeight(int par1, int par2, int par3){
float weight = this.worldObj.getLightBrightness(par1, par2, par3) - 0.5F;
2022-11-15 00:48:31 -05:00
Block block = worldObj.getBlock(par1, par2, par3);
if(block.isOpaqueCube())
weight += 10;
return weight;
}
2018-09-13 12:03:28 -04:00
/*
* Used for getting the applied potion effect from dataStats.
*/
private int getPotionEffect(EnumPotionType p) {
switch(p)
{
2022-11-15 00:48:31 -05:00
case Poison : return Potion.poison.id;
case Hunger : return Potion.hunger.id;
case Weakness : return Potion.weakness.id;
case Slowness : return Potion.moveSlowdown.id;
case Nausea : return Potion.confusion.id;
case Blindness : return Potion.blindness.id;
case Wither : return Potion.wither.id;
default : return 0;
2018-09-13 12:03:28 -04:00
}
}
2022-06-29 12:21:30 -05:00
@Override
public void setAir(int air) {
2022-06-29 14:36:17 -05:00
if (this.isInWater() || air < this.getAir() || this.stats.drowningType != 2) {
2022-06-29 12:21:30 -05:00
super.setAir(air);
}
}
2022-11-15 00:48:31 -05:00
@Override
2018-09-13 12:03:28 -04:00
protected int decreaseAirSupply(int par1)
2022-11-15 00:48:31 -05:00
{
2022-06-29 12:21:30 -05:00
if (this.stats.drowningType == 0)
2018-09-13 12:03:28 -04:00
return par1;
2022-11-15 00:48:31 -05:00
return super.decreaseAirSupply(par1);
}
2018-09-13 12:03:28 -04:00
2022-11-15 00:48:31 -05:00
@Override
2018-09-13 12:03:28 -04:00
public EnumCreatureAttribute getCreatureAttribute()
2022-11-15 00:48:31 -05:00
{
return this.stats.creatureType;
}
/**
* Returns the sound this mob makes while it's alive.
*/
2018-09-13 12:03:28 -04:00
@Override
protected String getLivingSound() {
if (!this.isEntityAlive())
return null;
if (this.getAttackTarget() != null)
return advanced.angrySound.isEmpty() ? null : advanced.angrySound;
return advanced.idleSound.isEmpty() ? null : advanced.idleSound;
}
@Override
2022-11-15 00:48:31 -05:00
public int getTalkInterval(){
return 160;
}
/**
* Returns the sound this mob makes when it is hurt.
*/
@Override
protected String getHurtSound(){
if(this.advanced.hurtSound.isEmpty())
return null;
return this.advanced.hurtSound;
}
/**
* Returns the sound this mob makes on death.
*/
@Override
protected String getDeathSound(){
if(this.advanced.deathSound.isEmpty())
return null;
return this.advanced.deathSound;
}
@Override
protected float getSoundPitch(){
2018-09-13 12:03:28 -04:00
if(this.advanced.disablePitch)
return 1;
2022-11-15 00:48:31 -05:00
return super.getSoundPitch();
}
/**
* Plays step sound at given x, y, z for the entity
*/
@Override
protected void func_145780_a(int p_145780_1_, int p_145780_2_, int p_145780_3_, Block p_145780_4_)
{
if (!this.advanced.stepSound.equals(""))
{
this.playSound(this.advanced.stepSound, 0.15F, 1.0F);
}
else
{
super.func_145780_a(p_145780_1_, p_145780_2_, p_145780_3_, p_145780_4_);
}
}
public EntityPlayerMP getFakePlayer(){
if(worldObj.isRemote)
return null;
2018-09-13 12:03:28 -04:00
if(chateventPlayer == null)
chateventPlayer = new FakePlayer((WorldServer)worldObj, chateventProfile);
EntityUtil.Copy(this, chateventPlayer);
chateventProfile.npc = this;
chateventPlayer.refreshDisplayName();
2023-03-15 23:10:03 -05:00
IItemStack stack = NpcAPI.Instance().createItem("minecraft:stone",0,1);
chateventPlayer.setCurrentItemOrArmor(0, stack.getMCItemStack());
2018-09-13 12:03:28 -04:00
return chateventPlayer;
2022-11-15 00:48:31 -05:00
}
2018-09-13 12:03:28 -04:00
2023-12-03 20:48:37 -06:00
public void saySurrounding(ILine line) {
if (line == null || line.getText() == null || getFakePlayer() == null)
2018-09-13 12:03:28 -04:00
return;
2023-12-03 20:48:37 -06:00
ServerChatEvent event = new ServerChatEvent(getFakePlayer(), line.getText(), new ChatComponentTranslation(line.getText().replace("%", "%%")));
2022-11-15 00:48:31 -05:00
if (MinecraftForge.EVENT_BUS.post(event) || event.component == null){
return;
}
2023-12-03 20:48:37 -06:00
line.setText(event.component.getUnformattedText().replace("%%", "%"));
2018-09-13 12:03:28 -04:00
List<EntityPlayer> inRange = worldObj.getEntitiesWithinAABB(
EntityPlayer.class, this.boundingBox.expand(20D, 20D, 20D));
for (EntityPlayer player : inRange)
say(player, line);
}
2023-12-03 20:48:37 -06:00
public void say(EntityPlayer player, ILine line) {
if (line == null || !this.canSee(player) || line.getText() == null)
2022-11-15 00:48:31 -05:00
return;
2023-12-03 20:48:37 -06:00
if(!line.getSound().isEmpty()){
Server.sendData((EntityPlayerMP)player, EnumPacketClient.PLAY_SOUND, line.getSound(), (float)posX, (float)posY, (float)posZ);
2018-09-13 12:03:28 -04:00
}
2023-12-03 20:48:37 -06:00
Server.sendData((EntityPlayerMP)player, EnumPacketClient.CHATBUBBLE, this.getEntityId(), line.getText(), !line.hideText());
2018-09-13 12:03:28 -04:00
}
2022-11-15 00:48:31 -05:00
public boolean getAlwaysRenderNameTagForRender(){
return true;
}
2018-09-13 12:03:28 -04:00
@Override
public void readEntityFromNBT(NBTTagCompound compound) {
super.readEntityFromNBT(compound);
npcVersion = compound.getInteger("ModRev");
VersionCompatibility.CheckNpcCompatibility(this, compound);
2022-06-14 22:26:11 -04:00
2018-09-13 12:03:28 -04:00
display.readToNBT(compound);
stats.readToNBT(compound);
ai.readToNBT(compound);
script.readFromNBT(compound);
2023-03-16 04:27:19 -05:00
script.readEventsFromNBT(compound);
timers.readFromNBT(compound);
2022-06-12 01:26:23 -05:00
if (compound.hasKey("ItemGiverId")) {
itemGiverId = compound.getInteger("ItemGiverId");
} else {
itemGiverId = -1;
}
2018-09-13 12:03:28 -04:00
advanced.readToNBT(compound);
2022-11-15 00:48:31 -05:00
if (advanced.role != EnumRoleType.None && roleInterface != null)
roleInterface.readFromNBT(compound);
if (advanced.job != EnumJobType.None && jobInterface != null)
jobInterface.readFromNBT(compound);
2018-09-13 12:03:28 -04:00
inventory.readEntityFromNBT(compound);
transform.readToNBT(compound);
2022-11-15 00:48:31 -05:00
killedtime = compound.getLong("KilledTime");
2018-09-13 12:03:28 -04:00
totalTicksAlive = compound.getLong("TotalTicksAlive");
2022-11-15 00:48:31 -05:00
2018-09-13 12:03:28 -04:00
linkedName = compound.getString("LinkedNpcName");
2022-11-15 00:48:31 -05:00
2018-09-13 12:03:28 -04:00
if(!isRemote())
LinkedNpcController.Instance.loadNpcData(this);
2022-11-15 00:48:31 -05:00
2023-01-07 00:21:08 -05:00
this.getEntityAttribute(SharedMonsterAttributes.followRange).setBaseValue(ConfigMain.NpcNavRange);
2018-09-13 12:03:28 -04:00
this.updateTasks();
2023-09-15 14:33:24 -04:00
this.func_110163_bv();
2018-09-13 12:03:28 -04:00
}
@Override
public void writeEntityToNBT(NBTTagCompound compound) {
super.writeEntityToNBT(compound);
display.writeToNBT(compound);
stats.writeToNBT(compound);
ai.writeToNBT(compound);
script.writeToNBT(compound);
2023-03-16 04:27:19 -05:00
script.writeEventsToNBT(compound);
timers.writeToNBT(compound);
2018-09-13 12:03:28 -04:00
advanced.writeToNBT(compound);
2022-11-15 00:48:31 -05:00
if (advanced.role != EnumRoleType.None && roleInterface != null)
roleInterface.writeToNBT(compound);
if (advanced.job != EnumJobType.None && jobInterface != null)
jobInterface.writeToNBT(compound);
2018-09-13 12:03:28 -04:00
inventory.writeEntityToNBT(compound);
transform.writeToNBT(compound);
compound.setLong("KilledTime", killedtime);
2022-11-15 00:48:31 -05:00
compound.setLong("TotalTicksAlive", totalTicksAlive);
2018-09-13 12:03:28 -04:00
compound.setInteger("ModRev", npcVersion);
compound.setString("LinkedNpcName", linkedName);
}
public void updateHitbox() {
2022-11-15 00:48:31 -05:00
2018-09-13 12:03:28 -04:00
if(currentAnimation == EnumAnimation.LYING || currentAnimation == EnumAnimation.CRAWLING){
width = 0.8f;
height = 0.4f;
}
else if (isRiding()){
width = 0.6f;
height = baseHeight * 0.77f;
}
else{
width = 0.6f;
height = baseHeight;
}
width = (width / 5f) * display.modelSize;
height = (height / 5f) * display.modelSize;
2022-11-15 00:48:31 -05:00
if(isKilled() && stats.hideKilledBody) {
width = 0.00001f;
}
if(width / 2 > worldObj.MAX_ENTITY_RADIUS) {
worldObj.MAX_ENTITY_RADIUS = width / 2;
}
2024-02-29 22:20:59 -05:00
if(display.hitboxData.isHitboxEnabled()){
width = display.hitboxData.getWidth();
height = display.hitboxData.getHeight();
}
2018-09-13 12:03:28 -04:00
this.setPosition(posX, posY, posZ);
}
@Override
public void onDeathUpdate(){
if(stats.spawnCycle == 3){
super.onDeathUpdate();
return;
}
2022-11-15 00:48:31 -05:00
2018-09-13 12:03:28 -04:00
++this.deathTime;
if(worldObj.isRemote)
return;
if(!hasDied){
setDead();
}
if (killedtime < System.currentTimeMillis()) {
if (stats.spawnCycle == 0 || (this.worldObj.isDaytime() && stats.spawnCycle == 1) || (!this.worldObj.isDaytime() && stats.spawnCycle == 2)) {
reset();
}
}
}
2022-11-15 00:48:31 -05:00
2018-09-13 12:03:28 -04:00
public void reset() {
hasDied = false;
isDead = false;
wasKilled = false;
setSprinting(false);
setHealth(getMaxHealth());
dataWatcher.updateObject(14, 0); // animation Normal
2022-11-15 00:48:31 -05:00
dataWatcher.updateObject(15, 0);
combatHandler.reset();
2018-09-13 12:03:28 -04:00
this.setAttackTarget(null);
this.setRevengeTarget(null);
this.deathTime = 0;
//fleeingTick = 0;
2022-11-12 15:53:20 -06:00
if(ai.returnToStart && !hasOwner() && !this.isRemote())
2018-09-13 12:03:28 -04:00
setLocationAndAngles(getStartXPos(), getStartYPos(), getStartZPos(), rotationYaw, rotationPitch);
killedtime = 0;
extinguish();
this.clearActivePotions();
getNavigator().clearPathEntity();
2022-11-07 21:23:46 -05:00
if(this.canFly()){
((PathNavigateFlying)getNavigator()).targetPos = null;
((PathNavigateFlying)getNavigator()).clearPathEntity();
2022-11-07 01:40:11 -05:00
((FlyingMoveHelper)getMoveHelper()).update = false;
}
2022-11-07 21:23:46 -05:00
moveEntityWithHeading(0,0);
distanceWalkedModified = 0;
2018-09-13 12:03:28 -04:00
currentAnimation = EnumAnimation.NONE;
updateHitbox();
updateAI = true;
ai.movingPos = 0;
if(getOwner() != null){
getOwner().setLastAttacker(null);
}
2022-11-15 00:48:31 -05:00
2018-09-13 12:03:28 -04:00
if(jobInterface != null)
jobInterface.reset();
2022-03-23 03:54:06 -05:00
if (!isRemote()) {
EventHooks.onNPCInit(this);
}
2018-09-13 12:03:28 -04:00
}
2022-11-15 00:48:31 -05:00
public void onCollide() {
if(!isEntityAlive() || ticksExisted % 4 != 0)
return;
AxisAlignedBB axisalignedbb = null;
2018-09-13 12:03:28 -04:00
2022-11-15 00:48:31 -05:00
if (this.ridingEntity != null && this.ridingEntity.isEntityAlive()){
axisalignedbb = this.boundingBox.func_111270_a(this.ridingEntity.boundingBox).expand(1.0D, 0.0D, 1.0D);
}
else{
axisalignedbb = this.boundingBox.expand(1.0D, 0.5D, 1.0D);
}
2018-09-13 12:03:28 -04:00
2022-11-15 00:48:31 -05:00
List list = this.worldObj.getEntitiesWithinAABBExcludingEntity(this, axisalignedbb);
if(list == null)
return;
2018-09-13 12:03:28 -04:00
if (!isRemote()) {
for (int i = 0; i < list.size(); ++i) {
Entity entity = (Entity) list.get(i);
if (entity.isEntityAlive()) {
EventHooks.onNPCCollide(this, entity);
}
2022-03-23 03:54:06 -05:00
}
}
2018-09-13 12:03:28 -04:00
2022-11-15 00:48:31 -05:00
}
2018-09-13 12:03:28 -04:00
@Override
public void setInPortal(){
//prevent npcs from walking into portals
}
2022-11-15 00:48:31 -05:00
2018-09-13 12:03:28 -04:00
public double field_20066_r;
public double field_20065_s;
public double field_20064_t;
public double field_20063_u;
public double field_20062_v;
public double field_20061_w;
public void cloakUpdate() {
field_20066_r = field_20063_u;
field_20065_s = field_20062_v;
field_20064_t = field_20061_w;
double d = posX - field_20063_u;
double d1 = posY - field_20062_v;
double d2 = posZ - field_20061_w;
double d3 = 10D;
if (d > d3) {
field_20066_r = field_20063_u = posX;
}
if (d2 > d3) {
field_20064_t = field_20061_w = posZ;
}
if (d1 > d3) {
field_20065_s = field_20062_v = posY;
}
if (d < -d3) {
field_20066_r = field_20063_u = posX;
}
if (d2 < -d3) {
field_20064_t = field_20061_w = posZ;
}
if (d1 < -d3) {
field_20065_s = field_20062_v = posY;
}
field_20063_u += d * 0.25D;
field_20061_w += d2 * 0.25D;
field_20062_v += d1 * 0.25D;
}
@Override
protected boolean canDespawn() {
return stats.canDespawn;
}
@Override
public ItemStack getHeldItem() {
if (isAttacking())
return inventory.getWeapon();
else if(advanced.role == EnumRoleType.Companion)
return ((RoleCompanion)roleInterface).getHeldItem();
else if (jobInterface != null && jobInterface.overrideMainHand)
return jobInterface.mainhand;
else
return inventory.getWeapon();
}
2022-11-15 00:48:31 -05:00
@Override
public ItemStack getEquipmentInSlot(int slot){
if(slot == 0)
return inventory.weapons.get(0);
return inventory.armorItemInSlot(4 - slot);
}
@Override
public ItemStack func_130225_q(int slot){
return inventory.armorItemInSlot(3 - slot);
}
@Override
public void setCurrentItemOrArmor(int slot, ItemStack item){
if(slot == 0)
inventory.setWeapon(item);
else{
inventory.armor.put(4 - slot, item);
}
}
private static final ItemStack[] lastActive = new ItemStack[5];
@Override
public ItemStack[] getLastActiveItems(){
return lastActive;
}
@Override
protected void dropEquipment(boolean p_82160_1_, int p_82160_2_){
}
2018-09-13 12:03:28 -04:00
public ItemStack getOffHand() {
if (isAttacking())
return inventory.getOffHand();
else if (jobInterface != null && jobInterface.overrideOffHand)
return jobInterface.offhand;
else
return inventory.getOffHand();
}
2022-11-15 00:48:31 -05:00
2018-09-13 12:03:28 -04:00
@Override
public void onDeath(DamageSource damagesource){
setSprinting(false);
getNavigator().clearPathEntity();
extinguish();
clearActivePotions();
2022-11-15 00:48:31 -05:00
2018-09-13 12:03:28 -04:00
Entity entity = damagesource.getEntity();
EntityLivingBase attackingEntity = null;
2022-11-15 00:48:31 -05:00
if (entity instanceof EntityLivingBase)
2018-09-13 12:03:28 -04:00
attackingEntity = (EntityLivingBase) entity;
if ((entity instanceof EntityArrow) && ((EntityArrow) entity).shootingEntity instanceof EntityLivingBase)
attackingEntity = (EntityLivingBase) ((EntityArrow) entity).shootingEntity;
else if ((entity instanceof EntityThrowable))
attackingEntity = ((EntityThrowable) entity).getThrower();
2022-11-15 00:48:31 -05:00
int droppedXp = inventory.getDroppedXp();
ArrayList<ItemStack> droppedItems = inventory.getDroppedItems(damagesource);
2018-09-13 12:03:28 -04:00
if(!isRemote()){
NpcEvent.DiedEvent event = new NpcEvent.DiedEvent(this.wrappedNPC,damagesource,entity,droppedItems, droppedXp);
if(EventHooks.onNPCKilled(this, event))
return;
droppedItems.clear();
for (IItemStack iItemStack : event.droppedItems) {
droppedItems.add(iItemStack.getMCItemStack());
}
droppedXp = event.expDropped;
if(this.recentlyHit > 0) {
inventory.dropItems(entity, droppedItems);
inventory.dropXp(entity, droppedXp);
}
2018-09-13 12:03:28 -04:00
Line line = advanced.getKilledLine();
if(line != null)
saySurrounding(line.formatTarget(attackingEntity));
}
super.onDeath(damagesource);
}
2022-11-15 00:48:31 -05:00
2018-09-13 12:03:28 -04:00
@Override
public void setDead() {
hasDied = true;
if(worldObj.isRemote || stats.spawnCycle == 3){
this.spawnExplosionParticle();
delete();
}
else {
if(this.riddenByEntity != null)
this.riddenByEntity.mountEntity(null);
if(this.ridingEntity != null)
this.mountEntity(null);
setHealth(-1);
setSprinting(false);
getNavigator().clearPathEntity();
if(killedtime <= 0)
killedtime = stats.respawnTime * 1000 + System.currentTimeMillis();
2022-11-15 00:48:31 -05:00
2018-09-13 12:03:28 -04:00
if (advanced.role != EnumRoleType.None && roleInterface != null)
roleInterface.killed();
if (advanced.job != EnumJobType.None && jobInterface != null)
jobInterface.killed();
}
}
public void delete() {
if (advanced.role != EnumRoleType.None && roleInterface != null)
roleInterface.delete();
if (advanced.job != EnumJobType.None && jobInterface != null)
jobInterface.delete();
super.setDead();
}
2022-11-15 00:48:31 -05:00
2018-09-13 12:03:28 -04:00
public float getStartXPos(){
2022-11-15 00:48:31 -05:00
2018-09-13 12:03:28 -04:00
return getStartPos()[0] + ai.bodyOffsetX / 10;
}
2022-11-15 00:48:31 -05:00
2018-09-13 12:03:28 -04:00
public float getStartZPos(){
return getStartPos()[2] + ai.bodyOffsetZ / 10;
}
2022-11-15 00:48:31 -05:00
2018-09-13 12:03:28 -04:00
public int[] getStartPos(){
if(ai.startPos == null || ai.startPos.length != 3)
2022-11-15 00:48:31 -05:00
ai.startPos = new int[] {
MathHelper.floor_double(posX),
MathHelper.floor_double(posY),
MathHelper.floor_double(posZ) };
2018-09-13 12:03:28 -04:00
return ai.startPos;
}
public boolean isVeryNearAssignedPlace() {
double xx = posX - getStartXPos();
double zz = posZ - getStartZPos();
if (xx < -0.2 || xx > 0.2)
return false;
if (zz < -0.2 || zz > 0.2)
return false;
return true;
}
@Override
public IIcon getItemIcon(ItemStack par1ItemStack, int par2){
2022-11-15 00:48:31 -05:00
if (par1ItemStack.getItem() instanceof ItemBow){
return par1ItemStack.getItem().getIcon(par1ItemStack, par2);
}
2018-09-13 12:03:28 -04:00
EntityPlayer player = CustomNpcs.proxy.getPlayer();
if(player == null)
return super.getItemIcon(par1ItemStack, par2);
return player.getItemIcon(par1ItemStack, par2);
2022-11-15 00:48:31 -05:00
}
2018-09-13 12:03:28 -04:00
public double getStartYPos() {
int i = getStartPos()[0];
int j = getStartPos()[1];
int k = getStartPos()[2];
double yy = 0;
2022-11-13 23:49:49 -06:00
for (int ii = j; ii >= 0; ii--) {
if (this.canFly()) {
if (ii < j - 1) {
yy = j;
break;
}
2022-11-11 16:57:06 -06:00
Block block = worldObj.getBlock(i, ii, k);
2022-11-13 23:49:49 -06:00
AxisAlignedBB bb = block.getCollisionBoundingBoxFromPool(worldObj, i, ii, k);
if (bb != null) {
yy = bb.maxY;
break;
}
} else {
Block block = worldObj.getBlock(i, ii, k);
if (block == null || block == Blocks.air)
2022-11-11 16:57:06 -06:00
continue;
AxisAlignedBB bb = block.getCollisionBoundingBoxFromPool(worldObj, i, ii, k);
if (bb == null)
continue;
yy = bb.maxY;
break;
}
2018-09-13 12:03:28 -04:00
}
if (yy <= 0)
setDead();
return yy;
}
public void givePlayerItem(EntityPlayer player, ItemStack item) {
if (worldObj.isRemote) {
return;
}
item = item.copy();
float f = 0.7F;
double d = (double) (worldObj.rand.nextFloat() * f)
+ (double) (1.0F - f);
double d1 = (double) (worldObj.rand.nextFloat() * f)
+ (double) (1.0F - f);
double d2 = (double) (worldObj.rand.nextFloat() * f)
+ (double) (1.0F - f);
EntityItem entityitem = new EntityItem(worldObj, posX + d, posY + d1,
posZ + d2, item);
entityitem.delayBeforeCanPickup = 2;
worldObj.spawnEntityInWorld(entityitem);
int i = item.stackSize;
if (player.inventory.addItemStackToInventory(item)) {
worldObj.playSoundAtEntity(
entityitem,
"random.pop",
0.2F,
((rand.nextFloat() - rand.nextFloat()) * 0.7F + 1.0F) * 2.0F);
player.onItemPickup(entityitem, i);
if (item.stackSize <= 0) {
entityitem.setDead();
}
}
}
2022-11-15 00:48:31 -05:00
2018-09-13 12:03:28 -04:00
@Override
public boolean isPlayerSleeping() {
return currentAnimation == EnumAnimation.LYING && !isAttacking();
}
@Override
public boolean isRiding() {
return currentAnimation == EnumAnimation.SITTING && !isAttacking() || ridingEntity != null;
}
public boolean isWalking() {
return ai.movingType != EnumMovingType.Standing || isAttacking() || isFollower() || getBoolFlag(1);
}
2022-11-15 00:48:31 -05:00
2018-09-13 12:03:28 -04:00
public void setBoolFlag(boolean bo, int id){
int i = dataWatcher.getWatchableObjectInt(15);
if(bo && (i & id) == 0)
dataWatcher.updateObject(15, i | id);
if(!bo && (i & id) != 0)
dataWatcher.updateObject(15, i - id);
}
2022-11-15 00:48:31 -05:00
2018-09-13 12:03:28 -04:00
/**
* 1: walking, 2:interacting, 4:attacking, 8:killed
*/
public boolean getBoolFlag(int id){
return (dataWatcher.getWatchableObjectInt(15) & id) != 0;
}
@Override
public boolean isSneaking() {
return currentAnimation == EnumAnimation.SNEAKING;
}
@Override
2022-11-15 00:48:31 -05:00
public void knockBack(Entity par1Entity, float par2, double par3, double par5)
{
2018-09-13 12:03:28 -04:00
if(stats.resistances.knockback >= 2)
return;
2022-11-15 00:48:31 -05:00
this.isAirBorne = true;
float f1 = MathHelper.sqrt_double(par3 * par3 + par5 * par5);
float f2 = 0.5F * (2 - stats.resistances.knockback);
this.motionX /= 2.0D;
this.motionY /= 2.0D;
this.motionZ /= 2.0D;
this.motionX -= par3 / (double)f1 * (double)f2;
this.motionY += 0.2 + f2 / 2;
this.motionZ -= par5 / (double)f1 * (double)f2;
if (this.motionY > 0.4000000059604645D)
{
this.motionY = 0.4000000059604645D;
}
}
@Override
public void addVelocity(double p_70024_1_, double p_70024_3_, double p_70024_5_) {
if (this.attackingPlayer != null) {
float f2 = 0.5F * (2 - stats.resistances.knockback);
super.addVelocity(p_70024_1_ * (double)f2,p_70024_3_ * (double)f2,p_70024_5_ * (double)f2);
} else {
super.addVelocity(p_70024_1_,p_70024_3_,p_70024_5_);
}
}
2022-11-15 00:48:31 -05:00
2018-09-13 12:03:28 -04:00
public Faction getFaction() {
String[] split = dataWatcher.getWatchableObjectString(13).split(":");
int faction = 0;
if(worldObj == null || split.length <= 1 && worldObj.isRemote)
return new Faction();
if(split.length > 1)
faction = Integer.parseInt(split[0]);
if(worldObj.isRemote){
Faction fac = new Faction();
fac.id = faction;
fac.color = Integer.parseInt(split[1]);
fac.name = split[2];
return fac;
}
else{
2022-01-10 15:21:48 -06:00
Faction fac = FactionController.getInstance().get(faction);
2018-09-13 12:03:28 -04:00
if (fac == null) {
faction = FactionController.getInstance().getFirstFactionId();
2022-01-10 15:21:48 -06:00
fac = FactionController.getInstance().get(faction);
2018-09-13 12:03:28 -04:00
}
return fac;
}
}
public boolean isRemote(){
return worldObj == null || worldObj.isRemote;
}
public void setFaction(int integer) {
if(integer < 0|| isRemote())
return;
2022-01-10 15:21:48 -06:00
Faction faction = FactionController.getInstance().get(integer);
2018-09-13 12:03:28 -04:00
if(faction == null)
return;
String str = faction.id + ":" + faction.color + ":" + faction.name;
if(str.length() > 64)
str = str.substring(0, 64);
dataWatcher.updateObject(13, str);
}
2022-11-15 00:48:31 -05:00
2018-09-13 12:03:28 -04:00
@Override
public boolean isPotionApplicable(PotionEffect effect){
if(stats.potionImmune)
return false;
if(getCreatureAttribute() == EnumCreatureAttribute.ARTHROPOD && effect.getPotionID() == Potion.poison.id)
return false;
2022-11-15 00:48:31 -05:00
return super.isPotionApplicable(effect);
}
2018-09-13 12:03:28 -04:00
public boolean isAttacking() {
return getBoolFlag(4);
}
public boolean isKilled() {
return getBoolFlag(8) || isDead;
}
@Override
public void writeSpawnData(ByteBuf buffer) {
try {
Server.writeNBT(buffer, writeSpawnData());
} catch (IOException e) {
e.printStackTrace();
}
}
public NBTTagCompound writeSpawnData() {
NBTTagCompound compound = new NBTTagCompound();
display.writeToNBT(compound);
compound.setDouble("MaxHealth", stats.maxHealth);
2018-09-13 12:03:28 -04:00
compound.setTag("Armor", NBTTags.nbtItemStackList(inventory.getArmor()));
compound.setTag("Weapons", NBTTags.nbtItemStackList(inventory.getWeapons()));
compound.setInteger("Speed", ai.getWalkingSpeed());
compound.setBoolean("DeadBody", stats.hideKilledBody);
compound.setInteger("StandingState", ai.standingType.ordinal());
compound.setInteger("MovingState", ai.movingType.ordinal());
compound.setInteger("Orientation", ai.orientation);
compound.setFloat("OffsetY",ai.bodyOffsetY);
2018-09-13 12:03:28 -04:00
compound.setInteger("Role", advanced.role.ordinal());
compound.setInteger("Job", advanced.job.ordinal());
if(advanced.job == EnumJobType.Bard){
NBTTagCompound bard = new NBTTagCompound();
jobInterface.writeToNBT(bard);
compound.setTag("Bard", bard);
}
if(advanced.role == EnumRoleType.Companion){
NBTTagCompound bard = new NBTTagCompound();
roleInterface.writeToNBT(bard);
compound.setTag("Companion", bard);
}
2022-11-15 00:48:31 -05:00
2018-09-13 12:03:28 -04:00
if(this instanceof EntityCustomNpc){
compound.setTag("ModelData", ((EntityCustomNpc)this).modelData.writeToNBT());
}
return compound;
}
@Override
public void readSpawnData(ByteBuf buf) {
try {
readSpawnData(Server.readNBT(buf));
} catch (IOException e) {
2022-11-15 00:48:31 -05:00
}
2018-09-13 12:03:28 -04:00
}
public void readSpawnData(NBTTagCompound compound) {
stats.maxHealth = compound.getDouble("MaxHealth");
2018-09-13 12:03:28 -04:00
ai.setWalkingSpeed(compound.getInteger("Speed"));
stats.hideKilledBody = compound.getBoolean("DeadBody");
ai.standingType = EnumStandingType.values()[compound.getInteger("StandingState") % EnumStandingType.values().length];
ai.movingType = EnumMovingType.values()[compound.getInteger("MovingState") % EnumMovingType.values().length];
ai.orientation = compound.getInteger("Orientation");
ai.bodyOffsetY=compound.getFloat("OffsetY");
2022-11-15 00:48:31 -05:00
2018-09-13 12:03:28 -04:00
this.getEntityAttribute(SharedMonsterAttributes.maxHealth).setBaseValue(stats.maxHealth);
inventory.setArmor(NBTTags.getItemStackList(compound.getTagList("Armor", 10)));
inventory.setWeapons(NBTTags.getItemStackList(compound.getTagList("Weapons", 10)));
advanced.setRole(compound.getInteger("Role"));
advanced.setJob(compound.getInteger("Job"));
if(advanced.job == EnumJobType.Bard){
NBTTagCompound bard = compound.getCompoundTag("Bard");
jobInterface.readFromNBT(bard);
2022-11-15 00:48:31 -05:00
}
2018-09-13 12:03:28 -04:00
if(advanced.role == EnumRoleType.Companion){
2023-03-02 16:10:22 -05:00
NBTTagCompound companion = compound.getCompoundTag("Companion");
roleInterface.readFromNBT(companion);
2022-11-15 00:48:31 -05:00
}
2018-09-13 12:03:28 -04:00
if(this instanceof EntityCustomNpc){
((EntityCustomNpc)this).modelData.readFromNBT(compound.getCompoundTag("ModelData"));
}
display.readToNBT(compound);
}
2018-09-13 12:03:28 -04:00
@Override
public String getCommandSenderName() {
return display.name;
}
@Override
public boolean canCommandSenderUseCommand(int var1, String var2) {
2023-01-07 00:21:08 -05:00
if(ConfigMain.NpcUseOpCommands)
2022-11-15 00:48:31 -05:00
return true;
return var1 <= 2;
2018-09-13 12:03:28 -04:00
}
@Override
public ChunkCoordinates getPlayerCoordinates() {
2022-11-15 00:48:31 -05:00
return new ChunkCoordinates(MathHelper.floor_double(posX), MathHelper.floor_double(posY), MathHelper.floor_double(posZ));
2018-09-13 12:03:28 -04:00
}
2022-11-15 00:48:31 -05:00
2018-09-13 12:03:28 -04:00
@Override
public boolean canAttackClass(Class par1Class)
2022-11-15 00:48:31 -05:00
{
return EntityBat.class != par1Class;
}
2018-09-13 12:03:28 -04:00
public void setImmuneToFire(boolean immuneToFire) {
this.isImmuneToFire = immuneToFire;
stats.immuneToFire = immuneToFire;
}
public boolean handleLavaMovement()
{
return !stats.immuneToFire && super.handleLavaMovement();
}
public boolean handleWaterMovement()
{
2022-11-12 15:53:20 -06:00
if (stats.drowningType != 1) {
2022-11-13 23:49:49 -06:00
if (this.worldObj.handleMaterialAcceleration(this.boundingBox.expand(0.0D, -this.height/2.0D, 0.0D).contract(0.001D, 0.001D, 0.001D), Material.water, this)) {
2022-11-12 15:53:20 -06:00
this.fallDistance = 0.0F;
this.inWater = true;
this.setFire(0);
} else {
this.inWater = false;
}
return false;
} else {
return super.handleWaterMovement();
}
}
public boolean canBreatheUnderwater()
{
return stats.drowningType != 1;
}
2022-11-15 00:48:31 -05:00
2018-09-13 12:03:28 -04:00
public void setAvoidWater(boolean avoidWater) {
this.getNavigator().setAvoidsWater(avoidWater);
ai.avoidsWater = avoidWater;
}
@Override
protected void fall(float par1) {
if (!this.stats.noFallDamage)
super.fall(par1);
}
@Override
2022-11-15 00:48:31 -05:00
public void setInWeb(){
if(!stats.ignoreCobweb)
2022-11-15 00:48:31 -05:00
super.setInWeb();
}
public boolean isInRange(Entity entity, double range){
return this.isInRange(entity.posX, entity.posY, entity.posZ, range);
}
public boolean isInRange(double posX, double posY, double posZ, double range){
double y = Math.abs(this.posY - posY);
if(posY >= 0 && y > range)
return false;
double x = Math.abs(this.posX - posX);
double z = Math.abs(this.posZ - posZ);
return x <= range && z <= range;
}
2018-09-13 12:03:28 -04:00
@Override
public boolean canBeCollidedWith(){
return !isKilled();
}
2021-06-13 16:22:06 -04:00
@Override
public boolean canBePushed() {
2022-01-14 19:07:41 -06:00
return this.display.collidesWith == 0;
}
// checks for any entity within a certain boundingbox, eg minecarts
@Override
protected void collideWithNearbyEntities() {
if(this.display.collidesWith != 1) {
List list = this.worldObj.getEntitiesWithinAABBExcludingEntity(this, this.boundingBox.expand(0.20000000298023224D, 0.0D, 0.20000000298023224D));
if (list != null && !list.isEmpty()) {
for (int i = 0; i < list.size(); ++i) {
Entity entity = (Entity) list.get(i);
if (this.canBePushed() ||
2022-11-15 00:48:31 -05:00
(entity instanceof EntityNPCInterface && (this.display.collidesWith == 2 || this.display.collidesWith == 4)) ||
(entity instanceof EntityPlayerMP && (this.display.collidesWith == 3 || this.display.collidesWith == 4))
2022-01-14 19:07:41 -06:00
) {
super.collideWithEntity(entity);
}
}
}
}
}
public void applyEntityCollision(Entity entity)
{
if (entity.riddenByEntity != this && entity.ridingEntity != this)
{
double d0 = entity.posX - this.posX;
double d1 = entity.posZ - this.posZ;
double d2 = MathHelper.abs_max(d0, d1);
if (d2 >= 0.009999999776482582D)
{
d2 = (double)MathHelper.sqrt_double(d2);
d0 /= d2;
d1 /= d2;
double d3 = 1.0D / d2;
if (d3 > 1.0D)
{
d3 = 1.0D;
}
d0 *= d3;
d1 *= d3;
d0 *= 0.05000000074505806D;
d1 *= 0.05000000074505806D;
d0 *= (double)(1.0F - this.entityCollisionReduction);
d1 *= (double)(1.0F - this.entityCollisionReduction);
if (this.canBePushed() ||
2022-11-15 00:48:31 -05:00
(entity instanceof EntityNPCInterface && (this.display.collidesWith == 2 || this.display.collidesWith == 4)) ||
(entity instanceof EntityPlayerMP && (this.display.collidesWith == 3 || this.display.collidesWith == 4))
2022-01-14 19:07:41 -06:00
)
this.addVelocity(-d0, 0.0D, -d1);
entity.addVelocity(d0, 0.0D, d1);
}
}
}
// not any entity can collide. if you want projectiles to still be
// effective, you will have to handle those yourself
@Override
2022-01-14 19:07:41 -06:00
protected void collideWithEntity(Entity p_82167_1_) {
2022-01-14 19:07:41 -06:00
}
2021-06-13 16:22:06 -04:00
public boolean canFly(){
return false;
}
2018-09-13 12:03:28 -04:00
public EntityAIRangedAttack getRangedTask(){
return this.aiRange;
}
public String getRoleDataWatcher(){
return dataWatcher.getWatchableObjectString(16);
}
2022-11-15 00:48:31 -05:00
2018-09-13 12:03:28 -04:00
public void setRoleDataWatcher(String s){
dataWatcher.updateObject(16, s);
}
2022-11-15 00:48:31 -05:00
2018-09-13 12:03:28 -04:00
@Override
public World getEntityWorld() {
return worldObj;
}
@Override
2022-11-15 00:48:31 -05:00
public boolean isInvisibleToPlayer(EntityPlayer player){
return (scriptInvisibleToPlayer(player) || display.visible == 1) && (player.getHeldItem() == null || player.getHeldItem().getItem() != CustomItems.wand);
}
2018-09-13 12:03:28 -04:00
public boolean scriptInvisibleToPlayer(EntityPlayer player){
return display.invisibleToList != null && display.invisibleToList.contains(player.getPersistentID());
}
2018-09-13 12:03:28 -04:00
@Override
public boolean isInvisible(){
return display.visible != 0;
}
2022-11-15 00:48:31 -05:00
2018-09-13 12:03:28 -04:00
@Override
public void addChatMessage(IChatComponent var1) {}
2022-11-15 00:48:31 -05:00
2018-09-13 12:03:28 -04:00
public void setCurrentAnimation(EnumAnimation animation) {
2022-11-15 00:48:31 -05:00
currentAnimation = animation;
dataWatcher.updateObject(14, animation.ordinal());
2018-09-13 12:03:28 -04:00
}
2022-11-15 00:48:31 -05:00
2018-09-13 12:03:28 -04:00
public boolean canSee(Entity entity){
return this.getEntitySenses().canSee(entity);
}
2022-11-15 00:48:31 -05:00
2018-09-13 12:03:28 -04:00
public boolean isFollower() {
2022-11-15 00:48:31 -05:00
return advanced.role == EnumRoleType.Follower && ((RoleFollower) roleInterface).isFollowing() ||
advanced.role == EnumRoleType.Companion && ((RoleCompanion) roleInterface).isFollowing() ||
2018-09-13 12:03:28 -04:00
advanced.job == EnumJobType.Follower && ((JobFollower)jobInterface).isFollowing();
}
2022-11-15 00:48:31 -05:00
2018-09-13 12:03:28 -04:00
public EntityLivingBase getOwner(){
if(roleInterface instanceof RoleFollower)
return ((RoleFollower)roleInterface).owner;
2022-11-15 00:48:31 -05:00
2018-09-13 12:03:28 -04:00
if(roleInterface instanceof RoleCompanion)
return ((RoleCompanion)roleInterface).owner;
if(jobInterface instanceof JobFollower)
return ((JobFollower)jobInterface).following;
2022-11-15 00:48:31 -05:00
2018-09-13 12:03:28 -04:00
return null;
}
2022-11-15 00:48:31 -05:00
2018-09-13 12:03:28 -04:00
public boolean hasOwner(){
2022-11-15 00:48:31 -05:00
return advanced.role == EnumRoleType.Follower && ((RoleFollower) roleInterface).hasOwner() ||
advanced.role == EnumRoleType.Companion && ((RoleCompanion) roleInterface).hasOwner() ||
2018-09-13 12:03:28 -04:00
advanced.job == EnumJobType.Follower && ((JobFollower)jobInterface).hasOwner();
}
2022-11-15 00:48:31 -05:00
2018-09-13 12:03:28 -04:00
public int followRange() {
if(advanced.role == EnumRoleType.Follower && ((RoleFollower) roleInterface).isFollowing())
return 36;
if(advanced.role == EnumRoleType.Companion && ((RoleCompanion) roleInterface).isFollowing())
return ((RoleCompanion) roleInterface).followRange();
if(advanced.job == EnumJobType.Follower && ((JobFollower)jobInterface).isFollowing())
return 16;
2022-11-15 00:48:31 -05:00
2018-09-13 12:03:28 -04:00
return 225;
}
@Override
public void setHomeArea(int x, int y, int z, int range){
super.setHomeArea(x, y, z, range);
ai.startPos = new int[]{x, y, z};
}
@Override
2022-11-15 00:48:31 -05:00
protected float applyArmorCalculations(DamageSource source, float damage){
2018-09-13 12:03:28 -04:00
if(advanced.role == EnumRoleType.Companion)
damage = ((RoleCompanion)roleInterface).applyArmorCalculations(source, damage);
2022-11-15 00:48:31 -05:00
return damage;
}
2018-09-13 12:03:28 -04:00
@Override
2022-11-15 00:48:31 -05:00
public boolean isOnSameTeam(EntityLivingBase entity){
2018-09-13 12:03:28 -04:00
if(entity instanceof EntityPlayer && !isRemote() && getFaction().isFriendlyToPlayer((EntityPlayer)entity))
return true;
2022-11-15 00:48:31 -05:00
return super.isOnSameTeam(entity);
}
2018-09-13 12:03:28 -04:00
public void setDataWatcher(DataWatcher dataWatcher) {
this.dataWatcher = dataWatcher;
}
@Override
2022-11-15 00:48:31 -05:00
public void moveEntityWithHeading(float p_70612_1_, float p_70612_2_){
double d0 = this.posX;
double d1 = this.posY;
double d2 = this.posZ;
super.moveEntityWithHeading(p_70612_1_, p_70612_2_);
if(advanced.role == EnumRoleType.Companion && !isRemote())
((RoleCompanion)roleInterface).addMovementStat(this.posX - d0, this.posY - d1, this.posZ - d2);
}
2018-09-13 12:03:28 -04:00
@Override
2022-11-15 00:48:31 -05:00
public boolean allowLeashing(){
return false;
}
2018-09-13 12:03:28 -04:00
@Override
2022-11-15 00:48:31 -05:00
public boolean shouldDismountInWater(Entity rider){
return false;
}
2021-04-29 20:42:52 -04:00
// Model Types: 0: Steve 64x32, 1: Steve 64x64, 2: Alex 64x64
public int getModelType()
{
return this.display.modelType;
}
2021-05-08 03:51:29 -04:00
2021-04-29 20:42:52 -04:00
public void setModelType(int val)
{
this.display.modelType = val;
}
protected void updateLeashedState(){}
2018-09-13 12:03:28 -04:00
}