diff --git a/src/api b/src/api index 21b4d91fc..c3a023021 160000 --- a/src/api +++ b/src/api @@ -1 +1 @@ -Subproject commit 21b4d91fc7ac0d69026fc9ebb1185961190061db +Subproject commit c3a023021d94aa86edfaf8262b25354a8acddf01 diff --git a/src/main/java/noppes/npcs/EventHooks.java b/src/main/java/noppes/npcs/EventHooks.java index 94bf5af59..24c6301fc 100644 --- a/src/main/java/noppes/npcs/EventHooks.java +++ b/src/main/java/noppes/npcs/EventHooks.java @@ -22,14 +22,17 @@ import net.minecraftforge.event.world.WorldEvent; import noppes.npcs.api.IWorld; import noppes.npcs.api.entity.IEntity; import noppes.npcs.api.entity.IPlayer; +import noppes.npcs.api.entity.IProjectile; import noppes.npcs.api.gui.ICustomGui; import noppes.npcs.api.item.IItemCustom; import noppes.npcs.api.item.IItemStack; import noppes.npcs.constants.EnumScriptType; import noppes.npcs.controllers.CustomGuiController; +import noppes.npcs.controllers.ScriptContainer; import noppes.npcs.controllers.ScriptController; import noppes.npcs.controllers.data.*; import noppes.npcs.entity.EntityNPCInterface; +import noppes.npcs.entity.EntityProjectile; import noppes.npcs.scripted.NpcAPI; import noppes.npcs.scripted.event.*; import noppes.npcs.scripted.event.PlayerEvent.*; @@ -239,6 +242,25 @@ public class EventHooks { NpcAPI.EVENT_BUS.post(event); } + public static void onProjectileTick(EntityProjectile projectile) { + ProjectileEvent.UpdateEvent event = new ProjectileEvent.UpdateEvent((IProjectile) NpcAPI.Instance().getIEntity(projectile)); + for(ScriptContainer script : projectile.scripts) { + if(script.isValid()) { + script.run(EnumScriptType.PROJECTILE_TICK, event); + } + } + NpcAPI.EVENT_BUS.post(event); + } + + public static void onProjectileImpact(EntityProjectile projectile, ProjectileEvent.ImpactEvent event) { + for(ScriptContainer script : projectile.scripts) { + if(script.isValid()) { + script.run(EnumScriptType.PROJECTILE_IMPACT, event); + } + } + NpcAPI.EVENT_BUS.post(event); + } + public static void onPlayerInit(PlayerDataScript handler, IPlayer player) { noppes.npcs.scripted.event.PlayerEvent.InitEvent event = new noppes.npcs.scripted.event.PlayerEvent.InitEvent(player); handler.callScript(EnumScriptType.INIT, event); diff --git a/src/main/java/noppes/npcs/controllers/ScriptContainer.java b/src/main/java/noppes/npcs/controllers/ScriptContainer.java index 254f6a739..862b03c45 100644 --- a/src/main/java/noppes/npcs/controllers/ScriptContainer.java +++ b/src/main/java/noppes/npcs/controllers/ScriptContainer.java @@ -204,6 +204,10 @@ public class ScriptContainer { } } + public boolean isValid() { + return init && !errored; + } + public boolean hasCode() { return !this.getFullCode().isEmpty(); } diff --git a/src/main/java/noppes/npcs/entity/EntityProjectile.java b/src/main/java/noppes/npcs/entity/EntityProjectile.java index 05a9e32d2..ffb64ca1d 100644 --- a/src/main/java/noppes/npcs/entity/EntityProjectile.java +++ b/src/main/java/noppes/npcs/entity/EntityProjectile.java @@ -25,10 +25,18 @@ import net.minecraft.util.MovingObjectPosition.MovingObjectType; import net.minecraft.world.Explosion; import net.minecraft.world.World; import noppes.npcs.DataStats; +import noppes.npcs.EventHooks; +import noppes.npcs.api.IPos; +import noppes.npcs.api.IWorld; +import noppes.npcs.api.entity.IProjectile; import noppes.npcs.constants.EnumParticleType; import noppes.npcs.constants.EnumPotionType; +import noppes.npcs.controllers.ScriptContainer; +import noppes.npcs.scripted.NpcAPI; +import noppes.npcs.scripted.event.ProjectileEvent; import noppes.npcs.util.IProjectileCallback; +import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.UUID; @@ -76,10 +84,11 @@ public class EntityProjectile extends EntityThrowable { public EnumPotionType effect = EnumPotionType.None; public int duration = 5; public int amplify = 0; + public int accuracy = 60; public IProjectileCallback callback; public ItemStack callbackItem; - + public List scripts = new ArrayList(); public EntityProjectile(World par1World) { @@ -209,6 +218,10 @@ public class EntityProjectile extends EntityThrowable { public void onUpdate() { super.onEntityUpdate(); + if(++ticksExisted % 10 == 0){ + EventHooks.onProjectileTick(this); + } + if (this.prevRotationPitch == 0.0F && this.prevRotationYaw == 0.0F) { float f = MathHelper.sqrt_double(this.motionX * this.motionX + this.motionZ * this.motionZ); @@ -432,11 +445,25 @@ public class EntityProjectile extends EntityThrowable { @Override protected void onImpact(MovingObjectPosition movingobjectposition) { + ProjectileEvent.ImpactEvent event; + if(movingobjectposition.entityHit != null) { + IPos pos = NpcAPI.Instance().getIPos(movingobjectposition.entityHit.posX,movingobjectposition.entityHit.posY,movingobjectposition.entityHit.posZ); + event = new ProjectileEvent.ImpactEvent((IProjectile) NpcAPI.Instance().getIEntity(this), 0, movingobjectposition.entityHit); + } + else { + IPos pos = NpcAPI.Instance().getIPos(movingobjectposition.blockX,movingobjectposition.blockY,movingobjectposition.blockZ); + IWorld world = NpcAPI.Instance().getIWorld(this.worldObj); + event = new ProjectileEvent.ImpactEvent((IProjectile) NpcAPI.Instance().getIEntity(this), 1, NpcAPI.Instance().getIBlock(world, pos)); + } + if (movingobjectposition.entityHit != null) { + if (callback != null && callbackItem != null && movingobjectposition.entityHit instanceof EntityLivingBase && callback.onImpact(this, (EntityLivingBase) movingobjectposition.entityHit, callbackItem)) { + return; + } + } + EventHooks.onProjectileImpact(this, event); + if (movingobjectposition.entityHit != null) { - if(callback != null && callbackItem != null && movingobjectposition.entityHit instanceof EntityLivingBase && callback.onImpact(this, (EntityLivingBase)movingobjectposition.entityHit, callbackItem)){ - return; - } float damage = this.damage; if(damage == 0) damage = 0.001f; @@ -695,6 +722,7 @@ public class EntityProjectile extends EntityThrowable { par1NBTTagCompound.setBoolean("accelerate", this.accelerate); par1NBTTagCompound.setByte("glows", this.dataWatcher.getWatchableObjectByte(24)); par1NBTTagCompound.setBoolean("explosive", explosive); + par1NBTTagCompound.setInteger("accuracy", accuracy); par1NBTTagCompound.setInteger("PotionEffect", effect.ordinal()); par1NBTTagCompound.setString("trail", this.dataWatcher.getWatchableObjectString(22)); par1NBTTagCompound.setByte("Render3D", this.dataWatcher.getWatchableObjectByte(28)); @@ -724,6 +752,7 @@ public class EntityProjectile extends EntityThrowable { this.duration = par1NBTTagCompound.getInteger("effectDuration"); this.accelerate = par1NBTTagCompound.getBoolean("accelerate"); this.explosive = par1NBTTagCompound.getBoolean("explosive"); + this.accuracy = par1NBTTagCompound.getInteger("accuracy"); this.effect = EnumPotionType.values()[par1NBTTagCompound.getInteger("PotionEffect") % EnumPotionType.values().length]; this.dataWatcher.updateObject(22, par1NBTTagCompound.getString("trail")); this.dataWatcher.updateObject(23, Integer.valueOf(par1NBTTagCompound.getInteger("size"))); diff --git a/src/main/java/noppes/npcs/scripted/NpcAPI.java b/src/main/java/noppes/npcs/scripted/NpcAPI.java index f90b75f47..f53337d83 100644 --- a/src/main/java/noppes/npcs/scripted/NpcAPI.java +++ b/src/main/java/noppes/npcs/scripted/NpcAPI.java @@ -54,6 +54,7 @@ import noppes.npcs.controllers.data.FramePart; import noppes.npcs.controllers.data.SkinOverlay; import noppes.npcs.entity.EntityCustomNpc; import noppes.npcs.entity.EntityNPCInterface; +import noppes.npcs.entity.EntityProjectile; import noppes.npcs.items.ItemScripted; import noppes.npcs.scripted.entity.*; import noppes.npcs.scripted.gui.ScriptGui; @@ -202,6 +203,8 @@ public class NpcAPI extends AbstractNpcAPI { data = new ScriptEntityData(new ScriptLiving<>((EntityLiving) entity)); else if(entity instanceof EntityLivingBase) data = new ScriptEntityData(new ScriptLivingBase<>((EntityLivingBase)entity)); + else if(entity instanceof EntityProjectile) + data = new ScriptEntityData(new ScriptProjectile<>((EntityProjectile)entity)); else data = new ScriptEntityData(new ScriptEntity<>(entity)); entity.registerExtendedProperties("ScriptedObject", data); diff --git a/src/main/java/noppes/npcs/scripted/constants/EntityType.java b/src/main/java/noppes/npcs/scripted/constants/EntityType.java index 3a9b1842c..4bd9cdfd5 100644 --- a/src/main/java/noppes/npcs/scripted/constants/EntityType.java +++ b/src/main/java/noppes/npcs/scripted/constants/EntityType.java @@ -7,4 +7,6 @@ public class EntityType { public static final int MONSTER = 3; public static final int ANIMAL = 4; public static final int LIVING = 5; + public static final int ITEM = 6; + public static final int PROJECTILE = 7; } diff --git a/src/main/java/noppes/npcs/scripted/entity/ScriptProjectile.java b/src/main/java/noppes/npcs/scripted/entity/ScriptProjectile.java new file mode 100644 index 000000000..e22bdb8f4 --- /dev/null +++ b/src/main/java/noppes/npcs/scripted/entity/ScriptProjectile.java @@ -0,0 +1,90 @@ +package noppes.npcs.scripted.entity; + +import net.minecraft.util.MathHelper; +import noppes.npcs.api.entity.IEntity; +import noppes.npcs.api.entity.IProjectile; +import noppes.npcs.api.item.IItemStack; +import noppes.npcs.controllers.ScriptContainer; +import noppes.npcs.entity.EntityProjectile; +import noppes.npcs.scripted.CustomNPCsException; +import noppes.npcs.scripted.NpcAPI; +import noppes.npcs.scripted.constants.EntityType; + +public class ScriptProjectile extends ScriptEntity implements IProjectile { + protected T entity; + + public ScriptProjectile(T entity) { + super(entity); + this.entity = entity; + } + + public IItemStack getItem() { + return NpcAPI.Instance().getIItemStack(entity.getItemDisplay()); + } + + public void setItem(IItemStack item) { + if(item == null) + entity.setThrownItem(null); + else + entity.setThrownItem(item.getMCItemStack()); + } + + public boolean getHasGravity() { + return entity.hasGravity(); + } + + public void setHasGravity(boolean bo) { + entity.setHasGravity(bo); + } + + public int getAccuracy() { + return entity.accuracy; + } + + public void setAccuracy(int accuracy) { + entity.accuracy = accuracy; + } + + public void setHeading(IEntity entity) { + setHeading(entity.getX(), entity.getMCEntity().boundingBox.minY + (double)(entity.getHeight() / 2.0F), entity.getZ()); + } + + public void setHeading(double x, double y, double z) { + x = x - entity.posX; + y = y - entity.posY; + z = z - entity.posZ; + float varF = entity.hasGravity() ? (float) Math.sqrt(x * x + z * z) : 0.0F; + float angle = entity.getAngleForXYZ(x, y, z, varF, false); + float acc = (float) (20.0F - Math.floor(entity.accuracy / 5.0F)); + entity.setThrowableHeading(x, y, z, angle, acc); + } + + public void setHeading(float yaw, float pitch) { + entity.prevRotationYaw = entity.rotationYaw = yaw; + entity.prevRotationPitch = entity.rotationPitch = pitch; + + double varX = (double)(-MathHelper.sin(yaw / 180.0F * (float)Math.PI) * MathHelper.cos(pitch / 180.0F * (float)Math.PI)); + double varZ = (double)(MathHelper.cos(yaw / 180.0F * (float)Math.PI) * MathHelper.cos(pitch / 180.0F * (float)Math.PI)); + double varY = (double)(-MathHelper.sin(pitch / 180.0F * (float)Math.PI)); + + float acc = (float) (20.0F - Math.floor(entity.accuracy / 5.0F)); + entity.setThrowableHeading(varX, varY, varZ, -pitch, acc); + } + + public int getType() { + return EntityType.PROJECTILE; + } + + public boolean typeOf(int type){ + return type == EntityType.PROJECTILE || super.typeOf(type); + } + + public void enableEvents() { + if(ScriptContainer.Current == null) + throw new CustomNPCsException("Can only be called during scripts"); + + if(!entity.scripts.contains(ScriptContainer.Current)) { + entity.scripts.add(ScriptContainer.Current); + } + } +} diff --git a/src/main/java/noppes/npcs/scripted/event/ProjectileEvent.java b/src/main/java/noppes/npcs/scripted/event/ProjectileEvent.java new file mode 100644 index 000000000..21dffd0f2 --- /dev/null +++ b/src/main/java/noppes/npcs/scripted/event/ProjectileEvent.java @@ -0,0 +1,37 @@ +package noppes.npcs.scripted.event; + +import noppes.npcs.api.entity.IProjectile; + +public class ProjectileEvent extends CustomNPCsEvent { + public IProjectile projectile; + + public ProjectileEvent(IProjectile projectile) { + this.projectile = projectile; + } + + /** + * projectileTick + */ + public static class UpdateEvent extends ProjectileEvent { + public UpdateEvent(IProjectile projectile) { + super(projectile); + } + } + + /** + * projectileImpact + */ + public static class ImpactEvent extends ProjectileEvent { + /** + * 0:entity, 1:block + */ + public final int type; + public final Object target; + + public ImpactEvent(IProjectile projectile, int type, Object target) { + super(projectile); + this.type = type; + this.target = target; + } + } +}