mirror of
https://github.com/HbmMods/Hbm-s-Nuclear-Tech-GIT.git
synced 2026-01-25 10:32:49 +00:00
212 lines
7.4 KiB
Java
212 lines
7.4 KiB
Java
package com.hbm.entity.projectile;
|
|
|
|
import com.hbm.items.weapon.sedna.BulletConfig;
|
|
import com.hbm.util.BobMathUtil;
|
|
import com.hbm.util.EntityDamageUtil;
|
|
import com.hbm.util.TrackerUtil;
|
|
|
|
import net.minecraft.entity.Entity;
|
|
import net.minecraft.entity.EntityLivingBase;
|
|
import net.minecraft.util.DamageSource;
|
|
import net.minecraft.util.MathHelper;
|
|
import net.minecraft.util.MovingObjectPosition;
|
|
import net.minecraft.util.Vec3;
|
|
import net.minecraft.world.World;
|
|
import net.minecraft.world.WorldServer;
|
|
import net.minecraftforge.common.util.ForgeDirection;
|
|
|
|
public class EntityBulletBaseMK4 extends EntityThrowableInterp {
|
|
|
|
public BulletConfig config;
|
|
//used for rendering tracers
|
|
public double velocity;
|
|
public double prevVelocity;
|
|
public float damage;
|
|
public int ricochets = 0;
|
|
|
|
public EntityBulletBaseMK4(World world) {
|
|
super(world);
|
|
this.renderDistanceWeight = 10.0D;
|
|
this.setSize(0.5F, 0.5F);
|
|
}
|
|
|
|
public EntityBulletBaseMK4(EntityLivingBase entity, BulletConfig config, float baseDamage, float gunSpread, double sideOffset, double heightOffset, double frontOffset) {
|
|
this(entity.worldObj);
|
|
|
|
this.thrower = entity;
|
|
this.setBulletConfig(config);
|
|
|
|
this.damage = baseDamage * this.config.damageMult;
|
|
|
|
this.setLocationAndAngles(thrower.posX, thrower.posY + thrower.getEyeHeight(), thrower.posZ, thrower.rotationYaw, thrower.rotationPitch);
|
|
|
|
Vec3 offset = Vec3.createVectorHelper(sideOffset, heightOffset, frontOffset);
|
|
offset.rotateAroundX(-this.rotationPitch / 180F * (float) Math.PI);
|
|
offset.rotateAroundY(-this.rotationYaw / 180F * (float) Math.PI);
|
|
|
|
this.posX += offset.xCoord;
|
|
this.posY += offset.yCoord;
|
|
this.posZ += offset.zCoord;
|
|
|
|
this.setPosition(this.posX, this.posY, this.posZ);
|
|
|
|
this.motionX = -MathHelper.sin(this.rotationYaw / 180.0F * (float) Math.PI) * MathHelper.cos(this.rotationPitch / 180.0F * (float) Math.PI);
|
|
this.motionZ = MathHelper.cos(this.rotationYaw / 180.0F * (float) Math.PI) * MathHelper.cos(this.rotationPitch / 180.0F * (float) Math.PI);
|
|
this.motionY = (-MathHelper.sin(this.rotationPitch / 180.0F * (float) Math.PI));
|
|
|
|
this.setThrowableHeading(this.motionX, this.motionY, this.motionZ, 1.0F, this.config.spread + gunSpread);
|
|
}
|
|
|
|
@Override
|
|
protected void entityInit() {
|
|
super.entityInit();
|
|
this.dataWatcher.addObject(3, Integer.valueOf(0));
|
|
}
|
|
|
|
public void setBulletConfig(BulletConfig config) {
|
|
this.config = config;
|
|
this.dataWatcher.updateObject(3, config.id);
|
|
}
|
|
|
|
public BulletConfig getBulletConfig() {
|
|
int id = this.dataWatcher.getWatchableObjectInt(3);
|
|
if(id < 0 || id > BulletConfig.configs.size()) return null;
|
|
return BulletConfig.configs.get(id);
|
|
}
|
|
|
|
@Override
|
|
public void onUpdate() {
|
|
|
|
if(config == null) config = this.getBulletConfig();
|
|
|
|
if(config == null){
|
|
this.setDead();
|
|
return;
|
|
}
|
|
|
|
this.prevPosX = this.posX;
|
|
this.prevPosY = this.posY;
|
|
this.prevPosZ = this.posZ;
|
|
|
|
super.onUpdate();
|
|
|
|
double dX = this.posX - this.prevPosX;
|
|
double dY = this.posY - this.prevPosY;
|
|
double dZ = this.posZ - this.prevPosZ;
|
|
|
|
this.prevVelocity = this.velocity;
|
|
this.velocity = Math.sqrt(dX * dX + dY * dY + dZ * dZ);
|
|
|
|
if(!this.onGround && velocity > 0) {
|
|
|
|
float hyp = MathHelper.sqrt_double(dX * dX + dZ * dZ);
|
|
this.rotationYaw = (float) (Math.atan2(dX, dZ) * 180.0D / Math.PI);
|
|
|
|
for(this.rotationPitch = (float) (Math.atan2(dY, (double) hyp) * 180.0D / Math.PI); this.rotationPitch - this.prevRotationPitch < -180.0F; this.prevRotationPitch -= 360.0F);
|
|
|
|
while(this.rotationPitch - this.prevRotationPitch >= 180.0F) this.prevRotationPitch += 360.0F;
|
|
while(this.rotationYaw - this.prevRotationYaw < -180.0F) this.prevRotationYaw -= 360.0F;
|
|
while(this.rotationYaw - this.prevRotationYaw >= 180.0F) this.prevRotationYaw += 360.0F;
|
|
}
|
|
|
|
if(!worldObj.isRemote && this.ticksExisted > config.expires) this.setDead();
|
|
|
|
if(this.config.onUpdate != null) this.config.onUpdate.accept(this);
|
|
}
|
|
|
|
@Override
|
|
public void setDead() {
|
|
super.setDead();
|
|
|
|
//send a teleport on collision so that the bullets are forced to move even if their lifetime is only 1 tick, letting them render
|
|
if(worldObj instanceof WorldServer) TrackerUtil.sendTeleport((WorldServer) worldObj, this);
|
|
}
|
|
|
|
@Override
|
|
protected void onImpact(MovingObjectPosition mop) {
|
|
if(!worldObj.isRemote) {
|
|
|
|
if(this.config.onImpact != null) this.config.onImpact.accept(this, mop);
|
|
|
|
if(this.isDead) return;
|
|
|
|
if(mop.typeOfHit == mop.typeOfHit.BLOCK) {
|
|
|
|
ForgeDirection dir = ForgeDirection.getOrientation(mop.sideHit);
|
|
Vec3 face = Vec3.createVectorHelper(dir.offsetX, dir.offsetY, dir.offsetZ);
|
|
Vec3 vel = Vec3.createVectorHelper(motionX, motionY, motionZ).normalize();
|
|
|
|
double angle = Math.abs(BobMathUtil.getCrossAngle(vel, face) - 90);
|
|
|
|
if(angle <= config.ricochetAngle) {
|
|
|
|
this.ricochets++;
|
|
if(this.ricochets > this.config.maxRicochetCount) {
|
|
this.setPosition(mop.hitVec.xCoord, mop.hitVec.yCoord, mop.hitVec.zCoord);
|
|
this.setDead();
|
|
}
|
|
|
|
switch(mop.sideHit) {
|
|
case 0: case 1: motionY *= -1; break;
|
|
case 2: case 3: motionZ *= -1; break;
|
|
case 4: case 5: motionX *= -1; break;
|
|
}
|
|
worldObj.playSoundAtEntity(this, "hbm:weapon.ricochet", 0.25F, 1.0F);
|
|
this.setPosition(mop.hitVec.xCoord, mop.hitVec.yCoord, mop.hitVec.zCoord);
|
|
//send a teleport so the ricochet is more accurate instead of the interp smoothing fucking everything up
|
|
if(worldObj instanceof WorldServer) TrackerUtil.sendTeleport((WorldServer) worldObj, this);
|
|
return;
|
|
|
|
} else {
|
|
this.setPosition(mop.hitVec.xCoord, mop.hitVec.yCoord, mop.hitVec.zCoord);
|
|
this.setDead();
|
|
}
|
|
}
|
|
|
|
if(mop.typeOfHit == mop.typeOfHit.ENTITY) {
|
|
Entity entity = mop.entityHit;
|
|
|
|
if(entity instanceof EntityLivingBase && ((EntityLivingBase) entity).getHealth() <= 0) {
|
|
return;
|
|
}
|
|
|
|
DamageSource damageCalc = this.config.getDamage(this, getThrower(), false);
|
|
|
|
if(!(entity instanceof EntityLivingBase)) {
|
|
EntityDamageUtil.attackEntityFromIgnoreIFrame(entity, damageCalc, this.damage);
|
|
return;
|
|
}
|
|
|
|
EntityLivingBase living = (EntityLivingBase) entity;
|
|
float prevHealth = living.getHealth();
|
|
|
|
if(this.config.armorPiercingPercent == 0) {
|
|
EntityDamageUtil.attackEntityFromIgnoreIFrame(entity, damageCalc, this.damage);
|
|
} else {
|
|
DamageSource damagePiercing = this.config.getDamage(this, getThrower(), true);
|
|
EntityDamageUtil.attackArmorPiercing(living, damageCalc, damagePiercing, this.damage, this.config.armorPiercingPercent);
|
|
}
|
|
|
|
float newHealth = living.getHealth();
|
|
|
|
if(this.config.damageFalloffByPen) this.damage -= Math.max(prevHealth - newHealth, 0);
|
|
if(!this.doesPenetrate() || this.damage < 0) {
|
|
this.setPosition(mop.hitVec.xCoord, mop.hitVec.yCoord, mop.hitVec.zCoord);
|
|
this.setDead();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
@Override protected double headingForceMult() { return 1D; }
|
|
@Override public double getGravityVelocity() { return this.config.gravity; }
|
|
@Override protected double motionMult() { return this.config.velocity; }
|
|
@Override protected float getAirDrag() { return 1F; }
|
|
@Override protected float getWaterDrag() { return 1F; }
|
|
|
|
@Override public boolean doesImpactEntities() { return this.config.impactsEntities; }
|
|
@Override public boolean doesPenetrate() { return this.config.doesPenetrate; }
|
|
@Override public boolean isSpectral() { return this.config.isSpectral; }
|
|
@Override public int selfDamageDelay() { return this.config.selfDamageDelay; }
|
|
}
|