From 1384f14fe39c3a01e2d884e0b762567638f07565 Mon Sep 17 00:00:00 2001 From: Bob Date: Tue, 17 Sep 2024 21:30:34 +0200 Subject: [PATCH] a ton of gun stuff --- .../java/com/hbm/entity/EntityMappings.java | 1 + .../projectile/EntityBulletBaseMK4.java | 89 ++++++++++++++ .../hbm/items/weapon/sedna/BulletConfig.java | 13 ++- .../com/hbm/items/weapon/sedna/GunConfig.java | 110 +++++++++++------- .../items/weapon/sedna/IWeaponUpgrade.java | 14 +++ .../hbm/items/weapon/sedna/ItemGunBaseNT.java | 14 ++- .../com/hbm/items/weapon/sedna/Receiver.java | 79 ++++++++----- .../weapon/sedna/WeaponUpgradeManager.java | 31 +++++ .../weapon/sedna/factory/GunFactory.java | 6 +- .../weapon/sedna/factory/GunStateDecider.java | 4 +- .../hbm/items/weapon/sedna/factory/Lego.java | 28 ++++- .../items/weapon/sedna/mags/IMagazine.java | 6 + .../sedna/mags/MagazineStandardBase.java | 8 +- .../com/hbm/render/anim/HbmAnimations.java | 3 +- .../item/weapon/sedna/ItemRenderDebug.java | 4 +- .../items/gun_upgrade_debug_conversion.png | Bin 0 -> 310 bytes .../items/gun_upgrade_debug_damage.png | Bin 0 -> 320 bytes .../items/gun_upgrade_debug_multishot.png | Bin 0 -> 358 bytes .../items/gun_upgrade_debug_shotspeed.png | Bin 0 -> 349 bytes 19 files changed, 319 insertions(+), 91 deletions(-) create mode 100644 src/main/java/com/hbm/entity/projectile/EntityBulletBaseMK4.java create mode 100644 src/main/java/com/hbm/items/weapon/sedna/IWeaponUpgrade.java create mode 100644 src/main/java/com/hbm/items/weapon/sedna/WeaponUpgradeManager.java create mode 100644 src/main/resources/assets/hbm/textures/items/gun_upgrade_debug_conversion.png create mode 100644 src/main/resources/assets/hbm/textures/items/gun_upgrade_debug_damage.png create mode 100644 src/main/resources/assets/hbm/textures/items/gun_upgrade_debug_multishot.png create mode 100644 src/main/resources/assets/hbm/textures/items/gun_upgrade_debug_shotspeed.png diff --git a/src/main/java/com/hbm/entity/EntityMappings.java b/src/main/java/com/hbm/entity/EntityMappings.java index b5011714c..70cd60c25 100644 --- a/src/main/java/com/hbm/entity/EntityMappings.java +++ b/src/main/java/com/hbm/entity/EntityMappings.java @@ -151,6 +151,7 @@ public class EntityMappings { addEntity(EntityGrenadeIFNull.class, "entity_grenade_ironshod_null", 250); addEntity(EntityFallingNuke.class, "entity_falling_bomb", 1000); addEntity(EntityBulletBaseNT.class, "entity_bullet_mk3", 250, false); + addEntity(EntityBulletBaseMK4.class, "entity_bullet_mk4", 250, false); addEntity(EntityMinerRocket.class, "entity_miner_lander", 1000); addEntity(EntityFogFX.class, "entity_nuclear_fog", 1000); addEntity(EntityDuchessGambit.class, "entity_duchessgambit", 1000); diff --git a/src/main/java/com/hbm/entity/projectile/EntityBulletBaseMK4.java b/src/main/java/com/hbm/entity/projectile/EntityBulletBaseMK4.java new file mode 100644 index 000000000..92938b64a --- /dev/null +++ b/src/main/java/com/hbm/entity/projectile/EntityBulletBaseMK4.java @@ -0,0 +1,89 @@ +package com.hbm.entity.projectile; + +import com.hbm.items.weapon.sedna.BulletConfig; + +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.util.MathHelper; +import net.minecraft.util.MovingObjectPosition; +import net.minecraft.util.Vec3; +import net.minecraft.world.World; + +public class EntityBulletBaseMK4 extends EntityThrowableInterp { + + public BulletConfig config; + + 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 spreadMod, double sideOffset, double heightOffset, double frontOffset) { + this(entity.worldObj); + + this.thrower = entity; + this.config = config; + + 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 * spreadMod); + } + + @Override + protected void entityInit() { + super.entityInit(); + this.dataWatcher.addObject(3, Integer.valueOf(0)); + } + + public void setBulletConfig(BulletConfig 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 = posX; + this.prevPosY = posY; + this.prevPosZ = posZ; + + super.onUpdate(); + } + + @Override + protected void onImpact(MovingObjectPosition mop) { + 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; } +} diff --git a/src/main/java/com/hbm/items/weapon/sedna/BulletConfig.java b/src/main/java/com/hbm/items/weapon/sedna/BulletConfig.java index 9cc858b8b..9a43ef50b 100644 --- a/src/main/java/com/hbm/items/weapon/sedna/BulletConfig.java +++ b/src/main/java/com/hbm/items/weapon/sedna/BulletConfig.java @@ -31,6 +31,15 @@ public class BulletConfig { this.id = configs.size(); configs.add(this); } - - public BulletConfig setItem(Item ammo) { this.ammo = new ComparableStack(ammo); return this; } + + public BulletConfig setItem(Item ammo) { this.ammo = new ComparableStack(ammo); return this; } + public BulletConfig setReloadCount(int ammoReloadCount) { this.ammoReloadCount = ammoReloadCount; return this; } + public BulletConfig setVel(float velocity) { this.velocity = velocity; return this; } + public BulletConfig setSpread(float spread) { this.spread = spread; return this; } + public BulletConfig setWear(float wear) { this.wear = wear; return this; } + public BulletConfig setProjectiles(int min, int max) { this.projectilesMin = min; this.projectilesMax = max; return this; } + public BulletConfig setDamage(float damageMult) { this.damageMult = damageMult; return this; } + public BulletConfig setHeadshot(float headshotMult) { this.headshotMult = headshotMult; return this; } + public BulletConfig setGrav(double gravity) { this.gravity = gravity; return this; } + public BulletConfig setLife(int expires) { this.expires = expires; return this; } } diff --git a/src/main/java/com/hbm/items/weapon/sedna/GunConfig.java b/src/main/java/com/hbm/items/weapon/sedna/GunConfig.java index 0eed0f236..e0388871c 100644 --- a/src/main/java/com/hbm/items/weapon/sedna/GunConfig.java +++ b/src/main/java/com/hbm/items/weapon/sedna/GunConfig.java @@ -9,75 +9,97 @@ import com.hbm.render.anim.HbmAnimations.AnimType; import net.minecraft.item.ItemStack; +/** + * Despite how complicated the GunConfig looks, it actually only exists to hold together a bunch of fields. Everything else is infrastructure for getting and setting. + * The gun config determines general gun specific stats like durability, crosshair, animations, receivers, click handling and the decider. + * + * @author hbm + * */ public class GunConfig { + + public static final String O_RECEIVERS = "O_RECEIVERS"; + public static final String F_DURABILITY = "F_DURABILITY"; + public static final String I_DRAWDURATION = "I_DRAWDURATION"; + public static final String O_CROSSHAIR = "O_CROSSHAIR"; + public static final String B_RELOADANIMATIONSEQUENTIAL = "B_RELOADANIMATIONSEQUENTIAL"; + public static final String CON_ONPRESSPRIMARY = "CON_ONPRESSPRIMARY"; + public static final String CON_ONPRESSSECONDARY = "CON_ONPRESSSECONDARY"; + public static final String CON_ONPRESSTERTIARY = "CON_ONPRESSTERTIARY"; + public static final String CON_ONPRESSRELOAD = "CON_ONPRESSRELOAD"; + public static final String CON_ONRELEASEPRIMARY = "CON_ONRELEASEPRIMARY"; + public static final String CON_ONRELEASESECONDARY = "CON_ONRELEASESECONDARY"; + public static final String CON_ONRELEASETERTIARY = "CON_ONRELEASETERTIARY"; + public static final String CON_ONRELEASERELOAD = "CON_ONRELEASERELOAD"; + public static final String CON_DECIDER = "CON_DECIDER"; + public static final String FUN_ANIMNATIONS = "FUN_ANIMNATIONS"; /* FIELDS */ /** List of receivers used by the gun, primary and secondary are usually indices 0 and 1 respectively, if applicable */ - protected Receiver[] receivers; - protected float durability; - protected int drawDuration = 0; - protected Crosshair crosshair; - protected boolean reloadAnimationsSequential; + protected Receiver[] receivers_DNA; + protected float durability_DNA; + protected int drawDuration_DNA = 0; + protected Crosshair crosshair_DNA; + protected boolean reloadAnimationsSequential_DNA; /** Lambda functions for clicking shit */ - protected BiConsumer onPressPrimary; - protected BiConsumer onPressSecondary; - protected BiConsumer onPressTertiary; - protected BiConsumer onPressReload; + protected BiConsumer onPressPrimary_DNA; + protected BiConsumer onPressSecondary_DNA; + protected BiConsumer onPressTertiary_DNA; + protected BiConsumer onPressReload_DNA; /** Lambda functions for releasing the aforementioned shit */ - protected BiConsumer onReleasePrimary; - protected BiConsumer onReleaseSecondary; - protected BiConsumer onReleaseTertiary; - protected BiConsumer onReleaseReload; + protected BiConsumer onReleasePrimary_DNA; + protected BiConsumer onReleaseSecondary_DNA; + protected BiConsumer onReleaseTertiary_DNA; + protected BiConsumer onReleaseReload_DNA; /** The engine for the state machine that determines the gun's overall behavior */ - protected BiConsumer decider; + protected BiConsumer decider_DNA; /** Lambda that returns the relevant animation for the given params */ - protected BiFunction animations; + protected BiFunction animations_DNA; /* GETTERS */ - public Receiver[] getReceivers(ItemStack stack) { return receivers; } - public float getDurability(ItemStack stack) { return durability; } - public int getDrawDuration(ItemStack stack) { return drawDuration; } - public Crosshair getCrosshair(ItemStack stack) { return crosshair; } - public boolean getReloadAnimSequential(ItemStack stack) { return reloadAnimationsSequential; } + public Receiver[] getReceivers(ItemStack stack) { return WeaponUpgradeManager.eval(receivers_DNA, stack, O_RECEIVERS, this); } + public float getDurability(ItemStack stack) { return WeaponUpgradeManager.eval(durability_DNA, stack, F_DURABILITY, this); } + public int getDrawDuration(ItemStack stack) { return WeaponUpgradeManager.eval(drawDuration_DNA, stack, I_DRAWDURATION, this); } + public Crosshair getCrosshair(ItemStack stack) { return WeaponUpgradeManager.eval(crosshair_DNA, stack, O_CROSSHAIR, this); } + public boolean getReloadAnimSequential(ItemStack stack) { return WeaponUpgradeManager.eval(reloadAnimationsSequential_DNA, stack, B_RELOADANIMATIONSEQUENTIAL, this); } - public BiConsumer getPressPrimary(ItemStack stack) { return this.onPressPrimary; } - public BiConsumer getPressSecondary(ItemStack stack) { return this.onPressSecondary; } - public BiConsumer getPressTertiary(ItemStack stack) { return this.onPressTertiary; } - public BiConsumer getPressReload(ItemStack stack) { return this.onPressReload; } + public BiConsumer getPressPrimary(ItemStack stack) { return WeaponUpgradeManager.eval(this.onPressPrimary_DNA, stack, CON_ONPRESSPRIMARY, this); } + public BiConsumer getPressSecondary(ItemStack stack) { return WeaponUpgradeManager.eval(this.onPressSecondary_DNA, stack, CON_ONPRESSSECONDARY, this); } + public BiConsumer getPressTertiary(ItemStack stack) { return WeaponUpgradeManager.eval(this.onPressTertiary_DNA, stack, CON_ONPRESSTERTIARY, this); } + public BiConsumer getPressReload(ItemStack stack) { return WeaponUpgradeManager.eval(this.onPressReload_DNA, stack, CON_ONPRESSRELOAD, this); } - public BiConsumer getReleasePrimary(ItemStack stack) { return this.onReleasePrimary; } - public BiConsumer getReleaseSecondary(ItemStack stack) { return this.onReleaseSecondary; } - public BiConsumer getReleaseTertiary(ItemStack stack) { return this.onReleaseTertiary; } - public BiConsumer getReleaseReload(ItemStack stack) { return this.onReleaseReload; } + public BiConsumer getReleasePrimary(ItemStack stack) { return WeaponUpgradeManager.eval(this.onReleasePrimary_DNA, stack, CON_ONRELEASEPRIMARY, this); } + public BiConsumer getReleaseSecondary(ItemStack stack) { return WeaponUpgradeManager.eval(this.onReleaseSecondary_DNA, stack, CON_ONRELEASESECONDARY, this); } + public BiConsumer getReleaseTertiary(ItemStack stack) { return WeaponUpgradeManager.eval(this.onReleaseTertiary_DNA, stack, CON_ONRELEASETERTIARY, this); } + public BiConsumer getReleaseReload(ItemStack stack) { return WeaponUpgradeManager.eval(this.onReleaseReload_DNA, stack, CON_ONRELEASERELOAD, this); } - public BiConsumer getDecider(ItemStack stack) { return this.decider; } + public BiConsumer getDecider(ItemStack stack) { return WeaponUpgradeManager.eval(this.decider_DNA, stack, CON_DECIDER, this); } - public BiFunction getAnims(ItemStack stack) { return this.animations; } + public BiFunction getAnims(ItemStack stack) { return WeaponUpgradeManager.eval(this.animations_DNA, stack, FUN_ANIMNATIONS, this); } /* SETTERS */ - public GunConfig rec(Receiver... receivers) { this.receivers = receivers; return this; } - public GunConfig dura(float dura) { this.durability = dura; return this; } - public GunConfig draw(int draw) { this.drawDuration = draw; return this; } - public GunConfig crosshair(Crosshair crosshair) { this.crosshair = crosshair; return this; } + public GunConfig rec(Receiver... receivers) { this.receivers_DNA = receivers; return this; } + public GunConfig dura(float dura) { this.durability_DNA = dura; return this; } + public GunConfig draw(int draw) { this.drawDuration_DNA = draw; return this; } + public GunConfig crosshair(Crosshair crosshair) { this.crosshair_DNA = crosshair; return this; } //press - public GunConfig pp(BiConsumer lambda) { this.onPressPrimary = lambda; return this; } - public GunConfig ps(BiConsumer lambda) { this.onPressSecondary = lambda; return this; } - public GunConfig pt(BiConsumer lambda) { this.onPressTertiary = lambda; return this; } - public GunConfig pr(BiConsumer lambda) { this.onPressReload = lambda; return this; } + public GunConfig pp(BiConsumer lambda) { this.onPressPrimary_DNA = lambda; return this; } + public GunConfig ps(BiConsumer lambda) { this.onPressSecondary_DNA = lambda; return this; } + public GunConfig pt(BiConsumer lambda) { this.onPressTertiary_DNA = lambda; return this; } + public GunConfig pr(BiConsumer lambda) { this.onPressReload_DNA = lambda; return this; } //release - public GunConfig rp(BiConsumer lambda) { this.onReleasePrimary = lambda; return this; } - public GunConfig rs(BiConsumer lambda) { this.onReleaseSecondary = lambda; return this; } - public GunConfig rt(BiConsumer lambda) { this.onReleaseTertiary = lambda; return this; } - public GunConfig rr(BiConsumer lambda) { this.onReleaseReload = lambda; return this; } + public GunConfig rp(BiConsumer lambda) { this.onReleasePrimary_DNA = lambda; return this; } + public GunConfig rs(BiConsumer lambda) { this.onReleaseSecondary_DNA = lambda; return this; } + public GunConfig rt(BiConsumer lambda) { this.onReleaseTertiary_DNA = lambda; return this; } + public GunConfig rr(BiConsumer lambda) { this.onReleaseReload_DNA = lambda; return this; } //decider - public GunConfig decider(BiConsumer lambda) { this.decider = lambda; return this; } + public GunConfig decider(BiConsumer lambda) { this.decider_DNA = lambda; return this; } //anims - public GunConfig anim(BiFunction lambda) { this.animations = lambda; return this; } + public GunConfig anim(BiFunction lambda) { this.animations_DNA = lambda; return this; } } diff --git a/src/main/java/com/hbm/items/weapon/sedna/IWeaponUpgrade.java b/src/main/java/com/hbm/items/weapon/sedna/IWeaponUpgrade.java new file mode 100644 index 000000000..502f12aec --- /dev/null +++ b/src/main/java/com/hbm/items/weapon/sedna/IWeaponUpgrade.java @@ -0,0 +1,14 @@ +package com.hbm.items.weapon.sedna; + +import net.minecraft.item.ItemStack; + +public interface IWeaponUpgrade { + + /** Lower numbers get installed and therefore evaluated first. Important when multiplicative and additive bonuses are supposed to stack */ + public int getModPriority(ItemStack stack); + /** Which "slots" this upgrade occupies, can be any value, upgrades that have at least one matching slot are incompatible */ + public String[] getSlots(ItemStack stack); + /** The meat and bones of the upgrade eval. Requires the base value, the held gun, the value's + * identifier and the yet unmodified parent (i.e. if the value is part of the receiver, that receiver) */ + public default T eval(T base, ItemStack stack, String key, Object parent) { return base; } +} diff --git a/src/main/java/com/hbm/items/weapon/sedna/ItemGunBaseNT.java b/src/main/java/com/hbm/items/weapon/sedna/ItemGunBaseNT.java index 8d55aec88..36a3e9bfa 100644 --- a/src/main/java/com/hbm/items/weapon/sedna/ItemGunBaseNT.java +++ b/src/main/java/com/hbm/items/weapon/sedna/ItemGunBaseNT.java @@ -27,6 +27,8 @@ import net.minecraftforge.client.event.RenderGameOverlayEvent.Pre; public class ItemGunBaseNT extends Item implements IKeybindReceiver, IEquipReceiver, IItemHUD { + public static final String O_GUNCONFIG = "O_GUNCONFIG"; + public static final String KEY_DRAWN = "drawn"; public static final String KEY_AIMING = "aiming"; public static final String KEY_TIMER = "timer"; @@ -43,7 +45,7 @@ public class ItemGunBaseNT extends Item implements IKeybindReceiver, IEquipRecei private GunConfig config_DNA; public GunConfig getConfig(ItemStack stack) { - return config_DNA; + return WeaponUpgradeManager.eval(config_DNA, stack, O_GUNCONFIG, this); } public ItemGunBaseNT(GunConfig cfg) { @@ -55,7 +57,7 @@ public class ItemGunBaseNT extends Item implements IKeybindReceiver, IEquipRecei DRAWING, //initial delay after selecting IDLE, //gun can be fired or reloaded WINDUP, //fire button is down, added delay before fire - JUST_FIRED, //gun has been fired, cooldown + COOLDOWN, //gun has been fired, cooldown RELOADING //gun is currently reloading } @@ -92,7 +94,15 @@ public class ItemGunBaseNT extends Item implements IKeybindReceiver, IEquipRecei EntityPlayer player = (EntityPlayer) entity; if(world.isRemote) { + if(isHeld && player == MainRegistry.proxy.me()) { + + /// DEBUG /// + /*Vec3 offset = Vec3.createVectorHelper(-0.2, -0.1, 0.75); + offset.rotateAroundX(-entity.rotationPitch / 180F * (float) Math.PI); + offset.rotateAroundY(-entity.rotationYaw / 180F * (float) Math.PI); + world.spawnParticle("flame", entity.posX + offset.xCoord, entity.posY + entity.getEyeHeight() + offset.yCoord, entity.posZ + offset.zCoord, 0, 0, 0);*/ + prevAimingProgress = aimingProgress; boolean aiming = this.getIsAiming(stack); float aimSpeed = 0.25F; diff --git a/src/main/java/com/hbm/items/weapon/sedna/Receiver.java b/src/main/java/com/hbm/items/weapon/sedna/Receiver.java index b5320d003..7c9ad2e14 100644 --- a/src/main/java/com/hbm/items/weapon/sedna/Receiver.java +++ b/src/main/java/com/hbm/items/weapon/sedna/Receiver.java @@ -9,39 +9,64 @@ import com.hbm.items.weapon.sedna.mags.IMagazine; import net.minecraft.item.ItemStack; +/** + * Receivers are the gun's "moving parts", i.e. they determine things like base damage, spread, the ejector and the magazine. Think of this class like the + * barrel, receiver and chamber of the gun, an underbarrel grenade launcher for example would be a separate receiver instance compared to the regular gun it is attached to. + * + * @author hbm + */ public class Receiver { - protected float baseDamage; - protected int delayAfterFire; - protected int roundsPerCycle = 1; - protected boolean refireOnHold = false; - protected CasingEjector ejector = null; - protected int reloadDuration; - protected IMagazine magazine; - protected BiFunction canFire; - protected BiConsumer onFire; + public static final String F_BASEDAMAGE = "F_BASEDAMAGE"; + public static final String I_DELAYAFTERFIRE = "I_DELAYAFTERFIRE"; + public static final String I_ROUNDSPERCYCLE = "I_ROUNDSPERCYCLE"; + public static final String F_SPREADMOD = "F_SPREADMOD"; + public static final String B_REFIREONHOLD = "B_REFIREONHOLD"; + public static final String O_EJECTOR = "O_EJECTOR"; + public static final String I_RELOADDURATION = "I_RELOADDURATION"; + public static final String O_MAGAZINE = "O_MAGAZINE"; + public static final String FUN_CANFIRE = "FUN_CANFIRE"; + public static final String CON_ONFIRE = "CON_ONFIRE"; + + public Receiver(int index) { + this.index = index; + } + + protected int index; + protected float baseDamage_DNA; + protected int delayAfterFire_DNA; + protected int roundsPerCycle_DNA = 1; + protected float spreadMod_DNA = 1F; + protected boolean refireOnHold_DNA = false; + protected CasingEjector ejector_DNA = null; + protected int reloadDuration_DNA; + protected IMagazine magazine_DNA; + protected BiFunction canFire_DNA; + protected BiConsumer onFire_DNA; /* GETTERS */ - public float getBaseDamage(ItemStack stack) { return this.baseDamage; } - public int getDelayAfterFire(ItemStack stack) { return this.delayAfterFire; } - public int getRoundsPerCycle(ItemStack stack) { return this.roundsPerCycle; } - public boolean getRefireOnHold(ItemStack stack) { return this.refireOnHold; } - public CasingEjector getEjector(ItemStack stack) { return this.ejector; } - public int getReloadDuration(ItemStack stack) { return this.reloadDuration; } - public IMagazine getMagazine(ItemStack stack) { return this.magazine; } + public float getBaseDamage(ItemStack stack) { return WeaponUpgradeManager.eval(this.baseDamage_DNA, stack, F_BASEDAMAGE, this); } + public int getDelayAfterFire(ItemStack stack) { return WeaponUpgradeManager.eval(this.delayAfterFire_DNA, stack, I_DELAYAFTERFIRE, this); } + public int getRoundsPerCycle(ItemStack stack) { return WeaponUpgradeManager.eval(this.roundsPerCycle_DNA, stack, I_ROUNDSPERCYCLE, this); } + public float getSpreadMod(ItemStack stack) { return WeaponUpgradeManager.eval(this.spreadMod_DNA, stack, F_SPREADMOD, this); } + public boolean getRefireOnHold(ItemStack stack) { return WeaponUpgradeManager.eval(this.refireOnHold_DNA, stack, B_REFIREONHOLD, this); } + public CasingEjector getEjector(ItemStack stack) { return WeaponUpgradeManager.eval(this.ejector_DNA, stack, O_EJECTOR, this); } + public int getReloadDuration(ItemStack stack) { return WeaponUpgradeManager.eval(this.reloadDuration_DNA, stack, I_RELOADDURATION, this); } + public IMagazine getMagazine(ItemStack stack) { return WeaponUpgradeManager.eval(this.magazine_DNA, stack, O_MAGAZINE, this); } - public BiFunction getCanFire(ItemStack stack) { return this.canFire; } - public BiConsumer getOnFire(ItemStack stack) { return this.onFire; } + public BiFunction getCanFire(ItemStack stack) { return WeaponUpgradeManager.eval(this.canFire_DNA, stack, FUN_CANFIRE, this); } + public BiConsumer getOnFire(ItemStack stack) { return WeaponUpgradeManager.eval(this.onFire_DNA, stack, CON_ONFIRE, this); } /* SETTERS */ - public Receiver dmg(float dmg) { this.baseDamage = dmg; return this; } - public Receiver delay(int delay) { this.delayAfterFire = delay; return this; } - public Receiver rounds(int rounds) { this.roundsPerCycle = rounds; return this; } - public Receiver auto(boolean auto) { this.refireOnHold = auto; return this; } - public Receiver burst(CasingEjector ejector) { this.ejector = ejector; return this; } - public Receiver reload(int delay) { this.reloadDuration = delay; return this; } - public Receiver mag(IMagazine magazine) { this.magazine = magazine; return this; } + public Receiver dmg(float dmg) { this.baseDamage_DNA = dmg; return this; } + public Receiver delay(int delay) { this.delayAfterFire_DNA = delay; return this; } + public Receiver rounds(int rounds) { this.roundsPerCycle_DNA = rounds; return this; } + public Receiver spread(int spread) { this.spreadMod_DNA = spread; return this; } + public Receiver auto(boolean auto) { this.refireOnHold_DNA = auto; return this; } + public Receiver burst(CasingEjector ejector) { this.ejector_DNA = ejector; return this; } + public Receiver reload(int delay) { this.reloadDuration_DNA = delay; return this; } + public Receiver mag(IMagazine magazine) { this.magazine_DNA = magazine; return this; } - public Receiver canFire(BiFunction lambda) { this.canFire = lambda; return this; } - public Receiver fire(BiConsumer lambda) { this.onFire = lambda; return this; } + public Receiver canFire(BiFunction lambda) { this.canFire_DNA = lambda; return this; } + public Receiver fire(BiConsumer lambda) { this.onFire_DNA = lambda; return this; } } diff --git a/src/main/java/com/hbm/items/weapon/sedna/WeaponUpgradeManager.java b/src/main/java/com/hbm/items/weapon/sedna/WeaponUpgradeManager.java new file mode 100644 index 000000000..4674ee866 --- /dev/null +++ b/src/main/java/com/hbm/items/weapon/sedna/WeaponUpgradeManager.java @@ -0,0 +1,31 @@ +package com.hbm.items.weapon.sedna; + +import net.minecraft.item.ItemStack; + +/** + * The upgrade manager operates by scraping upgrades from a gun, then iterating over them and evaluating the given value, passing the modified value to successive mods. + * The way that mods stack (additive vs multiplicative) depends on the order the mod is installed in + * + * @author hbm + */ +public class WeaponUpgradeManager { + + public static ItemStack[] getUpgrades(ItemStack stack) { + return null; // TBI + } + + /** Scrapes all upgrades, iterates over them and evaluates the given value. The parent (i.e. holder of the base value) + * is passed for context (so upgrades can differentiate primary and secondary receivers for example) */ + public static T eval(T base, ItemStack stack, String key, Object parent) { + + ItemStack[] upgrades = getUpgrades(stack); + if(upgrades != null) for(ItemStack upgradeStack : upgrades) { + if(upgradeStack.getItem() instanceof IWeaponUpgrade) { + IWeaponUpgrade upgrade = (IWeaponUpgrade) upgradeStack.getItem(); + base = upgrade.eval(base, upgradeStack, key, parent); + } + } + + return base; + } +} diff --git a/src/main/java/com/hbm/items/weapon/sedna/factory/GunFactory.java b/src/main/java/com/hbm/items/weapon/sedna/factory/GunFactory.java index 1fcba5bd0..434bf5949 100644 --- a/src/main/java/com/hbm/items/weapon/sedna/factory/GunFactory.java +++ b/src/main/java/com/hbm/items/weapon/sedna/factory/GunFactory.java @@ -18,12 +18,12 @@ public class GunFactory { ModItems.ammo_debug = new Item().setUnlocalizedName("ammo_debug").setTextureName(RefStrings.MODID + ":ammo_45"); - BulletConfig ammo_debug = new BulletConfig().setItem(ModItems.ammo_debug); + BulletConfig ammo_debug = new BulletConfig().setItem(ModItems.ammo_debug).setSpread(0.01F); ModItems.gun_debug = new ItemGunBaseNT(new GunConfig() .dura(600).draw(15).crosshair(Crosshair.L_CLASSIC) - .rec(new Receiver() - .dmg(10F).delay(10).mag(new MagazineRevolverDrum(0, 6).addConfigs(ammo_debug)) + .rec(new Receiver(0) + .dmg(10F).delay(12).mag(new MagazineRevolverDrum(0, 6).addConfigs(ammo_debug)) .canFire(Lego.LAMBDA_DEBUG_CAN_FIRE).fire(Lego.LAMBDA_DEBUG_FIRE)) .pr(Lego.LAMBDA_STANDARD_RELOAD) .pp(Lego.LAMBDA_STANDARD_FIRE) diff --git a/src/main/java/com/hbm/items/weapon/sedna/factory/GunStateDecider.java b/src/main/java/com/hbm/items/weapon/sedna/factory/GunStateDecider.java index d4d3fdc8d..3fc55d712 100644 --- a/src/main/java/com/hbm/items/weapon/sedna/factory/GunStateDecider.java +++ b/src/main/java/com/hbm/items/weapon/sedna/factory/GunStateDecider.java @@ -62,7 +62,7 @@ public class GunStateDecider { /** Triggers a re-fire of the primary if the fire delay has expired, the left mouse button is down and re-firing is enabled, otherwise switches to IDLE */ public static void deciderAutoRefire(ItemStack stack, LambdaContext ctx, GunState lastState, int recIndex, BooleanSupplier refireCondition) { - if(lastState == GunState.JUST_FIRED) { + if(lastState == GunState.COOLDOWN) { GunConfig cfg = ctx.config; Receiver rec = cfg.getReceivers(stack)[recIndex]; @@ -72,7 +72,7 @@ public class GunStateDecider { //if there's a bullet loaded, fire again if(rec.getCanFire(stack).apply(stack, ctx)) { rec.getOnFire(stack).accept(stack, ctx); - ItemGunBaseNT.setState(stack, GunState.JUST_FIRED); + ItemGunBaseNT.setState(stack, GunState.COOLDOWN); ItemGunBaseNT.setTimer(stack, rec.getDelayAfterFire(stack)); //if not, revert to idle } else { diff --git a/src/main/java/com/hbm/items/weapon/sedna/factory/Lego.java b/src/main/java/com/hbm/items/weapon/sedna/factory/Lego.java index 6863d5627..8546cfa39 100644 --- a/src/main/java/com/hbm/items/weapon/sedna/factory/Lego.java +++ b/src/main/java/com/hbm/items/weapon/sedna/factory/Lego.java @@ -3,9 +3,12 @@ package com.hbm.items.weapon.sedna.factory; import java.util.function.BiConsumer; import java.util.function.BiFunction; +import com.hbm.entity.projectile.EntityBulletBaseMK4; +import com.hbm.items.weapon.sedna.BulletConfig; import com.hbm.items.weapon.sedna.ItemGunBaseNT; import com.hbm.items.weapon.sedna.ItemGunBaseNT.GunState; import com.hbm.items.weapon.sedna.ItemGunBaseNT.LambdaContext; +import com.hbm.items.weapon.sedna.Receiver; import com.hbm.packet.PacketDispatcher; import com.hbm.packet.toclient.GunAnimationPacket; import com.hbm.render.anim.BusAnimation; @@ -38,7 +41,7 @@ public class Lego { public static BiConsumer LAMBDA_STANDARD_FIRE = (stack, ctx) -> { if(ItemGunBaseNT.getState(stack) == GunState.IDLE && ctx.config.getReceivers(stack)[0].getCanFire(stack).apply(stack, ctx)) { - ItemGunBaseNT.setState(stack, GunState.JUST_FIRED); + ItemGunBaseNT.setState(stack, GunState.COOLDOWN); ItemGunBaseNT.setTimer(stack, ctx.config.getReceivers(stack)[0].getDelayAfterFire(stack)); ctx.config.getReceivers(stack)[0].getOnFire(stack).accept(stack, ctx); } @@ -55,19 +58,35 @@ public class Lego { /** JUMPER - bypasses mag testing and just allows constant fire */ public static BiFunction LAMBDA_DEBUG_CAN_FIRE = (stack, ctx) -> { return true; }; + /** simply plays a sound to indicate that the keybind has triggered */ public static BiConsumer LAMBDA_DEBUG_FIRE = (stack, ctx) -> { EntityPlayer player = ctx.player; - player.worldObj.playSoundEffect(player.posX, player.posY, player.posZ, "hbm:weapon.shotgunShoot", 1F, 1F); if(player instanceof EntityPlayerMP) PacketDispatcher.wrapper.sendTo(new GunAnimationPacket(AnimType.CYCLE.ordinal()), (EntityPlayerMP) player); + + double sideOffset = ItemGunBaseNT.getIsAiming(stack) ? 0 : -0.2D; + float aim = ItemGunBaseNT.getIsAiming(stack) ? 0.25F : 1F; + Receiver primary = ctx.config.getReceivers(stack)[0]; + + EntityBulletBaseMK4 mk4 = new EntityBulletBaseMK4(player, (BulletConfig) primary.getMagazine(stack).getType(stack), primary.getBaseDamage(stack), primary.getSpreadMod(stack) * aim, sideOffset, -0.1, 0.75); + player.worldObj.spawnEntityInWorld(mk4); + player.worldObj.playSoundEffect(player.posX, player.posY, player.posZ, "hbm:weapon.shotgunShoot", 1F, 1F); }; + + /** No reload, simply play inspect animation */ + public static BiConsumer LAMBDA_DEBUG_RELOAD = (stack, ctx) -> { + EntityPlayer player = ctx.player; + if(player instanceof EntityPlayerMP) PacketDispatcher.wrapper.sendTo(new GunAnimationPacket(AnimType.INSPECT.ordinal()), (EntityPlayerMP) player); + }; + + /** anims for the DEBUG revolver, mostly a copy of the li'lpip but with some fixes regarding the cylinder movement */ public static BiFunction LAMBDA_DEBUG_ANIMS = (stack, type) -> { switch(type) { case CYCLE: return new BusAnimation() .addBus("RECOIL", new BusAnimationSequence().addKeyframePosition(0, 0, 0, 50).addKeyframePosition(0, 0, -3, 50).addKeyframePosition(0, 0, 0, 250)) - .addBus("HAMMER", new BusAnimationSequence().addKeyframePosition(0, 0, 1, 50).addKeyframePosition(0, 0, 1, 300 + 200).addKeyframePosition(0, 0, 0, 200)) - .addBus("DRUM", new BusAnimationSequence().addKeyframePosition(0, 0, 0, 350 + 200).addKeyframePosition(0, 0, 1, 200)); + .addBus("HAMMER", new BusAnimationSequence().addKeyframePosition(0, 0, 1, 50).addKeyframePosition(0, 0, 1, 300 + 100).addKeyframePosition(0, 0, 0, 200)) + .addBus("DRUM", new BusAnimationSequence().addKeyframePosition(0, 0, 0, 350 + 100).addKeyframePosition(0, 0, 1, 200)); case CYCLE_EMPTY: break; case ALT_CYCLE: break; case EQUIP: return new BusAnimation().addBus("ROTATE", new BusAnimationSequence().addKeyframePosition(-360, 0, 0, 350)); @@ -77,6 +96,7 @@ public class Lego { case RELOAD_END: break; case SPINDOWN: break; case SPINUP: break; + case INSPECT: break; } return null; diff --git a/src/main/java/com/hbm/items/weapon/sedna/mags/IMagazine.java b/src/main/java/com/hbm/items/weapon/sedna/mags/IMagazine.java index 90d6a2337..55d7d4bb7 100644 --- a/src/main/java/com/hbm/items/weapon/sedna/mags/IMagazine.java +++ b/src/main/java/com/hbm/items/weapon/sedna/mags/IMagazine.java @@ -3,6 +3,12 @@ package com.hbm.items.weapon.sedna.mags; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; +/** + * The magazine simply provides the receiver it's attached to with ammo, the receiver does not care where it comes from. + * Therefore it is the mag's responsibility to handle reloading, any type restrictions as well as belt-like action from "magless" guns. + * + * @author hbm + */ public interface IMagazine { /** What ammo is loaded currently */ diff --git a/src/main/java/com/hbm/items/weapon/sedna/mags/MagazineStandardBase.java b/src/main/java/com/hbm/items/weapon/sedna/mags/MagazineStandardBase.java index 818833767..874d14195 100644 --- a/src/main/java/com/hbm/items/weapon/sedna/mags/MagazineStandardBase.java +++ b/src/main/java/com/hbm/items/weapon/sedna/mags/MagazineStandardBase.java @@ -31,8 +31,8 @@ public abstract class MagazineStandardBase implements IMagazine { @Override public Object getType(ItemStack stack) { int type = getMagType(stack, index); - if(type >= 0 && type < acceptedBullets.size()) { - return acceptedBullets.get(type); + if(type >= 0 && type < BulletConfig.configs.size()) { + return BulletConfig.configs.get(type); } return null; } @@ -40,7 +40,7 @@ public abstract class MagazineStandardBase implements IMagazine { @Override public void setType(ItemStack stack, Object type) { if(!(type instanceof BulletConfig)) return; - int i = acceptedBullets.indexOf(type); + int i = BulletConfig.configs.indexOf(type); if(i >= 0) setMagType(stack, index, i); } @@ -49,7 +49,7 @@ public abstract class MagazineStandardBase implements IMagazine { @Override public void setAmount(ItemStack stack, int amount) { setMagCount(stack, index, amount); } // MAG TYPE // - public static int getMagType(ItemStack stack, int index) { return ItemGunBaseNT.getValueInt(stack, KEY_MAG_TYPE + index); } + public static int getMagType(ItemStack stack, int index) { return ItemGunBaseNT.getValueInt(stack, KEY_MAG_TYPE + index); } //TODO: replace with named tags to avoid ID shifting public static void setMagType(ItemStack stack, int index, int value) { ItemGunBaseNT.setValueInt(stack, KEY_MAG_TYPE + index, value); } // MAG COUNT // diff --git a/src/main/java/com/hbm/render/anim/HbmAnimations.java b/src/main/java/com/hbm/render/anim/HbmAnimations.java index 44fff33dc..699703db6 100644 --- a/src/main/java/com/hbm/render/anim/HbmAnimations.java +++ b/src/main/java/com/hbm/render/anim/HbmAnimations.java @@ -27,7 +27,8 @@ public class HbmAnimations { ALT_CYCLE, //animation for alt fire cycles SPINUP, //animation for actionstart SPINDOWN, //animation for actionend - EQUIP //animation for drawing the weapon + EQUIP, //animation for drawing the weapon + INSPECT //animation for inspecting the weapon } // A NOTE ON SHOTGUN STYLE RELOADS diff --git a/src/main/java/com/hbm/render/item/weapon/sedna/ItemRenderDebug.java b/src/main/java/com/hbm/render/item/weapon/sedna/ItemRenderDebug.java index 840b87052..1294c7443 100644 --- a/src/main/java/com/hbm/render/item/weapon/sedna/ItemRenderDebug.java +++ b/src/main/java/com/hbm/render/item/weapon/sedna/ItemRenderDebug.java @@ -35,8 +35,8 @@ public class ItemRenderDebug extends ItemRenderWeaponBase { GL11.glRotated(equipSpin[0], 0, 0, 1); double[] recoil = HbmAnimations.getRelevantTransformation("RECOIL"); - //GL11.glTranslated(-recoil[2], 0, 0); - GL11.glTranslated(0, 0, recoil[2]); + standardAimingTransform(stack, 0, 0, recoil[2], -recoil[2], 0, 0); + GL11.glRotated(recoil[2] * 10, 0, 0, 1); GL11.glShadeModel(GL11.GL_SMOOTH); diff --git a/src/main/resources/assets/hbm/textures/items/gun_upgrade_debug_conversion.png b/src/main/resources/assets/hbm/textures/items/gun_upgrade_debug_conversion.png new file mode 100644 index 0000000000000000000000000000000000000000..e8d8198f2603b0aab87150177090eb389f3f38ca GIT binary patch literal 310 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`EX7WqAsj$Z!;#VfC-t) zp4mWq19FZVFr;xXGpE%Y4$|0^wuWtiGz;?!sg-OD5$EIn7ug(p4)i#Kr>mdKI;Vst E0G0xFApigX literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/hbm/textures/items/gun_upgrade_debug_damage.png b/src/main/resources/assets/hbm/textures/items/gun_upgrade_debug_damage.png new file mode 100644 index 0000000000000000000000000000000000000000..d71b134fdf0936cb4acafc700e3d697137a50bd4 GIT binary patch literal 320 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`EX7WqAsj$Z!;#VfSp>65_d323%4uiyffI5xhPQbj*Q|;X0hM= z$&2!}a_ir}{%+SG@7l&EcUx6>|J)r$_qMhl(8=xny-F}pzp%hm&Xa9-_T~5br#3zB z;9C7aC)wgsxoqB+o$omrB9`rQi4g65vTp6dS2A|u^H^evn51rc+-YEJ6JSix3z^qu zuJGm>`zroJ846)@Tg({_to*=m<-Vjzq3+%%Ar%?PvTSjZ7KN@EDc?D}gA(h{PFT9u zj#ciQ`VAG$sYiGv%y&L1O8B=c+kMSC$pT@A`R4zfU2kM8kSbjH;QkjDZT^Dj8&Y9w QfkD9F>FVdQ&MBb@06ph;wEzGB literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/hbm/textures/items/gun_upgrade_debug_multishot.png b/src/main/resources/assets/hbm/textures/items/gun_upgrade_debug_multishot.png new file mode 100644 index 0000000000000000000000000000000000000000..38180b907381d65563d2570658111bc156785c3f GIT binary patch literal 358 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`EX7WqAsj$Z!;#X#z`!W$>Eak- z(VLvGK)~S9q#t!Qf9#FsUoKJ&+p4p}#4dgl_iBq>jv90Fk01KCKVsMHMj&vEm@a&@ zVf*y`hmZa=o_Fx;LCO35?f>idrHFSOW1n_gQZH`Li3k7JG96Y}y7IlGq=baTj151z z*+9YtA0N4j7@m|c7qJuG^_E{}yK&BwR|z1{@paFs3vz#@-_7cck>%O1Czm#%r!aZP zblo5FtGPGa?DCgU7E7{SZ{+ggPuh>VE{j4Q<_QOvZ|(l*X>4HNu=hab&Pjnr$9Uxq z{a~2APxtU=)!h#^GL$pw6cpU#5>CIo-Br-t)1!Pd%YW~qyAJZYY@Z4A$ithDVtGzo zzL%_~BGKT=UsZE>lG&M;7Q7DT9Bda%gLoMjvJz{f%FdL`2L>F2r>mdKI;Vst0J>L{ A@c;k- literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/hbm/textures/items/gun_upgrade_debug_shotspeed.png b/src/main/resources/assets/hbm/textures/items/gun_upgrade_debug_shotspeed.png new file mode 100644 index 0000000000000000000000000000000000000000..06f5167609cf00df3fe82989a87e946e1565ac94 GIT binary patch literal 349 zcmV-j0iyniP)|q`B106t+#a*LeC9g+VR@9+{$=F~T5GJe7-K4)*7|oq zZ@R)5LvOm;=y`x)yP0G~?j{^76z}kSpILw6w%}$U!