a ton of gun stuff

This commit is contained in:
Bob 2024-09-17 21:30:34 +02:00
parent 3a81e79554
commit 1384f14fe3
19 changed files with 319 additions and 91 deletions

View File

@ -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);

View File

@ -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; }
}

View File

@ -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; }
}

View File

@ -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<ItemStack, LambdaContext> onPressPrimary;
protected BiConsumer<ItemStack, LambdaContext> onPressSecondary;
protected BiConsumer<ItemStack, LambdaContext> onPressTertiary;
protected BiConsumer<ItemStack, LambdaContext> onPressReload;
protected BiConsumer<ItemStack, LambdaContext> onPressPrimary_DNA;
protected BiConsumer<ItemStack, LambdaContext> onPressSecondary_DNA;
protected BiConsumer<ItemStack, LambdaContext> onPressTertiary_DNA;
protected BiConsumer<ItemStack, LambdaContext> onPressReload_DNA;
/** Lambda functions for releasing the aforementioned shit */
protected BiConsumer<ItemStack, LambdaContext> onReleasePrimary;
protected BiConsumer<ItemStack, LambdaContext> onReleaseSecondary;
protected BiConsumer<ItemStack, LambdaContext> onReleaseTertiary;
protected BiConsumer<ItemStack, LambdaContext> onReleaseReload;
protected BiConsumer<ItemStack, LambdaContext> onReleasePrimary_DNA;
protected BiConsumer<ItemStack, LambdaContext> onReleaseSecondary_DNA;
protected BiConsumer<ItemStack, LambdaContext> onReleaseTertiary_DNA;
protected BiConsumer<ItemStack, LambdaContext> onReleaseReload_DNA;
/** The engine for the state machine that determines the gun's overall behavior */
protected BiConsumer<ItemStack, LambdaContext> decider;
protected BiConsumer<ItemStack, LambdaContext> decider_DNA;
/** Lambda that returns the relevant animation for the given params */
protected BiFunction<ItemStack, AnimType, BusAnimation> animations;
protected BiFunction<ItemStack, AnimType, BusAnimation> 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<ItemStack, LambdaContext> getPressPrimary(ItemStack stack) { return this.onPressPrimary; }
public BiConsumer<ItemStack, LambdaContext> getPressSecondary(ItemStack stack) { return this.onPressSecondary; }
public BiConsumer<ItemStack, LambdaContext> getPressTertiary(ItemStack stack) { return this.onPressTertiary; }
public BiConsumer<ItemStack, LambdaContext> getPressReload(ItemStack stack) { return this.onPressReload; }
public BiConsumer<ItemStack, LambdaContext> getPressPrimary(ItemStack stack) { return WeaponUpgradeManager.eval(this.onPressPrimary_DNA, stack, CON_ONPRESSPRIMARY, this); }
public BiConsumer<ItemStack, LambdaContext> getPressSecondary(ItemStack stack) { return WeaponUpgradeManager.eval(this.onPressSecondary_DNA, stack, CON_ONPRESSSECONDARY, this); }
public BiConsumer<ItemStack, LambdaContext> getPressTertiary(ItemStack stack) { return WeaponUpgradeManager.eval(this.onPressTertiary_DNA, stack, CON_ONPRESSTERTIARY, this); }
public BiConsumer<ItemStack, LambdaContext> getPressReload(ItemStack stack) { return WeaponUpgradeManager.eval(this.onPressReload_DNA, stack, CON_ONPRESSRELOAD, this); }
public BiConsumer<ItemStack, LambdaContext> getReleasePrimary(ItemStack stack) { return this.onReleasePrimary; }
public BiConsumer<ItemStack, LambdaContext> getReleaseSecondary(ItemStack stack) { return this.onReleaseSecondary; }
public BiConsumer<ItemStack, LambdaContext> getReleaseTertiary(ItemStack stack) { return this.onReleaseTertiary; }
public BiConsumer<ItemStack, LambdaContext> getReleaseReload(ItemStack stack) { return this.onReleaseReload; }
public BiConsumer<ItemStack, LambdaContext> getReleasePrimary(ItemStack stack) { return WeaponUpgradeManager.eval(this.onReleasePrimary_DNA, stack, CON_ONRELEASEPRIMARY, this); }
public BiConsumer<ItemStack, LambdaContext> getReleaseSecondary(ItemStack stack) { return WeaponUpgradeManager.eval(this.onReleaseSecondary_DNA, stack, CON_ONRELEASESECONDARY, this); }
public BiConsumer<ItemStack, LambdaContext> getReleaseTertiary(ItemStack stack) { return WeaponUpgradeManager.eval(this.onReleaseTertiary_DNA, stack, CON_ONRELEASETERTIARY, this); }
public BiConsumer<ItemStack, LambdaContext> getReleaseReload(ItemStack stack) { return WeaponUpgradeManager.eval(this.onReleaseReload_DNA, stack, CON_ONRELEASERELOAD, this); }
public BiConsumer<ItemStack, LambdaContext> getDecider(ItemStack stack) { return this.decider; }
public BiConsumer<ItemStack, LambdaContext> getDecider(ItemStack stack) { return WeaponUpgradeManager.eval(this.decider_DNA, stack, CON_DECIDER, this); }
public BiFunction<ItemStack, AnimType, BusAnimation> getAnims(ItemStack stack) { return this.animations; }
public BiFunction<ItemStack, AnimType, BusAnimation> 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<ItemStack, LambdaContext> lambda) { this.onPressPrimary = lambda; return this; }
public GunConfig ps(BiConsumer<ItemStack, LambdaContext> lambda) { this.onPressSecondary = lambda; return this; }
public GunConfig pt(BiConsumer<ItemStack, LambdaContext> lambda) { this.onPressTertiary = lambda; return this; }
public GunConfig pr(BiConsumer<ItemStack, LambdaContext> lambda) { this.onPressReload = lambda; return this; }
public GunConfig pp(BiConsumer<ItemStack, LambdaContext> lambda) { this.onPressPrimary_DNA = lambda; return this; }
public GunConfig ps(BiConsumer<ItemStack, LambdaContext> lambda) { this.onPressSecondary_DNA = lambda; return this; }
public GunConfig pt(BiConsumer<ItemStack, LambdaContext> lambda) { this.onPressTertiary_DNA = lambda; return this; }
public GunConfig pr(BiConsumer<ItemStack, LambdaContext> lambda) { this.onPressReload_DNA = lambda; return this; }
//release
public GunConfig rp(BiConsumer<ItemStack, LambdaContext> lambda) { this.onReleasePrimary = lambda; return this; }
public GunConfig rs(BiConsumer<ItemStack, LambdaContext> lambda) { this.onReleaseSecondary = lambda; return this; }
public GunConfig rt(BiConsumer<ItemStack, LambdaContext> lambda) { this.onReleaseTertiary = lambda; return this; }
public GunConfig rr(BiConsumer<ItemStack, LambdaContext> lambda) { this.onReleaseReload = lambda; return this; }
public GunConfig rp(BiConsumer<ItemStack, LambdaContext> lambda) { this.onReleasePrimary_DNA = lambda; return this; }
public GunConfig rs(BiConsumer<ItemStack, LambdaContext> lambda) { this.onReleaseSecondary_DNA = lambda; return this; }
public GunConfig rt(BiConsumer<ItemStack, LambdaContext> lambda) { this.onReleaseTertiary_DNA = lambda; return this; }
public GunConfig rr(BiConsumer<ItemStack, LambdaContext> lambda) { this.onReleaseReload_DNA = lambda; return this; }
//decider
public GunConfig decider(BiConsumer<ItemStack, LambdaContext> lambda) { this.decider = lambda; return this; }
public GunConfig decider(BiConsumer<ItemStack, LambdaContext> lambda) { this.decider_DNA = lambda; return this; }
//anims
public GunConfig anim(BiFunction<ItemStack, AnimType, BusAnimation> lambda) { this.animations = lambda; return this; }
public GunConfig anim(BiFunction<ItemStack, AnimType, BusAnimation> lambda) { this.animations_DNA = lambda; return this; }
}

View File

@ -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> T eval(T base, ItemStack stack, String key, Object parent) { return base; }
}

View File

@ -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;

View File

@ -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<ItemStack, LambdaContext, Boolean> canFire;
protected BiConsumer<ItemStack, LambdaContext> 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<ItemStack, LambdaContext, Boolean> canFire_DNA;
protected BiConsumer<ItemStack, LambdaContext> 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<ItemStack, LambdaContext, Boolean> getCanFire(ItemStack stack) { return this.canFire; }
public BiConsumer<ItemStack, LambdaContext> getOnFire(ItemStack stack) { return this.onFire; }
public BiFunction<ItemStack, LambdaContext, Boolean> getCanFire(ItemStack stack) { return WeaponUpgradeManager.eval(this.canFire_DNA, stack, FUN_CANFIRE, this); }
public BiConsumer<ItemStack, LambdaContext> 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<ItemStack, LambdaContext, Boolean> lambda) { this.canFire = lambda; return this; }
public Receiver fire(BiConsumer<ItemStack, LambdaContext> lambda) { this.onFire = lambda; return this; }
public Receiver canFire(BiFunction<ItemStack, LambdaContext, Boolean> lambda) { this.canFire_DNA = lambda; return this; }
public Receiver fire(BiConsumer<ItemStack, LambdaContext> lambda) { this.onFire_DNA = lambda; return this; }
}

View File

@ -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> 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;
}
}

View File

@ -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)

View File

@ -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 {

View File

@ -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<ItemStack, LambdaContext> 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<ItemStack, LambdaContext, Boolean> LAMBDA_DEBUG_CAN_FIRE = (stack, ctx) -> { return true; };
/** simply plays a sound to indicate that the keybind has triggered */
public static BiConsumer<ItemStack, LambdaContext> 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<ItemStack, LambdaContext> 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<ItemStack, AnimType, BusAnimation> 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;

View File

@ -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 */

View File

@ -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 //

View File

@ -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

View File

@ -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);

Binary file not shown.

After

Width:  |  Height:  |  Size: 310 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 320 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 358 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 349 B