mirror of
https://github.com/HbmMods/Hbm-s-Nuclear-Tech-GIT.git
synced 2026-01-25 10:32:49 +00:00
295 lines
8.8 KiB
Java
295 lines
8.8 KiB
Java
package com.hbm.entity.effect;
|
|
|
|
import java.util.ArrayList;
|
|
|
|
import cpw.mods.fml.relauncher.Side;
|
|
import cpw.mods.fml.relauncher.SideOnly;
|
|
import net.minecraft.entity.Entity;
|
|
import net.minecraft.nbt.NBTTagCompound;
|
|
import net.minecraft.util.MathHelper;
|
|
import net.minecraft.util.Vec3;
|
|
import net.minecraft.world.World;
|
|
|
|
/*
|
|
* Toroidial Convection Simulation Explosion Effect
|
|
* Tor Ex
|
|
*/
|
|
public class EntityNukeTorex extends Entity {
|
|
|
|
public double coreHeight = 3;
|
|
public double convectionHeight = 3;
|
|
public double torusWidth = 3;
|
|
public double rollerSize = 1;
|
|
public double heat = 1;
|
|
public ArrayList<Cloudlet> cloudlets = new ArrayList();
|
|
public static int cloudletLife = 200;
|
|
|
|
public EntityNukeTorex(World world) {
|
|
super(world);
|
|
this.ignoreFrustumCheck = true;
|
|
}
|
|
|
|
@Override
|
|
protected void entityInit() { }
|
|
|
|
@Override
|
|
public void onUpdate() {
|
|
this.ticksExisted++;
|
|
|
|
int maxAge = 90 * 20;
|
|
|
|
if(worldObj.isRemote) {
|
|
|
|
double range = (torusWidth - rollerSize) * 0.25;
|
|
|
|
if(this.ticksExisted + cloudletLife * 2 < maxAge) {
|
|
|
|
int toSpawn = (int) Math.ceil(10 * getSimulationSpeed());
|
|
|
|
for(int i = 0; i < toSpawn; i++) {
|
|
double y = posY + rand.nextGaussian() - 3; //this.ticksExisted < 60 ? this.posY + this.coreHeight : posY + rand.nextGaussian() - 3;
|
|
Cloudlet cloud = new Cloudlet(posX + rand.nextGaussian() * range, y, posZ + rand.nextGaussian() * range, (float)(rand.nextDouble() * 2D * Math.PI), 0);
|
|
cloud.setScale(1F + this.ticksExisted * 0.001F, 5F);
|
|
cloudlets.add(cloud);
|
|
}
|
|
}
|
|
|
|
int cloudCount = ticksExisted * 3;
|
|
if(ticksExisted < 200) {
|
|
for(int i = 0; i < cloudCount; i++) {
|
|
Vec3 vec = Vec3.createVectorHelper((ticksExisted + rand.nextDouble()) * 2, 0, 0);
|
|
float rot = (float) (Math.PI * 2 * rand.nextDouble());
|
|
vec.rotateAroundY(rot);
|
|
this.cloudlets.add(new Cloudlet(vec.xCoord + posX, worldObj.getHeightValue((int) (vec.xCoord + posX) + 1, (int) (vec.zCoord + posZ)), vec.zCoord + posZ, rot, 0)
|
|
.setScale(5F, 2F)
|
|
.setMotion(0));
|
|
}
|
|
}
|
|
|
|
for(Cloudlet cloud : cloudlets) {
|
|
cloud.update();
|
|
}
|
|
|
|
coreHeight += 0.15;
|
|
torusWidth += 0.05;
|
|
rollerSize = torusWidth * 0.35;
|
|
convectionHeight = coreHeight + rollerSize;
|
|
|
|
int maxHeat = 50;
|
|
heat = maxHeat - Math.pow((maxHeat * this.ticksExisted) / maxAge, 1);
|
|
|
|
cloudlets.removeIf(x -> x.isDead);
|
|
}
|
|
|
|
if(!worldObj.isRemote && this.ticksExisted > maxAge) {
|
|
this.setDead();
|
|
}
|
|
}
|
|
|
|
public double getSimulationSpeed() {
|
|
|
|
if(EntityNukeTorex.this.ticksExisted > 45 * 20) {
|
|
int timeLeft = 1600 - EntityNukeTorex.this.ticksExisted;
|
|
return MathHelper.clamp_double((double) timeLeft / 900D, 0, 1);
|
|
}
|
|
|
|
return 1.0D;
|
|
}
|
|
|
|
public class Cloudlet {
|
|
|
|
public double posX;
|
|
public double posY;
|
|
public double posZ;
|
|
public double prevPosX;
|
|
public double prevPosY;
|
|
public double prevPosZ;
|
|
public double motionX;
|
|
public double motionY;
|
|
public double motionZ;
|
|
public int age;
|
|
public float angle;
|
|
public boolean isDead = false;
|
|
float rangeMod = 1.0F;
|
|
public float colorMod = 1.0F;
|
|
public Vec3 color;
|
|
public Vec3 prevColor;
|
|
|
|
public Cloudlet(double posX, double posY, double posZ, float angle, int age) {
|
|
this.posX = posX;
|
|
this.posY = posY;
|
|
this.posZ = posZ;
|
|
this.age = age;
|
|
this.angle = angle;
|
|
this.rangeMod = 0.3F + rand.nextFloat() * 0.7F;
|
|
this.colorMod = 0.8F + rand.nextFloat() * 0.2F;
|
|
|
|
this.updateColor();
|
|
}
|
|
|
|
private void update() {
|
|
|
|
age++;
|
|
|
|
if(age > cloudletLife) {
|
|
this.isDead = true;
|
|
}
|
|
|
|
this.prevPosX = this.posX;
|
|
this.prevPosY = this.posY;
|
|
this.prevPosZ = this.posZ;
|
|
|
|
Vec3 simPos = Vec3.createVectorHelper(EntityNukeTorex.this.posX - this.posX, 0, EntityNukeTorex.this.posZ - this.posZ);
|
|
double simPosX = EntityNukeTorex.this.posX + simPos.lengthVector();
|
|
double simPosZ = EntityNukeTorex.this.posZ + 0D;
|
|
|
|
Vec3 convection = getConvectionMotion(simPosX, simPosZ);
|
|
Vec3 lift = getLiftMotion(simPosX, simPosZ);
|
|
|
|
double factor = MathHelper.clamp_double((this.posY - EntityNukeTorex.this.posY) / EntityNukeTorex.this.coreHeight, 0, 1);
|
|
this.motionX = convection.xCoord * factor + lift.xCoord * (1D - factor);
|
|
this.motionY = convection.yCoord * factor + lift.yCoord * (1D - factor);
|
|
this.motionZ = convection.zCoord * factor + lift.zCoord * (1D - factor);
|
|
|
|
double mult = this.motionMult * getSimulationSpeed();
|
|
|
|
this.posX += this.motionX * mult;
|
|
this.posY += this.motionY * mult;
|
|
this.posZ += this.motionZ * mult;
|
|
|
|
this.updateColor();
|
|
}
|
|
|
|
/* simulated on a 2D-plane along the X/Y axis */
|
|
private Vec3 getConvectionMotion(double simPosX, double simPosZ) {
|
|
|
|
if(simPosX > EntityNukeTorex.this.posX + torusWidth * 2)
|
|
return Vec3.createVectorHelper(0, 0, 0);
|
|
|
|
/* the position of the torus' outer ring center */
|
|
Vec3 torusPos = Vec3.createVectorHelper(
|
|
(EntityNukeTorex.this.posX + torusWidth),
|
|
(EntityNukeTorex.this.posY + coreHeight),
|
|
EntityNukeTorex.this.posZ);
|
|
|
|
/* the difference between the cloudlet and the torus' ring center */
|
|
Vec3 delta = Vec3.createVectorHelper(torusPos.xCoord - simPosX, torusPos.yCoord - this.posY, torusPos.zCoord - simPosZ);
|
|
|
|
|
|
/* the distance this cloudlet wants to achieve to the torus' ring center */
|
|
double roller = EntityNukeTorex.this.rollerSize * this.rangeMod;
|
|
/* the distance between this cloudlet and the torus' outer ring perimeter */
|
|
double dist = delta.lengthVector() / roller - 1D;
|
|
|
|
/* euler function based on how far the cloudlet is away from the perimeter */
|
|
double func = 1D - Math.pow(Math.E, -dist); // [0;1]
|
|
/* just an approximation, but it's good enough */
|
|
float angle = (float) (func * Math.PI * 0.5D); // [0;90°]
|
|
|
|
/* vector going from the ring center in the direction of the cloudlet, stopping at the perimeter */
|
|
Vec3 rot = Vec3.createVectorHelper(-delta.xCoord / dist, -delta.yCoord / dist, -delta.zCoord / dist);
|
|
/* rotate by the approximate angle */
|
|
rot.rotateAroundZ(angle);
|
|
|
|
/* the direction from the cloudlet to the target position on the perimeter */
|
|
Vec3 motion = Vec3.createVectorHelper(
|
|
torusPos.xCoord + rot.xCoord - simPosX,
|
|
torusPos.yCoord + rot.yCoord - this.posY,
|
|
torusPos.zCoord + rot.zCoord - simPosZ);
|
|
|
|
motion = motion.normalize();
|
|
motion.rotateAroundY(this.angle);
|
|
|
|
return motion;
|
|
}
|
|
|
|
private Vec3 getLiftMotion(double simPosX, double simPosZ) {
|
|
double scale = MathHelper.clamp_double(1D - (simPosX - (EntityNukeTorex.this.posX + torusWidth)), 0, 1);
|
|
|
|
Vec3 motion = Vec3.createVectorHelper(EntityNukeTorex.this.posX - this.posX, (EntityNukeTorex.this.posY + convectionHeight) - this.posY, EntityNukeTorex.this.posZ - this.posZ);
|
|
|
|
motion = motion.normalize();
|
|
motion.xCoord *= scale;
|
|
motion.yCoord *= scale;
|
|
motion.zCoord *= scale;
|
|
|
|
return motion;
|
|
}
|
|
|
|
private void updateColor() {
|
|
this.prevColor = this.color;
|
|
|
|
double exX = EntityNukeTorex.this.posX;
|
|
double exY = EntityNukeTorex.this.posY + EntityNukeTorex.this.coreHeight;
|
|
double exZ = EntityNukeTorex.this.posZ;
|
|
|
|
double distX = exX - posX;
|
|
double distY = exY - posY;
|
|
double distZ = exZ - posZ;
|
|
|
|
double distSq = distX * distX + distY * distY + distZ * distZ;
|
|
distSq /= EntityNukeTorex.this.heat;
|
|
double dist = Math.sqrt(distSq);
|
|
|
|
dist = Math.max(dist, 1);
|
|
double col = 2D / dist;
|
|
|
|
this.color = Vec3.createVectorHelper(
|
|
Math.max(col * 2, 0.25),
|
|
Math.max(col * 1.5, 0.25),
|
|
Math.max(col * 0.5, 0.25)
|
|
);
|
|
}
|
|
|
|
public Vec3 getInterpPos(float interp) {
|
|
return Vec3.createVectorHelper(
|
|
prevPosX + (posX - prevPosX) * interp,
|
|
prevPosY + (posY - prevPosY) * interp,
|
|
prevPosZ + (posZ - prevPosZ) * interp);
|
|
}
|
|
|
|
public Vec3 getInterpColor(float interp) {
|
|
return Vec3.createVectorHelper(
|
|
prevColor.xCoord + (color.xCoord - prevColor.xCoord) * interp,
|
|
prevColor.yCoord + (color.yCoord - prevColor.yCoord) * interp,
|
|
prevColor.zCoord + (color.zCoord - prevColor.zCoord) * interp);
|
|
}
|
|
|
|
public float getAlpha() {
|
|
return 1F - ((float)age / (float)cloudletLife);
|
|
}
|
|
|
|
private float startingScale = 1;
|
|
private float growingScale = 5F;
|
|
|
|
public float getScale() {
|
|
return startingScale + ((float)age / (float)cloudletLife) * growingScale;
|
|
}
|
|
|
|
public Cloudlet setScale(float start, float grow) {
|
|
this.startingScale = start;
|
|
this.growingScale = grow;
|
|
return this;
|
|
}
|
|
|
|
private double motionMult = 1F;
|
|
|
|
public Cloudlet setMotion(double mult) {
|
|
this.motionMult = mult;
|
|
return this;
|
|
}
|
|
}
|
|
|
|
@Override
|
|
protected void readEntityFromNBT(NBTTagCompound nbt) { }
|
|
|
|
@Override
|
|
protected void writeEntityToNBT(NBTTagCompound nbt) { }
|
|
|
|
@Override
|
|
@SideOnly(Side.CLIENT)
|
|
public boolean isInRangeToRenderDist(double distance) {
|
|
return distance < 25000;
|
|
}
|
|
}
|