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(EntityGrenadeIFNull.class, "entity_grenade_ironshod_null", 250);
addEntity(EntityFallingNuke.class, "entity_falling_bomb", 1000); addEntity(EntityFallingNuke.class, "entity_falling_bomb", 1000);
addEntity(EntityBulletBaseNT.class, "entity_bullet_mk3", 250, false); addEntity(EntityBulletBaseNT.class, "entity_bullet_mk3", 250, false);
addEntity(EntityBulletBaseMK4.class, "entity_bullet_mk4", 250, false);
addEntity(EntityMinerRocket.class, "entity_miner_lander", 1000); addEntity(EntityMinerRocket.class, "entity_miner_lander", 1000);
addEntity(EntityFogFX.class, "entity_nuclear_fog", 1000); addEntity(EntityFogFX.class, "entity_nuclear_fog", 1000);
addEntity(EntityDuchessGambit.class, "entity_duchessgambit", 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(); this.id = configs.size();
configs.add(this); 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; 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 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 */ /* FIELDS */
/** List of receivers used by the gun, primary and secondary are usually indices 0 and 1 respectively, if applicable */ /** List of receivers used by the gun, primary and secondary are usually indices 0 and 1 respectively, if applicable */
protected Receiver[] receivers; protected Receiver[] receivers_DNA;
protected float durability; protected float durability_DNA;
protected int drawDuration = 0; protected int drawDuration_DNA = 0;
protected Crosshair crosshair; protected Crosshair crosshair_DNA;
protected boolean reloadAnimationsSequential; protected boolean reloadAnimationsSequential_DNA;
/** Lambda functions for clicking shit */ /** Lambda functions for clicking shit */
protected BiConsumer<ItemStack, LambdaContext> onPressPrimary; protected BiConsumer<ItemStack, LambdaContext> onPressPrimary_DNA;
protected BiConsumer<ItemStack, LambdaContext> onPressSecondary; protected BiConsumer<ItemStack, LambdaContext> onPressSecondary_DNA;
protected BiConsumer<ItemStack, LambdaContext> onPressTertiary; protected BiConsumer<ItemStack, LambdaContext> onPressTertiary_DNA;
protected BiConsumer<ItemStack, LambdaContext> onPressReload; protected BiConsumer<ItemStack, LambdaContext> onPressReload_DNA;
/** Lambda functions for releasing the aforementioned shit */ /** Lambda functions for releasing the aforementioned shit */
protected BiConsumer<ItemStack, LambdaContext> onReleasePrimary; protected BiConsumer<ItemStack, LambdaContext> onReleasePrimary_DNA;
protected BiConsumer<ItemStack, LambdaContext> onReleaseSecondary; protected BiConsumer<ItemStack, LambdaContext> onReleaseSecondary_DNA;
protected BiConsumer<ItemStack, LambdaContext> onReleaseTertiary; protected BiConsumer<ItemStack, LambdaContext> onReleaseTertiary_DNA;
protected BiConsumer<ItemStack, LambdaContext> onReleaseReload; protected BiConsumer<ItemStack, LambdaContext> onReleaseReload_DNA;
/** The engine for the state machine that determines the gun's overall behavior */ /** 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 */ /** Lambda that returns the relevant animation for the given params */
protected BiFunction<ItemStack, AnimType, BusAnimation> animations; protected BiFunction<ItemStack, AnimType, BusAnimation> animations_DNA;
/* GETTERS */ /* GETTERS */
public Receiver[] getReceivers(ItemStack stack) { return receivers; } public Receiver[] getReceivers(ItemStack stack) { return WeaponUpgradeManager.eval(receivers_DNA, stack, O_RECEIVERS, this); }
public float getDurability(ItemStack stack) { return durability; } public float getDurability(ItemStack stack) { return WeaponUpgradeManager.eval(durability_DNA, stack, F_DURABILITY, this); }
public int getDrawDuration(ItemStack stack) { return drawDuration; } public int getDrawDuration(ItemStack stack) { return WeaponUpgradeManager.eval(drawDuration_DNA, stack, I_DRAWDURATION, this); }
public Crosshair getCrosshair(ItemStack stack) { return crosshair; } public Crosshair getCrosshair(ItemStack stack) { return WeaponUpgradeManager.eval(crosshair_DNA, stack, O_CROSSHAIR, this); }
public boolean getReloadAnimSequential(ItemStack stack) { return reloadAnimationsSequential; } 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> getPressPrimary(ItemStack stack) { return WeaponUpgradeManager.eval(this.onPressPrimary_DNA, stack, CON_ONPRESSPRIMARY, this); }
public BiConsumer<ItemStack, LambdaContext> getPressSecondary(ItemStack stack) { return this.onPressSecondary; } 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 this.onPressTertiary; } 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 this.onPressReload; } 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> getReleasePrimary(ItemStack stack) { return WeaponUpgradeManager.eval(this.onReleasePrimary_DNA, stack, CON_ONRELEASEPRIMARY, this); }
public BiConsumer<ItemStack, LambdaContext> getReleaseSecondary(ItemStack stack) { return this.onReleaseSecondary; } 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 this.onReleaseTertiary; } 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 this.onReleaseReload; } 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 */ /* SETTERS */
public GunConfig rec(Receiver... receivers) { this.receivers = receivers; return this; } public GunConfig rec(Receiver... receivers) { this.receivers_DNA = receivers; return this; }
public GunConfig dura(float dura) { this.durability = dura; return this; } public GunConfig dura(float dura) { this.durability_DNA = dura; return this; }
public GunConfig draw(int draw) { this.drawDuration = draw; return this; } public GunConfig draw(int draw) { this.drawDuration_DNA = draw; return this; }
public GunConfig crosshair(Crosshair crosshair) { this.crosshair = crosshair; return this; } public GunConfig crosshair(Crosshair crosshair) { this.crosshair_DNA = crosshair; return this; }
//press //press
public GunConfig pp(BiConsumer<ItemStack, LambdaContext> lambda) { this.onPressPrimary = 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 = 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 = 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 = lambda; return this; } public GunConfig pr(BiConsumer<ItemStack, LambdaContext> lambda) { this.onPressReload_DNA = lambda; return this; }
//release //release
public GunConfig rp(BiConsumer<ItemStack, LambdaContext> lambda) { this.onReleasePrimary = 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 = 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 = 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 = lambda; return this; } public GunConfig rr(BiConsumer<ItemStack, LambdaContext> lambda) { this.onReleaseReload_DNA = lambda; return this; }
//decider //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 //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 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_DRAWN = "drawn";
public static final String KEY_AIMING = "aiming"; public static final String KEY_AIMING = "aiming";
public static final String KEY_TIMER = "timer"; public static final String KEY_TIMER = "timer";
@ -43,7 +45,7 @@ public class ItemGunBaseNT extends Item implements IKeybindReceiver, IEquipRecei
private GunConfig config_DNA; private GunConfig config_DNA;
public GunConfig getConfig(ItemStack stack) { public GunConfig getConfig(ItemStack stack) {
return config_DNA; return WeaponUpgradeManager.eval(config_DNA, stack, O_GUNCONFIG, this);
} }
public ItemGunBaseNT(GunConfig cfg) { public ItemGunBaseNT(GunConfig cfg) {
@ -55,7 +57,7 @@ public class ItemGunBaseNT extends Item implements IKeybindReceiver, IEquipRecei
DRAWING, //initial delay after selecting DRAWING, //initial delay after selecting
IDLE, //gun can be fired or reloaded IDLE, //gun can be fired or reloaded
WINDUP, //fire button is down, added delay before fire 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 RELOADING //gun is currently reloading
} }
@ -92,7 +94,15 @@ public class ItemGunBaseNT extends Item implements IKeybindReceiver, IEquipRecei
EntityPlayer player = (EntityPlayer) entity; EntityPlayer player = (EntityPlayer) entity;
if(world.isRemote) { if(world.isRemote) {
if(isHeld && player == MainRegistry.proxy.me()) { 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; prevAimingProgress = aimingProgress;
boolean aiming = this.getIsAiming(stack); boolean aiming = this.getIsAiming(stack);
float aimSpeed = 0.25F; float aimSpeed = 0.25F;

View File

@ -9,39 +9,64 @@ import com.hbm.items.weapon.sedna.mags.IMagazine;
import net.minecraft.item.ItemStack; 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 { public class Receiver {
protected float baseDamage; public static final String F_BASEDAMAGE = "F_BASEDAMAGE";
protected int delayAfterFire; public static final String I_DELAYAFTERFIRE = "I_DELAYAFTERFIRE";
protected int roundsPerCycle = 1; public static final String I_ROUNDSPERCYCLE = "I_ROUNDSPERCYCLE";
protected boolean refireOnHold = false; public static final String F_SPREADMOD = "F_SPREADMOD";
protected CasingEjector ejector = null; public static final String B_REFIREONHOLD = "B_REFIREONHOLD";
protected int reloadDuration; public static final String O_EJECTOR = "O_EJECTOR";
protected IMagazine magazine; public static final String I_RELOADDURATION = "I_RELOADDURATION";
protected BiFunction<ItemStack, LambdaContext, Boolean> canFire; public static final String O_MAGAZINE = "O_MAGAZINE";
protected BiConsumer<ItemStack, LambdaContext> onFire; 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 */ /* GETTERS */
public float getBaseDamage(ItemStack stack) { return this.baseDamage; } public float getBaseDamage(ItemStack stack) { return WeaponUpgradeManager.eval(this.baseDamage_DNA, stack, F_BASEDAMAGE, this); }
public int getDelayAfterFire(ItemStack stack) { return this.delayAfterFire; } public int getDelayAfterFire(ItemStack stack) { return WeaponUpgradeManager.eval(this.delayAfterFire_DNA, stack, I_DELAYAFTERFIRE, this); }
public int getRoundsPerCycle(ItemStack stack) { return this.roundsPerCycle; } public int getRoundsPerCycle(ItemStack stack) { return WeaponUpgradeManager.eval(this.roundsPerCycle_DNA, stack, I_ROUNDSPERCYCLE, this); }
public boolean getRefireOnHold(ItemStack stack) { return this.refireOnHold; } public float getSpreadMod(ItemStack stack) { return WeaponUpgradeManager.eval(this.spreadMod_DNA, stack, F_SPREADMOD, this); }
public CasingEjector getEjector(ItemStack stack) { return this.ejector; } public boolean getRefireOnHold(ItemStack stack) { return WeaponUpgradeManager.eval(this.refireOnHold_DNA, stack, B_REFIREONHOLD, this); }
public int getReloadDuration(ItemStack stack) { return this.reloadDuration; } public CasingEjector getEjector(ItemStack stack) { return WeaponUpgradeManager.eval(this.ejector_DNA, stack, O_EJECTOR, this); }
public IMagazine getMagazine(ItemStack stack) { return this.magazine; } 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 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 this.onFire; } public BiConsumer<ItemStack, LambdaContext> getOnFire(ItemStack stack) { return WeaponUpgradeManager.eval(this.onFire_DNA, stack, CON_ONFIRE, this); }
/* SETTERS */ /* SETTERS */
public Receiver dmg(float dmg) { this.baseDamage = dmg; return this; } public Receiver dmg(float dmg) { this.baseDamage_DNA = dmg; return this; }
public Receiver delay(int delay) { this.delayAfterFire = delay; return this; } public Receiver delay(int delay) { this.delayAfterFire_DNA = delay; return this; }
public Receiver rounds(int rounds) { this.roundsPerCycle = rounds; return this; } public Receiver rounds(int rounds) { this.roundsPerCycle_DNA = rounds; return this; }
public Receiver auto(boolean auto) { this.refireOnHold = auto; return this; } public Receiver spread(int spread) { this.spreadMod_DNA = spread; return this; }
public Receiver burst(CasingEjector ejector) { this.ejector = ejector; return this; } public Receiver auto(boolean auto) { this.refireOnHold_DNA = auto; return this; }
public Receiver reload(int delay) { this.reloadDuration = delay; return this; } public Receiver burst(CasingEjector ejector) { this.ejector_DNA = ejector; return this; }
public Receiver mag(IMagazine magazine) { this.magazine = magazine; 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 canFire(BiFunction<ItemStack, LambdaContext, Boolean> lambda) { this.canFire_DNA = lambda; return this; }
public Receiver fire(BiConsumer<ItemStack, LambdaContext> lambda) { this.onFire = 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"); 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() ModItems.gun_debug = new ItemGunBaseNT(new GunConfig()
.dura(600).draw(15).crosshair(Crosshair.L_CLASSIC) .dura(600).draw(15).crosshair(Crosshair.L_CLASSIC)
.rec(new Receiver() .rec(new Receiver(0)
.dmg(10F).delay(10).mag(new MagazineRevolverDrum(0, 6).addConfigs(ammo_debug)) .dmg(10F).delay(12).mag(new MagazineRevolverDrum(0, 6).addConfigs(ammo_debug))
.canFire(Lego.LAMBDA_DEBUG_CAN_FIRE).fire(Lego.LAMBDA_DEBUG_FIRE)) .canFire(Lego.LAMBDA_DEBUG_CAN_FIRE).fire(Lego.LAMBDA_DEBUG_FIRE))
.pr(Lego.LAMBDA_STANDARD_RELOAD) .pr(Lego.LAMBDA_STANDARD_RELOAD)
.pp(Lego.LAMBDA_STANDARD_FIRE) .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 */ /** 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) { 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; GunConfig cfg = ctx.config;
Receiver rec = cfg.getReceivers(stack)[recIndex]; Receiver rec = cfg.getReceivers(stack)[recIndex];
@ -72,7 +72,7 @@ public class GunStateDecider {
//if there's a bullet loaded, fire again //if there's a bullet loaded, fire again
if(rec.getCanFire(stack).apply(stack, ctx)) { if(rec.getCanFire(stack).apply(stack, ctx)) {
rec.getOnFire(stack).accept(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)); ItemGunBaseNT.setTimer(stack, rec.getDelayAfterFire(stack));
//if not, revert to idle //if not, revert to idle
} else { } else {

View File

@ -3,9 +3,12 @@ package com.hbm.items.weapon.sedna.factory;
import java.util.function.BiConsumer; import java.util.function.BiConsumer;
import java.util.function.BiFunction; 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;
import com.hbm.items.weapon.sedna.ItemGunBaseNT.GunState; import com.hbm.items.weapon.sedna.ItemGunBaseNT.GunState;
import com.hbm.items.weapon.sedna.ItemGunBaseNT.LambdaContext; import com.hbm.items.weapon.sedna.ItemGunBaseNT.LambdaContext;
import com.hbm.items.weapon.sedna.Receiver;
import com.hbm.packet.PacketDispatcher; import com.hbm.packet.PacketDispatcher;
import com.hbm.packet.toclient.GunAnimationPacket; import com.hbm.packet.toclient.GunAnimationPacket;
import com.hbm.render.anim.BusAnimation; import com.hbm.render.anim.BusAnimation;
@ -38,7 +41,7 @@ public class Lego {
public static BiConsumer<ItemStack, LambdaContext> LAMBDA_STANDARD_FIRE = (stack, ctx) -> { 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)) { 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)); ItemGunBaseNT.setTimer(stack, ctx.config.getReceivers(stack)[0].getDelayAfterFire(stack));
ctx.config.getReceivers(stack)[0].getOnFire(stack).accept(stack, ctx); 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 */ /** JUMPER - bypasses mag testing and just allows constant fire */
public static BiFunction<ItemStack, LambdaContext, Boolean> LAMBDA_DEBUG_CAN_FIRE = (stack, ctx) -> { return true; }; 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 */ /** simply plays a sound to indicate that the keybind has triggered */
public static BiConsumer<ItemStack, LambdaContext> LAMBDA_DEBUG_FIRE = (stack, ctx) -> { public static BiConsumer<ItemStack, LambdaContext> LAMBDA_DEBUG_FIRE = (stack, ctx) -> {
EntityPlayer player = ctx.player; 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); 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) -> { public static BiFunction<ItemStack, AnimType, BusAnimation> LAMBDA_DEBUG_ANIMS = (stack, type) -> {
switch(type) { switch(type) {
case CYCLE: case CYCLE:
return new BusAnimation() return new BusAnimation()
.addBus("RECOIL", new BusAnimationSequence().addKeyframePosition(0, 0, 0, 50).addKeyframePosition(0, 0, -3, 50).addKeyframePosition(0, 0, 0, 250)) .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("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 + 200).addKeyframePosition(0, 0, 1, 200)); .addBus("DRUM", new BusAnimationSequence().addKeyframePosition(0, 0, 0, 350 + 100).addKeyframePosition(0, 0, 1, 200));
case CYCLE_EMPTY: break; case CYCLE_EMPTY: break;
case ALT_CYCLE: break; case ALT_CYCLE: break;
case EQUIP: return new BusAnimation().addBus("ROTATE", new BusAnimationSequence().addKeyframePosition(-360, 0, 0, 350)); 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 RELOAD_END: break;
case SPINDOWN: break; case SPINDOWN: break;
case SPINUP: break; case SPINUP: break;
case INSPECT: break;
} }
return null; return null;

View File

@ -3,6 +3,12 @@ package com.hbm.items.weapon.sedna.mags;
import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack; 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 { public interface IMagazine {
/** What ammo is loaded currently */ /** What ammo is loaded currently */

View File

@ -31,8 +31,8 @@ public abstract class MagazineStandardBase implements IMagazine {
@Override @Override
public Object getType(ItemStack stack) { public Object getType(ItemStack stack) {
int type = getMagType(stack, index); int type = getMagType(stack, index);
if(type >= 0 && type < acceptedBullets.size()) { if(type >= 0 && type < BulletConfig.configs.size()) {
return acceptedBullets.get(type); return BulletConfig.configs.get(type);
} }
return null; return null;
} }
@ -40,7 +40,7 @@ public abstract class MagazineStandardBase implements IMagazine {
@Override @Override
public void setType(ItemStack stack, Object type) { public void setType(ItemStack stack, Object type) {
if(!(type instanceof BulletConfig)) return; if(!(type instanceof BulletConfig)) return;
int i = acceptedBullets.indexOf(type); int i = BulletConfig.configs.indexOf(type);
if(i >= 0) setMagType(stack, index, i); 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); } @Override public void setAmount(ItemStack stack, int amount) { setMagCount(stack, index, amount); }
// MAG TYPE // // 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); } public static void setMagType(ItemStack stack, int index, int value) { ItemGunBaseNT.setValueInt(stack, KEY_MAG_TYPE + index, value); }
// MAG COUNT // // MAG COUNT //

View File

@ -27,7 +27,8 @@ public class HbmAnimations {
ALT_CYCLE, //animation for alt fire cycles ALT_CYCLE, //animation for alt fire cycles
SPINUP, //animation for actionstart SPINUP, //animation for actionstart
SPINDOWN, //animation for actionend 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 // A NOTE ON SHOTGUN STYLE RELOADS

View File

@ -35,8 +35,8 @@ public class ItemRenderDebug extends ItemRenderWeaponBase {
GL11.glRotated(equipSpin[0], 0, 0, 1); GL11.glRotated(equipSpin[0], 0, 0, 1);
double[] recoil = HbmAnimations.getRelevantTransformation("RECOIL"); double[] recoil = HbmAnimations.getRelevantTransformation("RECOIL");
//GL11.glTranslated(-recoil[2], 0, 0); standardAimingTransform(stack, 0, 0, recoil[2], -recoil[2], 0, 0);
GL11.glTranslated(0, 0, recoil[2]);
GL11.glRotated(recoil[2] * 10, 0, 0, 1); GL11.glRotated(recoil[2] * 10, 0, 0, 1);
GL11.glShadeModel(GL11.GL_SMOOTH); 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