Add support for shotgun reloading animations

Add support for alternate reload animations when loading from completely empty
Add animations for Samuel The Big Fucking Shotgun
This commit is contained in:
George Paton 2024-01-31 17:11:03 +11:00
parent 67c4273ebf
commit d979fd2e09
12 changed files with 5576 additions and 5979 deletions

View File

@ -49,17 +49,18 @@ public class GunConfiguration implements Cloneable {
//the target FOV/multiplied FOV modifier when sneaking
public float zoomFOV = 0.0F;
//how long the reload animation will play
//MUST BE GREATER THAN ZERO ! ! !
public int reloadDuration;
//duration of every animation cycle, used also for how quickly a burst fire rifle can fire
public int firingDuration;
//sound path to the reload sound
public String reloadSound = "";
//sound path to the shooting sound
public String firingSound = "";
public float firingVolume = 1.0F;
public float firingPitch = 1.0F;
//how long the reload animation will play
//MUST BE GREATER THAN ZERO ! ! !
public int reloadDuration;
public int emptyReloadAdditionalDuration;
//sound path to the reload sound
public String reloadSound = "";
//whether the reload sound should be played at the beginning or at the end of the reload
public boolean reloadSoundEnd = true;
public String equipSound = "";
@ -68,6 +69,8 @@ public class GunConfiguration implements Cloneable {
public int ammoCap;
//0 does not allow direct reload, 1 is full clip, 2 is single bullet
public int reloadType;
// If the animations are designed to be sequential, the last frame will be held until the next anmiation starts
public boolean reloadAnimationsSequential = false;
//whether or not the infinity enchantment should work
public boolean allowsInfinity;
//whether the ammo count should be displayed

View File

@ -17,6 +17,7 @@ import com.hbm.items.ModItems;
import com.hbm.items.ItemAmmoEnums.Ammo4Gauge;
import com.hbm.lib.HbmCollection;
import com.hbm.lib.HbmCollection.EnumGunManufacturer;
import com.hbm.main.ResourceManager;
import com.hbm.lib.ModDamageSource;
import com.hbm.packet.AuxParticlePacketNT;
import com.hbm.packet.PacketDispatcher;
@ -24,7 +25,6 @@ import com.hbm.particle.SpentCasing;
import com.hbm.particle.SpentCasing.CasingType;
import com.hbm.potion.HbmPotion;
import com.hbm.render.anim.BusAnimation;
import com.hbm.render.anim.BusAnimationKeyframe;
import com.hbm.render.anim.BusAnimationSequence;
import com.hbm.render.anim.HbmAnimations.AnimType;
import com.hbm.render.util.RenderScreenOverlay.Crosshair;
@ -84,6 +84,18 @@ public class Gun4GaugeFactory {
config.name = "ks23";
config.manufacturer = EnumGunManufacturer.TULSKY;
config.emptyReloadAdditionalDuration = 5;
config.reloadAnimationsSequential = true;
config.loadAnimations = i -> {
config.animations.put(AnimType.CYCLE, ResourceManager.ks23_anim.get("Fire"));
config.animations.put(AnimType.RELOAD, ResourceManager.ks23_anim.get("ReloadStart"));
config.animations.put(AnimType.RELOAD_EMPTY, ResourceManager.ks23_anim.get("ReloadEmptyStart"));
config.animations.put(AnimType.RELOAD_CYCLE, ResourceManager.ks23_anim.get("Reload"));
config.animations.put(AnimType.RELOAD_END, ResourceManager.ks23_anim.get("ReloadEnd"));
};
config.config = HbmCollection.g4;
return config;
@ -203,7 +215,7 @@ public class Gun4GaugeFactory {
PotionEffect eff = new PotionEffect(HbmPotion.phosphorus.id, 20 * 20, 0, true);
eff.getCurativeItems().clear();
bullet.effects = new ArrayList();
bullet.effects = new ArrayList<PotionEffect>();
bullet.effects.add(new PotionEffect(eff));
bullet.bntImpact = (bulletnt, x, y, z, sideHit) -> {
@ -494,7 +506,7 @@ public class Gun4GaugeFactory {
BulletConfigFactory.nuclearExplosion(creature, 0, 0, 0, ExplosionNukeSmall.PARAMS_TOTS);
bulletnt.worldObj.removeEntity(creature);
bulletnt.worldObj.unloadEntities(new ArrayList() {{ add(creature); }});
bulletnt.worldObj.unloadEntities(new ArrayList<EntityCreature>() {{ add(creature); }});
}
}
}

View File

@ -376,17 +376,20 @@ public class ItemGunBase extends Item implements IHoldableWeapon, IItemHUD, IEqu
ammo.stacksize = toConsume;
setMag(stack, getMag(stack) + toAdd);
if (getMag(stack) >= mainConfig.ammoCap)
if (getMag(stack) >= mainConfig.ammoCap) {
setIsReloading(stack, false);
else
PacketDispatcher.wrapper.sendTo(new GunAnimationPacket(AnimType.RELOAD_END.ordinal()), (EntityPlayerMP) player);
} else {
resetReloadCycle(player, stack);
PacketDispatcher.wrapper.sendTo(new GunAnimationPacket(AnimType.RELOAD_CYCLE.ordinal()), (EntityPlayerMP) player);
}
if(hasLoaded && mainConfig.reloadSoundEnd)
world.playSoundAtEntity(player, mainConfig.reloadSound, 1.0F, 1.0F);
if(mainConfig.ejector != null && mainConfig.ejector.getAfterReload())
queueCasing(player, mainConfig.ejector, prevCfg, stack);
InventoryUtil.tryConsumeAStack(player.inventory.mainInventory, 0, player.inventory.mainInventory.length - 1, ammo);
} else {
setReloadCycle(stack, getReloadCycle(stack) - 1);
@ -403,8 +406,8 @@ public class ItemGunBase extends Item implements IHoldableWeapon, IItemHUD, IEqu
if(player.isSneaking() && hasInfinity(stack, mainConfig)) {
if(this.getMag(stack) == mainConfig.ammoCap) {
this.setMag(stack, 0);
if(getMag(stack) == mainConfig.ammoCap) {
setMag(stack, 0);
this.resetAmmoType(stack, world, player);
world.playSoundAtEntity(player, "tile.piston.out", 1.0F, 1.0F);
}
@ -412,7 +415,7 @@ public class ItemGunBase extends Item implements IHoldableWeapon, IItemHUD, IEqu
return;
}
if(this.getMag(stack) == mainConfig.ammoCap)
if(getMag(stack) == mainConfig.ammoCap)
return;
if(getIsReloading(stack))
@ -421,8 +424,10 @@ public class ItemGunBase extends Item implements IHoldableWeapon, IItemHUD, IEqu
if(!mainConfig.reloadSoundEnd)
world.playSoundAtEntity(player, mainConfig.reloadSound, 1.0F, 1.0F);
if(!world.isRemote)
PacketDispatcher.wrapper.sendTo(new GunAnimationPacket(AnimType.RELOAD.ordinal()), (EntityPlayerMP) player);
if(!world.isRemote) {
AnimType reloadType = getMag(stack) == 0 ? AnimType.RELOAD_EMPTY : AnimType.RELOAD;
PacketDispatcher.wrapper.sendTo(new GunAnimationPacket(reloadType.ordinal()), (EntityPlayerMP) player);
}
setIsReloading(stack, true);
resetReloadCycle(player, stack);
@ -829,7 +834,9 @@ public class ItemGunBase extends Item implements IHoldableWeapon, IItemHUD, IEqu
}
public static int getReloadDuration(EntityPlayer player, ItemStack stack) {
int cycle = ((ItemGunBase) stack.getItem()).mainConfig.reloadDuration;
GunConfiguration config = ((ItemGunBase) stack.getItem()).mainConfig;
int cycle = config.reloadDuration;
if (getMag(stack) == 0) cycle += config.emptyReloadAdditionalDuration;
if(isTrenchMaster(player)) return Math.max(1, cycle / 2);
return cycle;
}

View File

@ -542,7 +542,7 @@ public class ClientProxy extends ServerProxy {
MinecraftForgeClient.registerItemRenderer(ModItems.gun_bio_revolver, new ItemRenderBioRevolver());
MinecraftForgeClient.registerItemRenderer(ModItems.gun_deagle, new ItemRenderWeaponObj());
MinecraftForgeClient.registerItemRenderer(ModItems.gun_supershotgun, new ItemRenderWeaponShotty());
MinecraftForgeClient.registerItemRenderer(ModItems.gun_ks23, new ItemRenderWeaponObj());
MinecraftForgeClient.registerItemRenderer(ModItems.gun_ks23, new ItemRenderWeaponKS23());
MinecraftForgeClient.registerItemRenderer(ModItems.gun_flamer, new ItemRenderWeaponObj());
MinecraftForgeClient.registerItemRenderer(ModItems.gun_flechette, new ItemRenderWeaponObj());
MinecraftForgeClient.registerItemRenderer(ModItems.gun_quadro, new ItemRenderWeaponQuadro());

View File

@ -321,6 +321,9 @@ public class ModEventHandlerClient {
if(animation == null)
continue;
if(animation.holdLastFrame)
continue;
long time = System.currentTimeMillis() - animation.startMillis;

View File

@ -847,6 +847,7 @@ public class ResourceManager {
public static final HashMap<String, BusAnimation> python_anim = AnimationLoader.load(new ResourceLocation(RefStrings.MODID, "models/weapons/animations/python.json"));
public static final HashMap<String, BusAnimation> cursed_anim = AnimationLoader.load(new ResourceLocation(RefStrings.MODID, "models/weapons/animations/cursed.json"));
public static final HashMap<String, BusAnimation> novac_anim = AnimationLoader.load(new ResourceLocation(RefStrings.MODID, "models/weapons/animations/novac.json"));
public static final HashMap<String, BusAnimation> ks23_anim = AnimationLoader.load(new ResourceLocation(RefStrings.MODID, "models/weapons/animations/ks23.json"));
public static final IModelCustom lance = new HFRWavefrontObject(new ResourceLocation(RefStrings.MODID, "models/weapons/lance.obj"));

View File

@ -58,10 +58,18 @@ public class GunAnimationPacket implements IMessage {
return null;
AnimType type = AnimType.values()[m.type];
BusAnimation animation = ((ItemGunBase) stack.getItem()).getAnimation(stack, type);
ItemGunBase base = (ItemGunBase) stack.getItem();
BusAnimation animation = base.getAnimation(stack, type);
// Fallback to regular reload if no empty reload animation
if(animation == null && type == AnimType.RELOAD_EMPTY) {
animation = base.getAnimation(stack, AnimType.RELOAD);
}
if(animation != null) {
HbmAnimations.hotbar[slot] = new Animation(stack.getItem().getUnlocalizedName(), System.currentTimeMillis(), animation);
boolean isReloadAnimation = type == AnimType.RELOAD || type == AnimType.RELOAD_CYCLE || type == AnimType.RELOAD_EMPTY;
HbmAnimations.hotbar[slot] = new Animation(stack.getItem().getUnlocalizedName(), System.currentTimeMillis(), animation, isReloadAnimation && base.mainConfig.reloadAnimationsSequential);
}
} catch(Exception x) { }

View File

@ -18,13 +18,19 @@ public class HbmAnimations {
public static final Animation[] hotbar = new Animation[9];
public static enum AnimType {
RELOAD, //animation for every reload cycle
CYCLE, //animation for every firing cycle
ALT_CYCLE, //animation for alt fire cycles
SPINUP, //animation for actionstart
SPINDOWN, //animation for actionend
EQUIP //animation for drawing the weapon
RELOAD, //animation for reloading the weapon
RELOAD_EMPTY, //animation for reloading from empty
RELOAD_CYCLE, //animation that plays for every individual round (for shotguns and similar single round loading weapons)
RELOAD_END, //animation for transitioning from our RELOAD_CYCLE to idle
CYCLE, //animation for every firing cycle
ALT_CYCLE, //animation for alt fire cycles
SPINUP, //animation for actionstart
SPINDOWN, //animation for actionend
EQUIP //animation for drawing the weapon
}
// A NOTE ON SHOTGUN STYLE RELOADS
// Make sure the RELOAD and RELOAD_EMPTY adds shells, not just RELOAD_CYCLE, they all proc once for each loaded shell
public static class Animation {
@ -35,12 +41,21 @@ public class HbmAnimations {
public long startMillis;
//the animation bus
public BusAnimation animation;
// If set, don't cancel this animation when the timer ends, instead wait for the next to start
public boolean holdLastFrame = false;
public Animation(String key, long startMillis, BusAnimation animation) {
this.key = key;
this.startMillis = startMillis;
this.animation = animation;
}
public Animation(String key, long startMillis, BusAnimation animation, boolean holdLastFrame) {
this.key = key;
this.startMillis = startMillis;
this.animation = animation;
this.holdLastFrame = holdLastFrame;
}
}
public static Animation getRelevantAnim() {

View File

@ -0,0 +1,144 @@
package com.hbm.render.item.weapon;
import java.awt.Color;
import org.lwjgl.opengl.GL11;
import com.hbm.main.ResourceManager;
import com.hbm.particle.SpentCasing;
import com.hbm.render.anim.HbmAnimations;
import net.minecraft.client.Minecraft;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraftforge.client.IItemRenderer;
public class ItemRenderWeaponKS23 implements IItemRenderer {
public ItemRenderWeaponKS23() { }
@Override
public boolean handleRenderType(ItemStack item, ItemRenderType type) {
switch(type) {
case EQUIPPED:
case EQUIPPED_FIRST_PERSON:
case ENTITY:
case INVENTORY:
return true;
default: return false;
}
}
@Override
public boolean shouldUseRenderHelper(ItemRenderType type, ItemStack item, ItemRendererHelper helper) {
return type == ItemRenderType.ENTITY && (helper == ItemRendererHelper.ENTITY_ROTATION || helper == ItemRendererHelper.ENTITY_BOBBING);
}
@Override
public void renderItem(ItemRenderType type, ItemStack item, Object... data) {
GL11.glPushMatrix();
GL11.glDisable(GL11.GL_CULL_FACE);
EntityPlayer player = Minecraft.getMinecraft().thePlayer;
Minecraft.getMinecraft().renderEngine.bindTexture(ResourceManager.ks23_tex);
switch(type) {
case EQUIPPED_FIRST_PERSON:
GL11.glTranslatef(1.0F, 0.5F, -0.25F);
GL11.glRotatef(25F, 0.0F, 0.0F, 1.0F);
GL11.glRotatef(-100, 0.0F, 1.0F, 0.0F);
GL11.glScaled(0.75, 0.75, 0.75);
if(player.isSneaking()) {
GL11.glRotatef(4.5F, 0.0F, 1.0F, 0.0F);
GL11.glRotatef(-2F, 0.0F, 0.0F, 1.0F);
GL11.glTranslatef(-0.9F, 0.2F, 0.325F);
}
HbmAnimations.applyRelevantTransformation("Body");
GL11.glShadeModel(GL11.GL_SMOOTH);
ResourceManager.ks23.renderPart("Body");
ResourceManager.ks23.renderPart("Trigger");
GL11.glPushMatrix();
HbmAnimations.applyRelevantTransformation("Bolt");
ResourceManager.ks23.renderPart("Bolt");
GL11.glPopMatrix();
GL11.glPushMatrix();
HbmAnimations.applyRelevantTransformation("Guard");
ResourceManager.ks23.renderPart("Guard");
GL11.glPopMatrix();
GL11.glPushMatrix();
Minecraft.getMinecraft().renderEngine.bindTexture(ResourceManager.casings_tex);
HbmAnimations.applyRelevantTransformation("Shell");
// TODO: Fetch the correct colors to render on the shells
Color shellColor = new Color(SpentCasing.COLOR_CASE_4GA);
GL11.glColor3f(shellColor.getRed() / 255F, shellColor.getGreen() / 255F, shellColor.getBlue() / 255F);
ResourceManager.ks23.renderPart("Shell");
Color shellForeColor = new Color(0xFFD800);
GL11.glColor3f(shellForeColor.getRed() / 255F, shellForeColor.getGreen() / 255F, shellForeColor.getBlue() / 255F);
ResourceManager.ks23.renderPart("ShellFore");
GL11.glColor3f(1F, 1F, 1F);
GL11.glPopMatrix();
GL11.glShadeModel(GL11.GL_FLAT);
GL11.glEnable(GL11.GL_CULL_FACE);
GL11.glPopMatrix();
return;
case EQUIPPED:
GL11.glRotatef(20F, 1.0F, 0.0F, 1.0F);
GL11.glRotatef(-170F, 0.0F, 1.0F, 0.0F);
GL11.glTranslatef(-0.5F, 0.0F, -0.9F);
GL11.glScaled(0.5, 0.5, 0.5);
break;
case ENTITY:
GL11.glTranslatef(0.3F, 0.2F, 0.0F);
GL11.glScaled(0.5, 0.5, 0.5);
break;
case INVENTORY:
GL11.glEnable(GL11.GL_LIGHTING);
GL11.glTranslatef(7F, 8F, 0.0F);
GL11.glScaled(4, 4, -4);
GL11.glRotatef(-90, 0, 1, 0);
GL11.glRotatef(-135F, 1.0F, 0.0F, 0.0F);
break;
default: break;
}
GL11.glShadeModel(GL11.GL_SMOOTH);
ResourceManager.ks23.renderAll();
GL11.glShadeModel(GL11.GL_FLAT);
GL11.glEnable(GL11.GL_CULL_FACE);
GL11.glPopMatrix();
}
}

View File

@ -23,7 +23,7 @@ public class ItemRenderWeaponObj implements IItemRenderer {
case ENTITY:
return true;
case INVENTORY:
return item.getItem() == ModItems.gun_ks23 || item.getItem() == ModItems.gun_hk69
return item.getItem() == ModItems.gun_hk69
|| item.getItem() == ModItems.gun_flamer || item.getItem() == ModItems.gun_deagle
|| item.getItem() == ModItems.gun_flechette || item.getItem() == ModItems.gun_quadro;
default: return false;
@ -50,9 +50,6 @@ public class ItemRenderWeaponObj implements IItemRenderer {
if(item.getItem() == ModItems.gun_deagle)
Minecraft.getMinecraft().renderEngine.bindTexture(ResourceManager.universal_bright);
if(item.getItem() == ModItems.gun_ks23)
Minecraft.getMinecraft().renderEngine.bindTexture(ResourceManager.ks23_tex);
if(item.getItem() == ModItems.gun_flamer)
Minecraft.getMinecraft().renderEngine.bindTexture(ResourceManager.flamer_tex);
@ -90,19 +87,6 @@ public class ItemRenderWeaponObj implements IItemRenderer {
}
}
if(item.getItem() == ModItems.gun_ks23) {
GL11.glTranslatef(1.0F, 0.5F, -0.25F);
GL11.glRotatef(25F, 0.0F, 0.0F, 1.0F);
GL11.glRotatef(-10F, 0.0F, 1.0F, 0.0F);
GL11.glScaled(0.75, 0.75, 0.75);
if(player.isSneaking()) {
GL11.glRotatef(4.5F, 0.0F, 1.0F, 0.0F);
GL11.glRotatef(-2.5F, 0.0F, 0.0F, 1.0F);
GL11.glTranslatef(0.3F, 0.2F, -0.875F);
}
}
if(item.getItem() == ModItems.gun_flamer) {
GL11.glTranslatef(1.0F, 0.0F, -0.15F);
GL11.glRotatef(90F, 0.0F, 1.0F, 0.0F);
@ -169,13 +153,6 @@ public class ItemRenderWeaponObj implements IItemRenderer {
GL11.glScaled(0.15, 0.15, 0.15);
}
if(item.getItem() == ModItems.gun_ks23) {
GL11.glRotatef(20F, 1.0F, 0.0F, 1.0F);
GL11.glRotatef(-80F, 0.0F, 1.0F, 0.0F);
GL11.glTranslatef(0.9F, 0.0F, -0.5F);
GL11.glScaled(0.5, 0.5, 0.5);
}
if(item.getItem() == ModItems.gun_flamer) {
GL11.glRotatef(20F, 1.0F, 0.0F, 1.0F);
GL11.glRotatef(10F, 0.0F, 1.0F, 0.0F);
@ -213,11 +190,6 @@ public class ItemRenderWeaponObj implements IItemRenderer {
GL11.glScaled(0.25, 0.25, 0.25);
}
if(item.getItem() == ModItems.gun_ks23) {
GL11.glTranslatef(0.3F, 0.2F, 0.0F);
GL11.glScaled(0.5, 0.5, 0.5);
}
if(item.getItem() == ModItems.gun_flamer) {
GL11.glTranslatef(0.25F, 0.2F, 0.0F);
GL11.glRotatef(-90F, 0.0F, 1.0F, 0.0F);
@ -257,12 +229,6 @@ public class ItemRenderWeaponObj implements IItemRenderer {
GL11.glRotatef(-45F, 1.0F, 0.0F, 0.0F);
}
if(item.getItem() == ModItems.gun_ks23) {
GL11.glTranslatef(7F, 8F, 0.0F);
GL11.glScaled(4, 4, -4);
GL11.glRotatef(-135F, 0.0F, 0.0F, 1.0F);
}
if(item.getItem() == ModItems.gun_flamer) {
GL11.glScaled(2.0, 2.0, -2.0);
GL11.glTranslatef(4.0F, 5.0F, 0.0F);
@ -303,12 +269,6 @@ public class ItemRenderWeaponObj implements IItemRenderer {
GL11.glShadeModel(GL11.GL_FLAT);
}
if(item.getItem() == ModItems.gun_ks23) {
GL11.glShadeModel(GL11.GL_SMOOTH);
ResourceManager.ks23.renderAll();
GL11.glShadeModel(GL11.GL_FLAT);
}
if(item.getItem() == ModItems.gun_flamer) {
GL11.glShadeModel(GL11.GL_SMOOTH);
ResourceManager.flamer.renderAll();

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff