mirror of
https://github.com/HbmMods/Hbm-s-Nuclear-Tech-GIT.git
synced 2026-01-25 10:32:49 +00:00
SPAS spent shells, fixed lighting and wobblyness
This commit is contained in:
parent
917e842efc
commit
b0bf2b6511
@ -5,6 +5,7 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
import com.hbm.lib.HbmCollection.EnumGunManufacturer;
|
||||
import com.hbm.particle.SpentCasingConfig;
|
||||
import com.hbm.render.anim.BusAnimation;
|
||||
import com.hbm.render.anim.HbmAnimations.AnimType;
|
||||
import com.hbm.render.util.RenderScreenOverlay.Crosshair;
|
||||
@ -77,7 +78,7 @@ public class GunConfiguration implements Cloneable {
|
||||
public Crosshair crosshair;
|
||||
|
||||
//casing eject behavior
|
||||
//public Optional<SpentCasingConfig> casingConfig = Optional.empty();
|
||||
public SpentCasingConfig casingConfig = null;
|
||||
|
||||
public static final int MODE_NORMAL = 0;
|
||||
public static final int MODE_RELEASE = 1;
|
||||
|
||||
@ -12,6 +12,9 @@ import com.hbm.items.ItemAmmoEnums.Ammo12Gauge;
|
||||
import com.hbm.items.ModItems;
|
||||
import com.hbm.lib.HbmCollection;
|
||||
import com.hbm.lib.HbmCollection.EnumGunManufacturer;
|
||||
import com.hbm.particle.SpentCasingConfig;
|
||||
import com.hbm.particle.SpentCasingConfig.CasingType;
|
||||
import com.hbm.particle.SpentCasingConfigBuilder;
|
||||
import com.hbm.potion.HbmPotion;
|
||||
import com.hbm.render.anim.BusAnimation;
|
||||
import com.hbm.render.anim.BusAnimationKeyframe;
|
||||
@ -22,9 +25,38 @@ import com.hbm.render.util.RenderScreenOverlay.Crosshair;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.potion.PotionEffect;
|
||||
import net.minecraft.util.Vec3;
|
||||
|
||||
public class Gun12GaugeFactory {
|
||||
|
||||
static final SpentCasingConfig CASING_SPAS, CASING_SPAS_ALT, CASING_BENELLI, CASING_UBOINIK, CASING_SSG;
|
||||
|
||||
static
|
||||
{
|
||||
final SpentCasingConfigBuilder CASING_12G_BUILDER = new SpentCasingConfigBuilder("", CasingType.SHOTGUN, false)
|
||||
.setScaleX(1.5f).setScaleY(1.5f).setScaleZ(1.5f);
|
||||
CASING_SPAS = CASING_12G_BUILDER.setRegistryName("spas12").setInitialMotion(Vec3.createVectorHelper(-0.4, 0.1, 0))
|
||||
.setPosOffset(Vec3.createVectorHelper(-0.35, 0, 0.5)).setPitchFactor(0.03f).setYawFactor(0.01f)
|
||||
.setSmokeChance(0).setDelay(10)
|
||||
.build();
|
||||
|
||||
CASING_SPAS_ALT = CASING_12G_BUILDER.setRegistryName("spas12alt").setCasingAmount(2)
|
||||
.build();
|
||||
|
||||
CASING_BENELLI = CASING_12G_BUILDER.setRegistryName("benelli").setCasingAmount(1).setDelay(0)
|
||||
.setInitialMotion(Vec3.createVectorHelper(-0.3, 1, 0))
|
||||
.build();
|
||||
|
||||
CASING_UBOINIK = CASING_12G_BUILDER.setRegistryName("uboinik").setOverrideColor(true)
|
||||
.setBlueOverride(255).setPosOffset(Vec3.createVectorHelper(-0.35, -0.3, 0.5))
|
||||
.build();
|
||||
|
||||
CASING_SSG = CASING_12G_BUILDER.setRegistryName("ssg").setBlueOverride(0).setRedOverride(255).setCasingAmount(2)
|
||||
.setPosOffset(Vec3.createVectorHelper(0.8, 0, 0)).setInitialMotion(Vec3.createVectorHelper(0.2, 0, -0.2))
|
||||
.setPitchFactor(0.05f).setYawFactor(0.02f)
|
||||
.build();
|
||||
}
|
||||
|
||||
public static GunConfiguration getSpas12Config() {
|
||||
|
||||
GunConfiguration config = new GunConfiguration();
|
||||
@ -66,6 +98,8 @@ public class Gun12GaugeFactory {
|
||||
)
|
||||
);
|
||||
|
||||
config.casingConfig = CASING_SPAS;
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
|
||||
@ -15,9 +15,11 @@ import com.hbm.interfaces.IItemHUD;
|
||||
import com.hbm.inventory.RecipesCommon.ComparableStack;
|
||||
import com.hbm.items.IEquipReceiver;
|
||||
import com.hbm.lib.HbmCollection;
|
||||
import com.hbm.main.MainRegistry;
|
||||
import com.hbm.packet.GunAnimationPacket;
|
||||
import com.hbm.packet.GunButtonPacket;
|
||||
import com.hbm.packet.PacketDispatcher;
|
||||
import com.hbm.particle.SpentCasingConfig;
|
||||
import com.hbm.render.anim.BusAnimation;
|
||||
import com.hbm.render.anim.HbmAnimations.AnimType;
|
||||
import com.hbm.render.util.RenderScreenOverlay;
|
||||
@ -208,6 +210,9 @@ public class ItemGunBase extends Item implements IHoldableWeapon, IItemHUD, IEqu
|
||||
}
|
||||
|
||||
world.playSoundAtEntity(player, mainConfig.firingSound, 1.0F, mainConfig.firingPitch);
|
||||
|
||||
if(mainConfig.casingConfig != null && !mainConfig.casingConfig.isAfterReload())
|
||||
spawnCasing(player, mainConfig.casingConfig, stack);
|
||||
}
|
||||
|
||||
//unlike fire(), being called does not automatically imply success, some things may still have to be handled before spawning the projectile
|
||||
@ -239,6 +244,9 @@ public class ItemGunBase extends Item implements IHoldableWeapon, IItemHUD, IEqu
|
||||
}
|
||||
|
||||
world.playSoundAtEntity(player, altConfig.firingSound, 1.0F, altConfig.firingPitch);
|
||||
|
||||
if(altConfig.casingConfig != null)
|
||||
spawnCasing(player, altConfig.casingConfig, stack);
|
||||
}
|
||||
|
||||
//spawns the actual projectile, can be overridden to change projectile entity
|
||||
@ -319,6 +327,9 @@ public class ItemGunBase extends Item implements IHoldableWeapon, IItemHUD, IEqu
|
||||
if(hasLoaded && mainConfig.reloadSoundEnd)
|
||||
world.playSoundAtEntity(player, mainConfig.reloadSound, 1.0F, 1.0F);
|
||||
|
||||
if(mainConfig.casingConfig != null && mainConfig.casingConfig.isAfterReload())
|
||||
spawnCasing(player, mainConfig.casingConfig, stack);
|
||||
|
||||
InventoryUtil.tryConsumeAStack(player.inventory.mainInventory, 0, player.inventory.mainInventory.length, ammo);
|
||||
} else {
|
||||
setReloadCycle(stack, getReloadCycle(stack) - 1);
|
||||
@ -692,4 +703,17 @@ public class ItemGunBase extends Item implements IHoldableWeapon, IItemHUD, IEqu
|
||||
player.worldObj.playSoundAtEntity(player, mainConfig.equipSound, 1, 1);
|
||||
}
|
||||
}
|
||||
|
||||
protected static void spawnCasing(Entity entity, SpentCasingConfig config, ItemStack stack) {
|
||||
NBTTagCompound data = new NBTTagCompound();
|
||||
data.setString("type", "casing");
|
||||
data.setDouble("posX", entity.posX);
|
||||
data.setDouble("posY", entity.posY + entity.getEyeHeight());
|
||||
data.setDouble("posZ", entity.posZ);
|
||||
data.setFloat("pitch", (float) Math.toRadians(entity.rotationPitch));
|
||||
data.setFloat("yaw", (float) Math.toRadians(entity.rotationYaw));
|
||||
data.setBoolean("crouched", entity.isSneaking());
|
||||
data.setString("name", config.getRegistryName());
|
||||
MainRegistry.proxy.effectNT(data);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1789,6 +1789,12 @@ public class ClientProxy extends ServerProxy {
|
||||
|
||||
RenderOverhead.queuedMarkers.put(new BlockPos(x, y, z), new Marker(color).setDist(dist).setExpire(expires > 0 ? System.currentTimeMillis() + expires : 0).withLabel(label.isEmpty() ? null : label));
|
||||
}
|
||||
|
||||
if("casing".equals(type)) {
|
||||
SpentCasingConfig casingConfig = SpentCasingConfig.get(data.getString("name"));
|
||||
for(int i = 0; i < casingConfig.getCasingAmount(); i++)
|
||||
casingConfig.spawnCasing(man, world, x, y, z, data.getFloat("pitch"), data.getFloat("yaw"), data.getBoolean("crouched"));
|
||||
}
|
||||
}
|
||||
|
||||
private HashMap<Integer, Long> vanished = new HashMap();
|
||||
|
||||
@ -865,6 +865,7 @@ public class ResourceManager {
|
||||
|
||||
//Projectiles
|
||||
public static final IModelCustom projectiles = new HFRWavefrontObject(new ResourceLocation(RefStrings.MODID, "models/projectiles/projectiles.obj"));
|
||||
public static final IModelCustom casings = new HFRWavefrontObject(new ResourceLocation(RefStrings.MODID, "models/effect/casings.obj"));
|
||||
|
||||
//Bomber
|
||||
public static final IModelCustom dornier = AdvancedModelLoader.loadModel(new ResourceLocation(RefStrings.MODID, "models/dornier.obj"));
|
||||
@ -990,6 +991,7 @@ public class ResourceManager {
|
||||
public static final ResourceLocation rocket_mirv_tex = new ResourceLocation(RefStrings.MODID, "textures/models/projectiles/rocket_mirv.png");
|
||||
public static final ResourceLocation mini_nuke_tex = new ResourceLocation(RefStrings.MODID, "textures/models/projectiles/mini_nuke.png");
|
||||
public static final ResourceLocation mini_mirv_tex = new ResourceLocation(RefStrings.MODID, "textures/models/projectiles/mini_mirv.png");
|
||||
public static final ResourceLocation casings_tex = new ResourceLocation(RefStrings.MODID, "textures/particle/casings.png");
|
||||
|
||||
//Bomber
|
||||
public static final ResourceLocation dornier_0_tex = new ResourceLocation(RefStrings.MODID, "textures/models/dornier_0.png");
|
||||
|
||||
209
src/main/java/com/hbm/particle/ParticleSpentCasing.java
Normal file
209
src/main/java/com/hbm/particle/ParticleSpentCasing.java
Normal file
@ -0,0 +1,209 @@
|
||||
package com.hbm.particle;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL12;
|
||||
|
||||
import com.hbm.main.ResourceManager;
|
||||
import com.hbm.util.Tuple.Pair;
|
||||
|
||||
import cpw.mods.fml.relauncher.Side;
|
||||
import cpw.mods.fml.relauncher.SideOnly;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.particle.EntityFX;
|
||||
import net.minecraft.client.renderer.RenderHelper;
|
||||
import net.minecraft.client.renderer.Tessellator;
|
||||
import net.minecraft.client.renderer.texture.TextureManager;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.util.Vec3;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
public class ParticleSpentCasing extends EntityFX
|
||||
{
|
||||
private static float dScale = 0.05F, smokeJitter = 0.025F, smokeAccel = 0.5F;
|
||||
private static byte maxSmokeGen = 60, maxSmokeLife = 120;
|
||||
|
||||
private final List<Pair<Vec3, Double>> smokeNodes = new ArrayList();
|
||||
|
||||
private final TextureManager textureManager;
|
||||
|
||||
private final SpentCasingConfig config;
|
||||
private boolean smoke;
|
||||
|
||||
private float momentumPitch, momentumYaw;
|
||||
private boolean onGroundPreviously = false;
|
||||
private double maxHeight;
|
||||
|
||||
public ParticleSpentCasing(TextureManager textureManager, World world, double x, double y, double z, double mx, double my, double mz, float momentumPitch, float momentumYaw, SpentCasingConfig config) {
|
||||
super(world, x, y, z, 0, 0, 0);
|
||||
this.textureManager = textureManager;
|
||||
this.momentumPitch = momentumPitch;
|
||||
this.momentumYaw = momentumYaw;
|
||||
this.config = config;
|
||||
|
||||
particleMaxAge = 240;
|
||||
// smoke = config.getSmokeChance() == 0 ? true
|
||||
// : config.getSmokeChance() < 0 ? false
|
||||
// : rand.nextInt(config.getSmokeChance()) == 0;
|
||||
|
||||
motionX = mx;
|
||||
motionY = my;
|
||||
motionZ = mz;
|
||||
|
||||
particleGravity = 8f;
|
||||
|
||||
maxHeight = y;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getFXLayer() {
|
||||
return 3;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUpdate() {
|
||||
super.onUpdate();
|
||||
|
||||
if(motionY > 0 && posY > maxHeight)
|
||||
maxHeight = posY;
|
||||
|
||||
if(!onGroundPreviously && onGround)
|
||||
tryPlayBounceSound();
|
||||
|
||||
// TODO Bounce factor in config
|
||||
if(!onGroundPreviously && onGround) {
|
||||
|
||||
onGroundPreviously = true;
|
||||
motionY = Math.log10(maxHeight - posY + 2);
|
||||
momentumPitch = (float) rand.nextGaussian() * config.getPitchFactor();
|
||||
momentumYaw = (float) rand.nextGaussian() * config.getYawFactor();
|
||||
maxHeight = posY;
|
||||
|
||||
} else if(onGroundPreviously && !onGround) {
|
||||
onGroundPreviously = false;
|
||||
}
|
||||
|
||||
// if (particleAge > maxSmokeLife && !smokeNodes.isEmpty())
|
||||
// smokeNodes.clear();
|
||||
|
||||
// if (smoke && particleAge <= maxSmokeLife)
|
||||
// {
|
||||
// final double side = (rotationYaw - prevRotationYaw) * 0.1D;
|
||||
// final Vec3 prev = Vec3.createVectorHelper(motionX, motionY, motionZ);
|
||||
// prev.rotateAroundY((float) Math.toRadians(rotationYaw));
|
||||
//
|
||||
// for (Pair<EasyLocation, Double> pair : smokeNodes)
|
||||
// {
|
||||
// final EasyLocation node = pair.getKey();
|
||||
//
|
||||
// node.posX += prev.xCoord * smokeAccel + rand.nextGaussian() * smokeJitter + side;
|
||||
// node.posY += prev.yCoord + smokeAccel;
|
||||
// node.posZ += prev.zCoord * smokeAccel + rand.nextGaussian() * smokeJitter;
|
||||
// }
|
||||
//
|
||||
// if (particleAge < maxSmokeGen || inWater)
|
||||
// {
|
||||
// final double alpha = (particleAge / 20d);
|
||||
// smokeNodes.add(new Pair<EasyLocation, Double>(EasyLocation.getZeroLocation(), alpha));
|
||||
// }
|
||||
// }
|
||||
|
||||
prevRotationPitch = rotationPitch;
|
||||
prevRotationYaw = rotationYaw;
|
||||
|
||||
// if (motionY > gravity && !onGround)
|
||||
// motionY += gravity;
|
||||
// if (motionY < -0.75)
|
||||
// motionY = -0.75;
|
||||
|
||||
if(onGround)
|
||||
rotationPitch = 0;
|
||||
else {
|
||||
rotationPitch += momentumPitch;
|
||||
rotationYaw += momentumYaw;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderParticle(Tessellator tessellator, float interp, float x, float y, float z, float tx, float tz) {
|
||||
|
||||
GL11.glPushMatrix();
|
||||
RenderHelper.enableStandardItemLighting();
|
||||
GL11.glEnable(GL11.GL_CULL_FACE);
|
||||
GL11.glShadeModel(GL11.GL_SMOOTH);
|
||||
GL11.glEnable(GL12.GL_RESCALE_NORMAL);
|
||||
|
||||
textureManager.bindTexture(ResourceManager.casings_tex);
|
||||
|
||||
EntityPlayer player = Minecraft.getMinecraft().thePlayer;
|
||||
double dX = player.lastTickPosX + (player.posX - player.lastTickPosX) * (double)interp;
|
||||
double dY = player.lastTickPosY + (player.posY - player.lastTickPosY) * (double)interp;
|
||||
double dZ = player.lastTickPosZ + (player.posZ - player.lastTickPosZ) * (double)interp;
|
||||
|
||||
GL11.glTranslated(prevPosX + (posX - prevPosX) * interp - dX, prevPosY + (posY - prevPosY) * interp - dY - this.height / 4, prevPosZ + (posZ - prevPosZ) * interp - dZ);
|
||||
|
||||
GL11.glScalef(dScale, dScale, dScale);
|
||||
|
||||
GL11.glRotatef(180 - rotationYaw, 0, 1, 0);
|
||||
GL11.glRotatef(-rotationPitch, 1, 0, 0);
|
||||
|
||||
GL11.glScalef(config.getScaleX(), config.getScaleY(), config.getScaleZ());
|
||||
|
||||
if(config.doesOverrideColor())
|
||||
GL11.glColor3b((byte) config.getRedOverride(), (byte) config.getGreenOverride(), (byte) config.getBlueOverride());
|
||||
|
||||
ResourceManager.casings.renderPart(config.getCasingType().objName);
|
||||
GL11.glDisable(GL12.GL_RESCALE_NORMAL);
|
||||
|
||||
/*if(!smokeNodes.isEmpty()) {
|
||||
tessellator.startDrawingQuads();
|
||||
tessellator.setNormal(0F, 1F, 0F);
|
||||
|
||||
for(int i = 0; i < smokeNodes.size() - 1; i++) {
|
||||
final Pair<Vec3, Double> node = smokeNodes.get(i), past = smokeNodes.get(i + 1);
|
||||
final Vec3 nodeLoc = node.getKey(), pastLoc = past.getKey();
|
||||
final float nodeAlpha = node.getValue().floatValue(), pastAlpha = past.getValue().floatValue(), scale = config.getScaleX();
|
||||
|
||||
tessellator.setColorRGBA_F(1F, 1F, 1F, nodeAlpha);
|
||||
tessellator.addVertex(nodeLoc.xCoord, nodeLoc.yCoord, nodeLoc.zCoord);
|
||||
tessellator.setColorRGBA_F(1F, 1F, 1F, 0F);
|
||||
tessellator.addVertex(nodeLoc.xCoord + scale, nodeLoc.yCoord, nodeLoc.zCoord);
|
||||
tessellator.setColorRGBA_F(1F, 1F, 1F, 0F);
|
||||
tessellator.addVertex(pastLoc.xCoord + scale, pastLoc.yCoord, pastLoc.zCoord);
|
||||
tessellator.setColorRGBA_F(1F, 1F, 1F, pastAlpha);
|
||||
tessellator.addVertex(pastLoc.xCoord, pastLoc.yCoord, pastLoc.zCoord);
|
||||
|
||||
tessellator.setColorRGBA_F(1F, 1F, 1F, nodeAlpha);
|
||||
tessellator.addVertex(nodeLoc.xCoord, nodeLoc.yCoord, nodeLoc.zCoord);
|
||||
tessellator.setColorRGBA_F(1F, 1F, 1F, 0F);
|
||||
tessellator.addVertex(nodeLoc.xCoord - scale, nodeLoc.yCoord, nodeLoc.zCoord);
|
||||
tessellator.setColorRGBA_F(1F, 1F, 1F, 0F);
|
||||
tessellator.addVertex(pastLoc.xCoord - scale, pastLoc.yCoord, pastLoc.zCoord);
|
||||
tessellator.setColorRGBA_F(1F, 1F, 1F, pastAlpha);
|
||||
tessellator.addVertex(pastLoc.xCoord, pastLoc.yCoord, pastLoc.zCoord);
|
||||
}
|
||||
|
||||
GL11.glAlphaFunc(GL11.GL_GREATER, 0F);
|
||||
GL11.glEnable(GL11.GL_BLEND);
|
||||
GL11.glDisable(GL11.GL_TEXTURE_2D);
|
||||
tessellator.draw();
|
||||
GL11.glEnable(GL11.GL_TEXTURE_2D);
|
||||
GL11.glDisable(GL11.GL_BLEND);
|
||||
GL11.glAlphaFunc(GL11.GL_GEQUAL, 0.1F);
|
||||
}*/
|
||||
|
||||
RenderHelper.disableStandardItemLighting();
|
||||
GL11.glShadeModel(GL11.GL_FLAT);
|
||||
GL11.glPopMatrix();
|
||||
}
|
||||
|
||||
private void tryPlayBounceSound() {
|
||||
|
||||
if(!config.getBounceSound().isEmpty()) {
|
||||
worldObj.playSoundAtEntity(this, config.getBounceSound(), 2, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
323
src/main/java/com/hbm/particle/SpentCasingConfig.java
Normal file
323
src/main/java/com/hbm/particle/SpentCasingConfig.java
Normal file
@ -0,0 +1,323 @@
|
||||
package com.hbm.particle;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Random;
|
||||
|
||||
import org.lwjgl.util.vector.Matrix4f;
|
||||
import org.lwjgl.util.vector.Vector3f;
|
||||
import org.lwjgl.util.vector.Vector4f;
|
||||
|
||||
import com.google.common.annotations.Beta;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.texture.TextureManager;
|
||||
import net.minecraft.util.Vec3;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
@Beta
|
||||
public class SpentCasingConfig {
|
||||
|
||||
private static final Map<String, SpentCasingConfig> CONFIG_MAP = new HashMap<String, SpentCasingConfig>();
|
||||
private static final Random RANDOM = new Random();
|
||||
|
||||
public enum CasingType {
|
||||
BRASS_STRAIGHT_WALL("Straight"),
|
||||
BRASS_BOTTLENECK("Bottleneck"),
|
||||
SHOTGUN("Shotgun"),
|
||||
AR2("AR2");
|
||||
|
||||
public final String objName;
|
||||
|
||||
private CasingType(String objName) {
|
||||
this.objName = objName;
|
||||
}
|
||||
}
|
||||
|
||||
/**Unique name used for map lookup.**/
|
||||
private final String registryName;
|
||||
/**Change position of the ejecting shell.**/
|
||||
private final Vec3 posOffset;
|
||||
/**Set initial motion after ejecting.**/
|
||||
private final Vec3 initialMotion;
|
||||
/**Multipliers for random pitch and yaw.**/
|
||||
private final float pitchFactor, yawFactor;
|
||||
/**Rescale the sprite to match the approximate scale of the rounds.**/
|
||||
private final float scaleX, scaleY, scaleZ;
|
||||
/**Overrides for the sprite colors.**/
|
||||
private final int redOverride, greenOverride, blueOverride;
|
||||
/**Whether or not to override the default sprite color scheme.**/
|
||||
private final boolean overrideColor;
|
||||
/**The type of casing.**/
|
||||
private final CasingType casingType;
|
||||
/**Amount of casings to spawn per event. Default 1.**/
|
||||
private final byte casingAmount;
|
||||
/**If the casing(s) should be spawned after reloading, instead of after firing.**/
|
||||
private final boolean afterReload;
|
||||
/**Sound effect for bouncing. Make empty string to have no sound.**/
|
||||
private final String bounceSound;
|
||||
/**Delay before casings are actually spawned**/
|
||||
private final byte delay;
|
||||
/**Chance for the casing to emit smoke. 0 for 100% chance and -1 for it to never make smoke.**/
|
||||
private final byte smokeChance;
|
||||
// TODO Setting to disregard crouch effect and/or another offset specifically for crouching which can be set to null to use the default one
|
||||
public SpentCasingConfig(
|
||||
String registryName, Vec3 posOffset, Vec3 initialMotion, float pitchFactor, float yawFactor,
|
||||
float scaleX, float scaleY, float scaleZ, int redOverride, int greenOverride, int blueOverride,
|
||||
boolean overrideColor, CasingType casingType, byte casingAmount, boolean afterReload, String bounceSound,
|
||||
byte delay, byte smokeChance) {
|
||||
|
||||
this.registryName = registryName;
|
||||
this.posOffset = posOffset;
|
||||
this.initialMotion = initialMotion;
|
||||
this.pitchFactor = pitchFactor;
|
||||
this.yawFactor = yawFactor;
|
||||
this.scaleX = scaleX;
|
||||
this.scaleY = scaleY;
|
||||
this.scaleZ = scaleZ;
|
||||
this.redOverride = redOverride;
|
||||
this.greenOverride = greenOverride;
|
||||
this.blueOverride = blueOverride;
|
||||
this.overrideColor = overrideColor;
|
||||
this.casingType = casingType;
|
||||
this.casingAmount = casingAmount;
|
||||
this.afterReload = afterReload;
|
||||
this.bounceSound = bounceSound;
|
||||
this.delay = delay;
|
||||
this.smokeChance = smokeChance;
|
||||
|
||||
CONFIG_MAP.put(registryName, this);
|
||||
}
|
||||
|
||||
public void spawnCasing(TextureManager textureManager, World world, double x, double y, double z, float pitch, float yaw, boolean crouched) {
|
||||
Vec3 rotatedMotionVec = rotateVector(getInitialMotion(),
|
||||
pitch + (float) RANDOM.nextGaussian() * getPitchFactor(), yaw + (float) RANDOM.nextGaussian() * getPitchFactor(),
|
||||
getPitchFactor(), getPitchFactor());
|
||||
|
||||
ParticleSpentCasing casing = new ParticleSpentCasing(textureManager, world, x,
|
||||
y, z, rotatedMotionVec.xCoord, rotatedMotionVec.yCoord, rotatedMotionVec.zCoord,
|
||||
// 0, 0,
|
||||
(float) (getPitchFactor() * RANDOM.nextGaussian()), (float) (getYawFactor() * RANDOM.nextGaussian()),
|
||||
this);
|
||||
|
||||
offsetCasing(casing, getPosOffset(), pitch, yaw, crouched);
|
||||
|
||||
casing.rotationPitch = (float) Math.toDegrees(pitch);
|
||||
casing.rotationYaw = (float) Math.toDegrees(yaw);
|
||||
|
||||
if(overrideColor)
|
||||
casing.setRBGColorF(redOverride / 255f, blueOverride / 255f, greenOverride / 255f);
|
||||
Minecraft.getMinecraft().effectRenderer.addEffect(casing);
|
||||
}
|
||||
|
||||
// Rotate a position
|
||||
private static void offsetCasing(ParticleSpentCasing casing, Vec3 offset, float pitch, float yaw, boolean crouched)
|
||||
{
|
||||
// // x-axis offset, 0 if crouched to center
|
||||
// final double oX = crouched ? 0 : offset.posX();
|
||||
// // Trigonometric operations, saved for convenience
|
||||
// final double sinP = Math.sin(pitch), cosP = Math.cos(pitch), sinY = Math.sin(yaw), cosY = Math.cos(yaw);
|
||||
// // New offsets
|
||||
// final double newX = oX * cosY - offset.posZ() * sinY,
|
||||
// newY = offset.posY() * cosP - sinP * (oX * sinY + offset.posZ() * cosY),
|
||||
// newZ = offset.posZ() * sinP + cosP * (oX * sinY + offset.posZ() * cosY);
|
||||
//
|
||||
// // Apply
|
||||
// casing.setPosition(casing.posX + newX, casing.posY + newY, casing.posZ + newZ);
|
||||
|
||||
// x-axis offset, 0 if crouched to center
|
||||
final float oX = (float) (crouched ? 0 : offset.xCoord);
|
||||
// Create rotation matrices for pitch and yaw
|
||||
final Matrix4f pitchMatrix = new Matrix4f(), yawMatrix = new Matrix4f();
|
||||
|
||||
pitchMatrix.rotate(pitch, new Vector3f(1, 0, 0)); // modify axis of rotation
|
||||
yawMatrix.rotate(-yaw, new Vector3f(0, 1, 0));
|
||||
|
||||
// Multiply matrices to get combined rotation matrix
|
||||
final Matrix4f rotMatrix = Matrix4f.mul(yawMatrix, pitchMatrix, null);
|
||||
// Create vector representing the offset and apply rotation
|
||||
final Vector4f offsetVector = new Vector4f(oX, (float) offset.yCoord, (float) offset.zCoord, 1); // set fourth coordinate to 1
|
||||
Matrix4f.transform(rotMatrix, offsetVector, offsetVector);
|
||||
final Vector3f result = new Vector3f(); // create result vector
|
||||
result.set(offsetVector.x, offsetVector.y, offsetVector.z); // set result vector using transformed coordinates
|
||||
// Apply rotation
|
||||
casing.setPosition(casing.posX + result.x, casing.posY + result.y, casing.posZ + result.z);
|
||||
}
|
||||
|
||||
// Rotate a vector
|
||||
private static Vec3 rotateVector(Vec3 vector, float pitch, float yaw, float pitchFactor, float yawFactor)
|
||||
{
|
||||
// Apply randomness to vector
|
||||
vector.xCoord += RANDOM.nextGaussian() * yawFactor;
|
||||
vector.yCoord += RANDOM.nextGaussian() * pitchFactor;
|
||||
vector.zCoord += RANDOM.nextGaussian() * yawFactor;
|
||||
|
||||
final Matrix4f pitchMatrix = new Matrix4f(), yawMatrix = new Matrix4f();
|
||||
|
||||
pitchMatrix.setIdentity();
|
||||
pitchMatrix.rotate(-pitch, new Vector3f(1, 0, 0));
|
||||
|
||||
yawMatrix.setIdentity();
|
||||
yawMatrix.rotate(-yaw, new Vector3f(0, 1, 0));
|
||||
|
||||
final Vector4f vector4f = new Vector4f((float) vector.xCoord, (float) vector.yCoord, (float) vector.zCoord, 1);
|
||||
|
||||
Matrix4f.transform(pitchMatrix, vector4f, vector4f);
|
||||
Matrix4f.transform(yawMatrix, vector4f, vector4f);
|
||||
|
||||
return Vec3.createVectorHelper(vector4f.x, vector4f.y, vector4f.z);
|
||||
}
|
||||
|
||||
public Vec3 getPosOffset()
|
||||
{
|
||||
return posOffset;
|
||||
}
|
||||
public Vec3 getInitialMotion()
|
||||
{
|
||||
return Vec3.createVectorHelper(initialMotion.xCoord, initialMotion.yCoord, initialMotion.zCoord);
|
||||
}
|
||||
public float getScaleX()
|
||||
{
|
||||
return scaleX;
|
||||
}
|
||||
public float getScaleY()
|
||||
{
|
||||
return scaleY;
|
||||
}
|
||||
public float getScaleZ()
|
||||
{
|
||||
return scaleZ;
|
||||
}
|
||||
public float getPitchFactor()
|
||||
{
|
||||
return pitchFactor;
|
||||
}
|
||||
public float getYawFactor()
|
||||
{
|
||||
return yawFactor;
|
||||
}
|
||||
public int getRedOverride()
|
||||
{
|
||||
return redOverride;
|
||||
}
|
||||
public int getGreenOverride()
|
||||
{
|
||||
return greenOverride;
|
||||
}
|
||||
public int getBlueOverride()
|
||||
{
|
||||
return blueOverride;
|
||||
}
|
||||
public boolean doesOverrideColor()
|
||||
{
|
||||
return overrideColor;
|
||||
}
|
||||
public CasingType getCasingType()
|
||||
{
|
||||
return casingType;
|
||||
}
|
||||
public byte getCasingAmount()
|
||||
{
|
||||
return casingAmount;
|
||||
}
|
||||
public boolean isAfterReload()
|
||||
{
|
||||
return afterReload;
|
||||
}
|
||||
public String getRegistryName()
|
||||
{
|
||||
return registryName;
|
||||
}
|
||||
public String getBounceSound()
|
||||
{
|
||||
return bounceSound;
|
||||
}
|
||||
public byte getDelay()
|
||||
{
|
||||
return delay;
|
||||
}
|
||||
public byte getSmokeChance()
|
||||
{
|
||||
return smokeChance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert to a new builder for modification.
|
||||
* @param newName The new registry name.
|
||||
* @return A new builder with all the settings inherited from this config, except for registry name.
|
||||
*/
|
||||
public SpentCasingConfigBuilder toBuilder(String newName)
|
||||
{
|
||||
final SpentCasingConfigBuilder builder = new SpentCasingConfigBuilder(newName, casingType, overrideColor);
|
||||
builder.setAfterReload(afterReload).setBlueOverride(blueOverride).setBounceSound(bounceSound).setCasingAmount(casingAmount)
|
||||
.setDelay(delay).setGreenOverride(greenOverride).setInitialMotion(getInitialMotion()).setPitchFactor(pitchFactor)
|
||||
.setPosOffset(getPosOffset()).setRedOverride(redOverride).setScaleX(scaleX).setScaleY(scaleY).setScaleZ(scaleZ)
|
||||
.setSmokeChance(smokeChance).setYawFactor(yawFactor);
|
||||
return builder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return Objects.hash(afterReload, blueOverride, bounceSound, casingAmount, casingType, delay, greenOverride,
|
||||
initialMotion.xCoord, initialMotion.yCoord, initialMotion.zCoord, overrideColor, pitchFactor,
|
||||
posOffset, redOverride, registryName, scaleX, scaleY, scaleZ, smokeChance, yawFactor);
|
||||
}
|
||||
@Override
|
||||
public boolean equals(Object obj)
|
||||
{
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (!(obj instanceof SpentCasingConfig))
|
||||
return false;
|
||||
final SpentCasingConfig other = (SpentCasingConfig) obj;
|
||||
return afterReload == other.afterReload && blueOverride == other.blueOverride
|
||||
&& Objects.equals(bounceSound, other.bounceSound) && casingAmount == other.casingAmount
|
||||
&& casingType == other.casingType && delay == other.delay && greenOverride == other.greenOverride
|
||||
&& Double.doubleToLongBits(initialMotion.xCoord) == Double.doubleToLongBits(other.initialMotion.xCoord)
|
||||
&& Double.doubleToLongBits(initialMotion.yCoord) == Double.doubleToLongBits(other.initialMotion.yCoord)
|
||||
&& Double.doubleToLongBits(initialMotion.zCoord) == Double.doubleToLongBits(other.initialMotion.zCoord)
|
||||
&& overrideColor == other.overrideColor
|
||||
&& Float.floatToIntBits(pitchFactor) == Float.floatToIntBits(other.pitchFactor)
|
||||
&& Objects.equals(posOffset, other.posOffset) && redOverride == other.redOverride
|
||||
&& Objects.equals(registryName, other.registryName)
|
||||
&& Float.floatToIntBits(scaleX) == Float.floatToIntBits(other.scaleX)
|
||||
&& Float.floatToIntBits(scaleY) == Float.floatToIntBits(other.scaleY)
|
||||
&& Float.floatToIntBits(scaleZ) == Float.floatToIntBits(other.scaleZ)
|
||||
&& smokeChance == other.smokeChance
|
||||
&& Float.floatToIntBits(yawFactor) == Float.floatToIntBits(other.yawFactor);
|
||||
}
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
final StringBuilder builder = new StringBuilder();
|
||||
builder.append("SpentCasingConfig [registryName=").append(registryName).append(", posOffset=").append(posOffset)
|
||||
.append(", initialMotion=").append(initialMotion).append(", pitchFactor=").append(pitchFactor)
|
||||
.append(", yawFactor=").append(yawFactor).append(", scaleX=").append(scaleX).append(", scaleY=")
|
||||
.append(scaleY).append(", scaleZ=").append(scaleZ).append(", redOverride=").append(redOverride)
|
||||
.append(", greenOverride=").append(greenOverride).append(", blueOverride=").append(blueOverride)
|
||||
.append(", overrideColor=").append(overrideColor).append(", casingType=").append(casingType)
|
||||
.append(", casingAmount=").append(casingAmount).append(", afterReload=").append(afterReload)
|
||||
.append(", bounceSound=").append(bounceSound).append(", delay=").append(delay).append(", smokeChance=")
|
||||
.append(smokeChance).append("]");
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
public static boolean containsKey(String key)
|
||||
{
|
||||
return CONFIG_MAP.containsKey(key);
|
||||
}
|
||||
|
||||
public static SpentCasingConfig get(String key)
|
||||
{
|
||||
return CONFIG_MAP.get(key);
|
||||
}
|
||||
|
||||
public static Map<String, SpentCasingConfig> getConfigMap()
|
||||
{
|
||||
return ImmutableMap.copyOf(CONFIG_MAP);
|
||||
}
|
||||
|
||||
}
|
||||
377
src/main/java/com/hbm/particle/SpentCasingConfigBuilder.java
Normal file
377
src/main/java/com/hbm/particle/SpentCasingConfigBuilder.java
Normal file
@ -0,0 +1,377 @@
|
||||
package com.hbm.particle;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import com.google.common.annotations.Beta;
|
||||
import com.hbm.main.MainRegistry;
|
||||
import com.hbm.particle.SpentCasingConfig.CasingType;
|
||||
|
||||
import net.minecraft.util.MathHelper;
|
||||
import net.minecraft.util.Vec3;
|
||||
|
||||
@Beta
|
||||
public class SpentCasingConfigBuilder implements Cloneable
|
||||
{
|
||||
/**Unique name used for map lookup.**/
|
||||
private String registryName;
|
||||
/**Change position of the ejecting shell.**/
|
||||
private Vec3 posOffset = Vec3.createVectorHelper(0, 0, 0);
|
||||
/**Set initial motion after ejecting.**/
|
||||
private Vec3 initialMotion = Vec3.createVectorHelper(0, 0, 0);
|
||||
/**Multipliers for random pitch and yaw.**/
|
||||
private float pitchFactor, yawFactor;
|
||||
/**Rescale the sprite to match the approximate scale of the rounds.**/
|
||||
private float scaleX = 1, scaleY = 1, scaleZ = 1;
|
||||
/**Overrides for the sprite colors.**/
|
||||
private int redOverride, greenOverride, blueOverride;
|
||||
/**Whether or not to override the default sprite color scheme.**/
|
||||
private boolean overrideColor;
|
||||
/**The type of casing.**/
|
||||
private CasingType casingType = CasingType.BRASS_STRAIGHT_WALL;
|
||||
/**Amount of casings to spawn per event. Default 1.**/
|
||||
private byte casingAmount = 1;
|
||||
/**If the casing(s) should be spawned after reloading, instead of after firing.**/
|
||||
private boolean afterReload;
|
||||
/**Sound effect for bouncing. Make empty string to have no sound.**/
|
||||
private String bounceSound = "";
|
||||
/**Delay before casings are actually spawned**/
|
||||
private byte delay;
|
||||
/**Chance for the casing to emit smoke. 0 for 100% chance and -1 for it to never make smoke.**/
|
||||
private byte smokeChance = -1;
|
||||
// TODO Setting to disregard crouch effect and/or another offset specifically for crouching which can be set to null to use the default one
|
||||
/**
|
||||
* Constructor with fields for the required bare minimum parameters.<br>
|
||||
* All parameters may overridden using setters at any time at your discretion, however.
|
||||
* @param registryName The unique name for map lookup. Null not permitted, becomes empty string.
|
||||
* @param casingType Type of casing model to use. Null not permitted, defaults to straight wall type.
|
||||
* @param overrideColor Whether or not the config will override the model texture's color.
|
||||
*/
|
||||
public SpentCasingConfigBuilder(String registryName, CasingType casingType, boolean overrideColor) {
|
||||
this.registryName = registryName == null ? "" : registryName;
|
||||
this.casingType = casingType == null ? CasingType.BRASS_STRAIGHT_WALL : casingType;
|
||||
this.overrideColor = overrideColor;
|
||||
}
|
||||
|
||||
public Vec3 getPosOffset() {
|
||||
return posOffset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the relative x, y, z coordinate offset on spawn.
|
||||
* @param posOffset Any ILocationProvider that serves as the offset. Null becomes a zero location.
|
||||
* @return Itself for chaining.
|
||||
*/
|
||||
public SpentCasingConfigBuilder setPosOffset(Vec3 posOffset) {
|
||||
this.posOffset = posOffset == null ? Vec3.createVectorHelper(0, 0, 0) : posOffset;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Vec3 getInitialMotion() {
|
||||
return initialMotion;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the casing's initial relative x, y, z motion on spawn.
|
||||
* @param initialMotion Vector representing the initial motion. Null becomes a zero vector.
|
||||
* @return Itself for chaining.
|
||||
*/
|
||||
public SpentCasingConfigBuilder setInitialMotion(Vec3 initialMotion) {
|
||||
this.initialMotion = initialMotion == null ? Vec3.createVectorHelper(0, 0, 0) : initialMotion;
|
||||
return this;
|
||||
}
|
||||
|
||||
public double getScaleX() {
|
||||
return scaleX;
|
||||
}
|
||||
|
||||
/**
|
||||
* Scale of the model on its x-axis.
|
||||
* @param scaleX The scale/stretch factor of the model on the x-axis.
|
||||
* @return Itself for chaining.
|
||||
*/
|
||||
public SpentCasingConfigBuilder setScaleX(float scaleX) {
|
||||
this.scaleX = scaleX;
|
||||
return this;
|
||||
}
|
||||
|
||||
public double getScaleY() {
|
||||
return scaleY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Scale of the model on its y-axis.
|
||||
* @param scaleY The scale/stretch factor of the model on the y-axis.
|
||||
* @return Itself for chaining.
|
||||
*/
|
||||
public SpentCasingConfigBuilder setScaleY(float scaleY) {
|
||||
this.scaleY = scaleY;
|
||||
return this;
|
||||
}
|
||||
|
||||
public float getScaleZ() {
|
||||
return scaleZ;
|
||||
}
|
||||
|
||||
/**
|
||||
* Scale of the model on its z-axis.
|
||||
* @param scaleZ The scale/stretch of the model on the z-axis.
|
||||
* @return Itself for chaining.
|
||||
*/
|
||||
public SpentCasingConfigBuilder setScaleZ(float scaleZ) {
|
||||
this.scaleZ = scaleZ;
|
||||
return this;
|
||||
}
|
||||
|
||||
public float getPitchFactor() {
|
||||
return pitchFactor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Multiplier for random pitch-related motion. Recommended to keep in the thousanths (0.00X), as even with the hundreths (0.0X) the pitch can get crazy at times.
|
||||
* @param pitchFactor The multiplier.
|
||||
* @return Itself for chaining.
|
||||
*/
|
||||
public SpentCasingConfigBuilder setPitchFactor(float pitchFactor) {
|
||||
this.pitchFactor = pitchFactor;
|
||||
return this;
|
||||
}
|
||||
|
||||
public float getYawFactor() {
|
||||
return yawFactor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Multiplier for random yaw-related motion. Recommended to keep in the thousanths (0.00X), as even with the hundreths (0.0X) the yaw can get crazy at times.
|
||||
* @param yawFactor The multiplier.
|
||||
* @return Itself for chaining.
|
||||
*/
|
||||
public SpentCasingConfigBuilder setYawFactor(float yawFactor) {
|
||||
this.yawFactor = yawFactor;
|
||||
return this;
|
||||
}
|
||||
|
||||
public int getRedOverride() {
|
||||
return redOverride;
|
||||
}
|
||||
|
||||
/**
|
||||
* Red color override. Clamped between 0-255, but I don't know how it actually works on the receiving end, so feel free to change.
|
||||
* @param redOverride Red color override.
|
||||
* @return Itself for chaining.
|
||||
*/
|
||||
public SpentCasingConfigBuilder setRedOverride(int redOverride) {
|
||||
this.redOverride = MathHelper.clamp_int(redOverride, 0, 255);
|
||||
return this;
|
||||
}
|
||||
|
||||
public int getGreenOverride() {
|
||||
return greenOverride;
|
||||
}
|
||||
|
||||
/**
|
||||
* Green color override. Clamped between 0-255, but I don't know how it actually works on the receiving end, so feel free to change.
|
||||
* @param greenOverride Green color override.
|
||||
* @return Itself for chaining.
|
||||
*/
|
||||
public SpentCasingConfigBuilder setGreenOverride(int greenOverride) {
|
||||
this.greenOverride = MathHelper.clamp_int(greenOverride, 0, 255);
|
||||
return this;
|
||||
}
|
||||
|
||||
public int getBlueOverride() {
|
||||
return blueOverride;
|
||||
}
|
||||
|
||||
/**
|
||||
* Blue color override. Clamped between 0-255, but I don't know how it actually works on the receiving end, so feel free to change.
|
||||
* @param blueOverride Blue color override.
|
||||
* @return Itself for chaining.
|
||||
*/
|
||||
public SpentCasingConfigBuilder setBlueOverride(int blueOverride) {
|
||||
this.blueOverride = MathHelper.clamp_int(blueOverride, 0, 255);
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean doesOverrideColor() {
|
||||
return overrideColor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether or not the config will override color. If false, the integer overrides will be ignored.
|
||||
* @param overrideColor True, to use the integer color overrides, false to ignore them.
|
||||
* @return Itself for chaining.
|
||||
*/
|
||||
public SpentCasingConfigBuilder setOverrideColor(boolean overrideColor) {
|
||||
this.overrideColor = overrideColor;
|
||||
return this;
|
||||
}
|
||||
|
||||
public CasingType getCasingType() {
|
||||
return casingType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the model the casing will use.
|
||||
* @param casingType One of the 4 casing model types. Null is not permitted, will have no effect.
|
||||
* @return Itself for chaining.
|
||||
*/
|
||||
public SpentCasingConfigBuilder setCasingType(CasingType casingType) {
|
||||
this.casingType = casingType == null ? this.casingType : casingType;
|
||||
return this;
|
||||
}
|
||||
|
||||
public byte getCasingAmount() {
|
||||
return casingAmount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the amount of casings to spawn. Default is 1.
|
||||
* @param casingAmount Amount of casings to spawn. Clamped to a positive byte (0 - 127).
|
||||
* @return Itself for chaining.
|
||||
*/
|
||||
public SpentCasingConfigBuilder setCasingAmount(int casingAmount) {
|
||||
this.casingAmount = (byte) MathHelper.clamp_int(casingAmount, 0, 127);
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean isAfterReload() {
|
||||
return afterReload;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether or not the casing will be spawned after reloading is done or after firing.
|
||||
* @param afterReload If true, casings will be spawned when reloading, false, they will be spawned after firing.
|
||||
* @return Itself for chaining.
|
||||
*/
|
||||
public SpentCasingConfigBuilder setAfterReload(boolean afterReload) {
|
||||
this.afterReload = afterReload;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getRegistryName() {
|
||||
return registryName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the unique name for the config used in map lookup.<br>
|
||||
* As the real class is self-registering, <i>make sure to set this in reused builders.</i>
|
||||
* @param registryName The registry name to use. Null is not permitted, becomes an empty string.
|
||||
* @return Itself for chaining.
|
||||
*/
|
||||
public SpentCasingConfigBuilder setRegistryName(String registryName) {
|
||||
this.registryName = registryName == null ? "" : registryName;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getBounceSound() {
|
||||
return bounceSound;
|
||||
}
|
||||
|
||||
/**
|
||||
* The sound used when bouncing. If empty, no sound will be made.
|
||||
* @param bounceSound The sound path. Null is not permitted, becomes an empty string.
|
||||
* @return Itself for chaining.
|
||||
*/
|
||||
public SpentCasingConfigBuilder setBounceSound(String bounceSound) {
|
||||
this.bounceSound = bounceSound == null ? "" : bounceSound;
|
||||
return this;
|
||||
}
|
||||
|
||||
public byte getDelay() {
|
||||
return delay;
|
||||
}
|
||||
|
||||
/**
|
||||
* The delay in ticks before spawning.
|
||||
* @param delay Tick spawn delay. Must be nonnegative, otherwise 0.
|
||||
* @return Itself for chaining.
|
||||
*/
|
||||
public SpentCasingConfigBuilder setDelay(int delay) {
|
||||
this.delay = (byte) (delay < 0 ? 0 : delay);
|
||||
return this;
|
||||
}
|
||||
|
||||
public byte getSmokeChance() {
|
||||
return smokeChance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Chance for the casing to emit smoke. 0 for 100% chance and -1 for it to never make smoke.
|
||||
* @param smokeChance Chance to emit smoke. Clamped to a byte.
|
||||
* @return Itself for chaining.
|
||||
*/
|
||||
public SpentCasingConfigBuilder setSmokeChance(int smokeChance) {
|
||||
this.smokeChance = (byte) smokeChance;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs the true immutable config with all settings loaded from this builder.<br>
|
||||
* This builder may be reused as all non-immutable and primitive fields are copied before being passed to the constructor.<br>
|
||||
* The config's constructor is self-registering.
|
||||
* @return The finished config with its settings specified by this builder.
|
||||
*/
|
||||
public SpentCasingConfig build() {
|
||||
return new SpentCasingConfig(registryName, Vec3.createVectorHelper(posOffset.xCoord, posOffset.yCoord, posOffset.zCoord),
|
||||
Vec3.createVectorHelper(initialMotion.xCoord, initialMotion.yCoord, initialMotion.zCoord), pitchFactor,
|
||||
yawFactor, scaleX, scaleY, scaleZ, redOverride, greenOverride, blueOverride, overrideColor, casingType,
|
||||
casingAmount, afterReload, bounceSound, delay, smokeChance);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(afterReload, blueOverride, bounceSound, casingAmount, casingType, delay, greenOverride,
|
||||
initialMotion.xCoord, initialMotion.yCoord, initialMotion.zCoord, overrideColor, pitchFactor,
|
||||
posOffset, redOverride, registryName, scaleX, scaleY, scaleZ, smokeChance, yawFactor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
|
||||
if(this == obj) return true;
|
||||
if(!(obj instanceof SpentCasingConfigBuilder)) return false;
|
||||
|
||||
SpentCasingConfigBuilder other = (SpentCasingConfigBuilder) obj;
|
||||
return afterReload == other.afterReload && blueOverride == other.blueOverride
|
||||
&& Objects.equals(bounceSound, other.bounceSound) && casingAmount == other.casingAmount
|
||||
&& casingType == other.casingType && delay == other.delay && greenOverride == other.greenOverride
|
||||
&& Double.doubleToLongBits(initialMotion.xCoord) == Double.doubleToLongBits(other.initialMotion.xCoord)
|
||||
&& Double.doubleToLongBits(initialMotion.yCoord) == Double.doubleToLongBits(other.initialMotion.yCoord)
|
||||
&& Double.doubleToLongBits(initialMotion.zCoord) == Double.doubleToLongBits(other.initialMotion.zCoord)
|
||||
&& overrideColor == other.overrideColor
|
||||
&& Float.floatToIntBits(pitchFactor) == Float.floatToIntBits(other.pitchFactor)
|
||||
&& Objects.equals(posOffset, other.posOffset) && redOverride == other.redOverride
|
||||
&& Objects.equals(registryName, other.registryName)
|
||||
&& Float.floatToIntBits(scaleX) == Float.floatToIntBits(other.scaleX)
|
||||
&& Float.floatToIntBits(scaleY) == Float.floatToIntBits(other.scaleY)
|
||||
&& Float.floatToIntBits(scaleZ) == Float.floatToIntBits(other.scaleZ)
|
||||
&& smokeChance == other.smokeChance
|
||||
&& Float.floatToIntBits(yawFactor) == Float.floatToIntBits(other.yawFactor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append("SpentCasingConfigBuilder [registryName=").append(registryName).append(", posOffset=")
|
||||
.append(posOffset).append(", initialMotion=").append(initialMotion).append(", pitchFactor=")
|
||||
.append(pitchFactor).append(", yawFactor=").append(yawFactor).append(", scaleX=").append(scaleX)
|
||||
.append(", scaleY=").append(scaleY).append(", scaleZ=").append(scaleZ).append(", redOverride=")
|
||||
.append(redOverride).append(", greenOverride=").append(greenOverride).append(", blueOverride=")
|
||||
.append(blueOverride).append(", overrideColor=").append(overrideColor).append(", casingType=")
|
||||
.append(casingType).append(", casingAmount=").append(casingAmount).append(", afterReload=")
|
||||
.append(afterReload).append(", bounceSound=").append(bounceSound).append(", delay=").append(delay)
|
||||
.append(", smokeChance=").append(smokeChance).append(']');
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpentCasingConfigBuilder clone() {
|
||||
try {
|
||||
return (SpentCasingConfigBuilder) super.clone();
|
||||
} catch(CloneNotSupportedException e) {
|
||||
MainRegistry.logger.catching(e);
|
||||
return new SpentCasingConfigBuilder(registryName, casingType, overrideColor);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
1084
src/main/resources/assets/hbm/models/effect/casings.obj
Normal file
1084
src/main/resources/assets/hbm/models/effect/casings.obj
Normal file
File diff suppressed because it is too large
Load Diff
BIN
src/main/resources/assets/hbm/textures/particle/casings.png
Normal file
BIN
src/main/resources/assets/hbm/textures/particle/casings.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 9.9 KiB |
Loading…
x
Reference in New Issue
Block a user