diff --git a/src/main/java/com/simibubi/create/content/curiosities/weapons/PotatoCannonProjectileTypes.java b/src/main/java/com/simibubi/create/content/curiosities/weapons/PotatoCannonProjectileTypes.java index 676293c6b..d6008d8ce 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/weapons/PotatoCannonProjectileTypes.java +++ b/src/main/java/com/simibubi/create/content/curiosities/weapons/PotatoCannonProjectileTypes.java @@ -194,7 +194,35 @@ public class PotatoCannonProjectileTypes { .renderTumbling() .soundPitch(0.9f) .onBlockHit(placeBlockOnGround(Blocks.PUMPKIN.delegate)) - .registerAndAssign(Blocks.PUMPKIN) + .registerAndAssign(Blocks.PUMPKIN), + + PUMPKIN_PIE = create("pumpkin_pie").damage(7) + .reloadTicks(15) + .knockback(0.05f) + .velocity(1.1f) + .renderTumbling() + .sticky() + .soundPitch(1.1f) + .registerAndAssign(Items.PUMPKIN_PIE), + + CAKE = create("cake").damage(8) + .reloadTicks(15) + .knockback(0.1f) + .velocity(1.1f) + .renderTumbling() + .sticky() + .soundPitch(1.0f) + .registerAndAssign(Items.CAKE), + + BLAZE_CAKE = create("blaze_cake").damage(12) + .reloadTicks(20) + .knockback(0.3f) + .velocity(1.1f) + .renderTumbling() + .sticky() + .onEntityHit(ray -> ray.getEntity().setFire(12)) + .soundPitch(1.0f) + .registerAndAssign(AllItems.BLAZE_CAKE.get()) ; public static void registerType(ResourceLocation resLoc, PotatoCannonProjectileTypes type) { @@ -225,6 +253,7 @@ public class PotatoCannonProjectileTypes { private int damage = 1; private int split = 1; private float fwoompPitch = 1; + private boolean sticky = false; private PotatoProjectileRenderMode renderMode = new PotatoProjectileRenderMode.Billboard(); private Consumer onEntityHit = e -> { }; @@ -267,6 +296,8 @@ public class PotatoCannonProjectileTypes { return damage; } + public boolean isSticky() { return sticky; } + public void onEntityHit(EntityRayTraceResult ray) { onEntityHit.accept(ray); } @@ -445,6 +476,11 @@ public class PotatoCannonProjectileTypes { return this; } + public Builder sticky() { + result.sticky = true; + return this; + } + public Builder onEntityHit(Consumer callback) { result.onEntityHit = callback; return this; diff --git a/src/main/java/com/simibubi/create/content/curiosities/weapons/PotatoProjectileEntity.java b/src/main/java/com/simibubi/create/content/curiosities/weapons/PotatoProjectileEntity.java index 6640b7b57..9c5a056a5 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/weapons/PotatoProjectileEntity.java +++ b/src/main/java/com/simibubi/create/content/curiosities/weapons/PotatoProjectileEntity.java @@ -36,6 +36,12 @@ import net.minecraftforge.fml.network.NetworkHooks; public class PotatoProjectileEntity extends DamagingProjectileEntity implements IEntityAdditionalSpawnData { ItemStack stack = ItemStack.EMPTY; + + Entity stuckEntity; + Vector3d stuckOffset; + PotatoProjectileRenderMode stuckRenderer; + double stuckFallSpeed; + PotatoCannonProjectileTypes type; public PotatoProjectileEntity(EntityType type, World world) { @@ -69,10 +75,48 @@ public class PotatoProjectileEntity extends DamagingProjectileEntity implements super.writeAdditional(nbt); } + public Entity getStuckEntity() { + if (stuckEntity == null) + return null; + if (!stuckEntity.isAlive()) + return null; + return stuckEntity; + } + + public void setStuckEntity(Entity stuckEntity) { + this.stuckEntity = stuckEntity; + this.stuckOffset = getPositionVec().subtract(stuckEntity.getPositionVec()); + this.stuckRenderer = new PotatoProjectileRenderMode.StuckToEntity(stuckOffset); + this.stuckFallSpeed = 0.0; + setMotion(Vector3d.ZERO); + } + + public PotatoProjectileRenderMode getRenderMode() { + if (getStuckEntity() != null) + return stuckRenderer; + + return getProjectileType().getRenderMode(); + } + public void tick() { PotatoCannonProjectileTypes projectileType = getProjectileType(); - setMotion(getMotion().add(0, -.05 * projectileType.getGravityMultiplier(), 0) - .scale(projectileType.getDrag())); + + Entity stuckEntity = getStuckEntity(); + if (stuckEntity != null) { + if (getY() < stuckEntity.getY() - 0.1) { + pop(getPositionVec()); + remove(); + } else { + stuckFallSpeed += 0.007 * projectileType.getGravityMultiplier(); + stuckOffset = stuckOffset.add(0, -stuckFallSpeed, 0); + Vector3d pos = stuckEntity.getPositionVec().add(stuckOffset); + setPosition(pos.x, pos.y, pos.z); + } + } else { + setMotion(getMotion().add(0, -0.05 * projectileType.getGravityMultiplier(), 0) + .scale(projectileType.getDrag())); + } + super.tick(); } @@ -95,6 +139,9 @@ public class PotatoProjectileEntity extends DamagingProjectileEntity implements protected void onEntityHit(EntityRayTraceResult ray) { super.onEntityHit(ray); + if (getStuckEntity() != null) + return; + Vector3d hit = ray.getHitVec(); Entity target = ray.getEntity(); PotatoCannonProjectileTypes projectileType = getProjectileType(); @@ -116,7 +163,8 @@ public class PotatoProjectileEntity extends DamagingProjectileEntity implements if (this.isBurning() && !targetIsEnderman) target.setFire(5); - if (!target.attackEntityFrom(causePotatoDamage(), (float) damage)) { + boolean onServer = !world.isRemote; + if (onServer && !target.attackEntityFrom(causePotatoDamage(), (float) damage)) { target.setFireTicks(k); remove(); return; @@ -147,13 +195,12 @@ public class PotatoProjectileEntity extends DamagingProjectileEntity implements livingentity.addVelocity(appliedMotion.x, 0.1D, appliedMotion.z); } - boolean onServer = !world.isRemote; if (onServer && owner instanceof LivingEntity) { EnchantmentHelper.applyThornEnchantments(livingentity, owner); EnchantmentHelper.applyArthropodEnchantments((LivingEntity) owner, livingentity); } - if (owner != null && livingentity != owner && livingentity instanceof PlayerEntity + if (livingentity != owner && livingentity instanceof PlayerEntity && owner instanceof ServerPlayerEntity && !this.isSilent()) { ((ServerPlayerEntity) owner).connection .sendPacket(new SChangeGameStatePacket(SChangeGameStatePacket.PROJECTILE_HIT_PLAYER, 0.0F)); @@ -167,7 +214,12 @@ public class PotatoProjectileEntity extends DamagingProjectileEntity implements AllTriggers.POTATO_KILL.trigger(serverplayerentity); } - remove(); + if (type.isSticky() && target.isAlive()) { + setStuckEntity(target); + } else { + remove(); + } + } public static void playHitSound(World world, Vector3d location) { diff --git a/src/main/java/com/simibubi/create/content/curiosities/weapons/PotatoProjectileRenderMode.java b/src/main/java/com/simibubi/create/content/curiosities/weapons/PotatoProjectileRenderMode.java index 9fb0c04e3..56c23cc01 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/weapons/PotatoProjectileRenderMode.java +++ b/src/main/java/com/simibubi/create/content/curiosities/weapons/PotatoProjectileRenderMode.java @@ -72,6 +72,22 @@ public abstract class PotatoProjectileRenderMode { } + public static class StuckToEntity extends PotatoProjectileRenderMode { + + private Vector3d offset; + + public StuckToEntity(Vector3d offset) { + this.offset = offset; + } + + @Override + @OnlyIn(Dist.CLIENT) + public void transform(MatrixStack ms, PotatoProjectileEntity entity, float pt) { + MatrixStacker.of(ms).rotateY(AngleHelper.deg(MathHelper.atan2(offset.x, offset.z))); + } + + } + public static int entityRandom(Entity entity, int maxValue) { return (System.identityHashCode(entity) * 31) % maxValue; } diff --git a/src/main/java/com/simibubi/create/content/curiosities/weapons/PotatoProjectileRenderer.java b/src/main/java/com/simibubi/create/content/curiosities/weapons/PotatoProjectileRenderer.java index 4a234782a..01d2ee95b 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/weapons/PotatoProjectileRenderer.java +++ b/src/main/java/com/simibubi/create/content/curiosities/weapons/PotatoProjectileRenderer.java @@ -26,8 +26,7 @@ public class PotatoProjectileRenderer extends EntityRenderer