mirror of
https://github.com/HbmMods/Hbm-s-Nuclear-Tech-GIT.git
synced 2026-01-25 10:32:49 +00:00
offsets and casing ejection sillies
This commit is contained in:
parent
109e710112
commit
c8d40f0d35
@ -5,7 +5,6 @@ import com.hbm.handler.MultiblockHandlerXR;
|
||||
import com.hbm.tileentity.machine.rbmk.TileEntityCraneConsole;
|
||||
|
||||
import api.hbm.block.IToolable;
|
||||
import api.hbm.block.IToolable.ToolType;
|
||||
import net.minecraft.block.material.Material;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
|
||||
@ -42,7 +42,7 @@ public class RotaryFurnaceRecipes extends SerializableRecipe {
|
||||
recipes.add(new RotaryFurnaceRecipe(new MaterialStack(MAT_STEEL, INGOT.q(3)), 100, 100, new OreDictStack(IRON.fragment(), 9), new OreDictStack(ANY_COKE.gem())));
|
||||
recipes.add(new RotaryFurnaceRecipe(new MaterialStack(MAT_STEEL, INGOT.q(4)), 200, 100, new OreDictStack(IRON.fragment(), 9), new OreDictStack(ANY_COKE.gem()), new ComparableStack(ModItems.powder_flux)));
|
||||
|
||||
recipes.add(new RotaryFurnaceRecipe(new MaterialStack(MAT_DESH, INGOT.q(1)), 100, 200, new FluidStack(Fluids.MERCURY, 100), new ComparableStack(ModItems.powder_desh_mix), new OreDictStack(COAL.dust())));
|
||||
recipes.add(new RotaryFurnaceRecipe(new MaterialStack(MAT_DESH, INGOT.q(1)), 100, 200, new FluidStack(Fluids.LIGHTOIL, 100), new ComparableStack(ModItems.powder_desh_ready)));
|
||||
recipes.add(new RotaryFurnaceRecipe(new MaterialStack(MAT_SATURN, INGOT.q(2)), 200, 400, new FluidStack(Fluids.HEATINGOIL, 250), new OreDictStack(DURA.dust(), 2), new OreDictStack(CU.dust())));
|
||||
|
||||
recipes.add(new RotaryFurnaceRecipe(new MaterialStack(MAT_GUNMETAL, INGOT.q(4)), 200, 100, new OreDictStack(CU.ingot(), 3), new OreDictStack(AL.ingot(), 1)));
|
||||
|
||||
@ -106,6 +106,7 @@ public class GunConfig {
|
||||
public GunConfig jam(int jam) { this.jamDuration_DNA = jam; return this; }
|
||||
public GunConfig crosshair(Crosshair crosshair) { this.crosshair_DNA = crosshair; return this; }
|
||||
public GunConfig smoke(boolean doesSmoke) { this.doesSmoke_DNA = doesSmoke; return this; }
|
||||
public GunConfig reloadSequential(boolean flag) { this.reloadAnimationsSequential_DNA = flag; return this; }
|
||||
|
||||
public GunConfig orchestra(BiConsumer<ItemStack, LambdaContext> orchestra) { this.orchestra_DNA = orchestra; return this; }
|
||||
|
||||
|
||||
@ -8,6 +8,7 @@ import com.hbm.items.weapon.sedna.ItemGunBaseNT.LambdaContext;
|
||||
import com.hbm.items.weapon.sedna.mags.IMagazine;
|
||||
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.Vec3;
|
||||
|
||||
/**
|
||||
* 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
|
||||
@ -30,6 +31,7 @@ public class Receiver {
|
||||
public static final String F_FIREVOLUME = "F_FIREVOLUME";
|
||||
public static final String F_FIREPITCH = "F_FIREPITCH";
|
||||
public static final String O_MAGAZINE = "O_MAGAZINE";
|
||||
public static final String O_PROJECTILEOFFSET = "O_PROJECTILEOFFSET";
|
||||
public static final String FUN_CANFIRE = "FUN_CANFIRE";
|
||||
public static final String CON_ONFIRE = "CON_ONFIRE";
|
||||
public static final String CON_ONRECOIL = "CON_ONRECOIL";
|
||||
@ -52,40 +54,43 @@ public class Receiver {
|
||||
protected float fireVolume_DNA = 1.0F;
|
||||
protected float firePitch_DNA = 1.0F;
|
||||
protected IMagazine magazine_DNA;
|
||||
protected Vec3 projectileOffset_DNA = Vec3.createVectorHelper(0, 0, 0);
|
||||
protected BiFunction<ItemStack, LambdaContext, Boolean> canFire_DNA;
|
||||
protected BiConsumer<ItemStack, LambdaContext> onFire_DNA;
|
||||
protected BiConsumer<ItemStack, LambdaContext> onRecoil_DNA;
|
||||
|
||||
/* GETTERS */
|
||||
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 getGunSpread(ItemStack stack) { return WeaponUpgradeManager.eval(this.spreadModExtra_DNA, stack, F_SPREADMOD, this); }
|
||||
public boolean getRefireOnHold(ItemStack stack) { return WeaponUpgradeManager.eval(this.refireOnHold_DNA, stack, B_REFIREONHOLD, this); }
|
||||
public boolean getDoesDryFire(ItemStack stack) { return WeaponUpgradeManager.eval(this.doesDryFire_DNA, stack, B_DOESDRYFIRE, this); }
|
||||
public CasingEjector getEjector(ItemStack stack) { return WeaponUpgradeManager.eval(this.ejector_DNA, stack, O_EJECTOR, this); }
|
||||
public boolean getEjectOnFire(ItemStack stack) { return WeaponUpgradeManager.eval(this.ejectOnFire_DNA, stack, B_EJECTONFIRE, this); }
|
||||
public int getReloadDuration(ItemStack stack) { return WeaponUpgradeManager.eval(this.reloadDuration_DNA, stack, I_RELOADDURATION, this); }
|
||||
public String getFireSound(ItemStack stack) { return WeaponUpgradeManager.eval(this.fireSound_DNA, stack, S_FIRESOUND, this); }
|
||||
public float getFireVolume(ItemStack stack) { return WeaponUpgradeManager.eval(this.fireVolume_DNA, stack, F_FIREVOLUME, this); }
|
||||
public float getFirePitch(ItemStack stack) { return WeaponUpgradeManager.eval(this.firePitch_DNA, stack, F_FIREPITCH, this); }
|
||||
public IMagazine getMagazine(ItemStack stack) { return WeaponUpgradeManager.eval(this.magazine_DNA, stack, O_MAGAZINE, this); }
|
||||
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 getGunSpread(ItemStack stack) { return WeaponUpgradeManager.eval(this.spreadModExtra_DNA, stack, F_SPREADMOD, this); }
|
||||
public boolean getRefireOnHold(ItemStack stack) { return WeaponUpgradeManager.eval(this.refireOnHold_DNA, stack, B_REFIREONHOLD, this); }
|
||||
public boolean getDoesDryFire(ItemStack stack) { return WeaponUpgradeManager.eval(this.doesDryFire_DNA, stack, B_DOESDRYFIRE, this); }
|
||||
public CasingEjector getEjector(ItemStack stack) { return WeaponUpgradeManager.eval(this.ejector_DNA, stack, O_EJECTOR, this); }
|
||||
public boolean getEjectOnFire(ItemStack stack) { return WeaponUpgradeManager.eval(this.ejectOnFire_DNA, stack, B_EJECTONFIRE, this); }
|
||||
public int getReloadDuration(ItemStack stack) { return WeaponUpgradeManager.eval(this.reloadDuration_DNA, stack, I_RELOADDURATION, this); }
|
||||
public String getFireSound(ItemStack stack) { return WeaponUpgradeManager.eval(this.fireSound_DNA, stack, S_FIRESOUND, this); }
|
||||
public float getFireVolume(ItemStack stack) { return WeaponUpgradeManager.eval(this.fireVolume_DNA, stack, F_FIREVOLUME, this); }
|
||||
public float getFirePitch(ItemStack stack) { return WeaponUpgradeManager.eval(this.firePitch_DNA, stack, F_FIREPITCH, this); }
|
||||
public IMagazine getMagazine(ItemStack stack) { return WeaponUpgradeManager.eval(this.magazine_DNA, stack, O_MAGAZINE, this); }
|
||||
public Vec3 getProjectileOffset(ItemStack stack) { return WeaponUpgradeManager.eval(this.projectileOffset_DNA, stack, O_PROJECTILEOFFSET, this); }
|
||||
|
||||
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); }
|
||||
public BiConsumer<ItemStack, LambdaContext> getRecoil(ItemStack stack) { return WeaponUpgradeManager.eval(this.onRecoil_DNA, stack, CON_ONRECOIL, this); }
|
||||
|
||||
/* SETTERS */
|
||||
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.spreadModExtra_DNA = spread; return this; }
|
||||
public Receiver auto(boolean auto) { this.refireOnHold_DNA = auto; return this; }
|
||||
public Receiver dryfire(boolean dryfire) { this.doesDryFire_DNA = dryfire; return this; }
|
||||
public Receiver ejector(CasingEjector ejector) { this.ejector_DNA = ejector; return this; }
|
||||
public Receiver ejectOnFire(boolean eject) { this.ejectOnFire_DNA = eject; 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 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.spreadModExtra_DNA = spread; return this; }
|
||||
public Receiver auto(boolean auto) { this.refireOnHold_DNA = auto; return this; }
|
||||
public Receiver dryfire(boolean dryfire) { this.doesDryFire_DNA = dryfire; return this; }
|
||||
public Receiver ejector(CasingEjector ejector) { this.ejector_DNA = ejector; return this; }
|
||||
public Receiver ejectOnFire(boolean eject) { this.ejectOnFire_DNA = eject; 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 offset(double f, double u, double s) { this.projectileOffset_DNA = Vec3.createVectorHelper(f, u, s); 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; }
|
||||
|
||||
@ -40,6 +40,7 @@ public class GunFactory {
|
||||
.dmg(10F).delay(14).reload(46).sound("hbm:weapon.44Shoot", 1.0F, 1.0F)
|
||||
.mag(new MagazineFullReload(0, 12).addConfigs(ammo_debug, ammo_debug_buckshot))
|
||||
.ejector(new CasingEjector().setMotion(0, -0.1, 0).setAngleRange(0.01F, 0.025F))
|
||||
.offset(0.75, -0.0625, -0.3125D)
|
||||
.canFire(Lego.LAMBDA_STANDARD_CAN_FIRE).fire(Lego.LAMBDA_STANDARD_FIRE))
|
||||
.pp(Lego.LAMBDA_STANDARD_CLICK_PRIMARY) .pr(Lego.LAMBDA_STANDARD_RELOAD) .pt(Lego.LAMBDA_TOGGLE_AIM)
|
||||
.decider(GunStateDecider.LAMBDA_STANDARD_DECIDER)
|
||||
@ -55,14 +56,8 @@ public class GunFactory {
|
||||
}
|
||||
|
||||
public static enum EnumAmmo {
|
||||
STONE,
|
||||
STONE_AP,
|
||||
STONE_IRON,
|
||||
STONE_SHOT,
|
||||
M357_SP,
|
||||
M357_FMJ,
|
||||
M357_JHP,
|
||||
M357_AP,
|
||||
M357_EXPRESS,
|
||||
STONE, STONE_AP, STONE_IRON, STONE_SHOT,
|
||||
M357_SP, M357_FMJ, M357_JHP, M357_AP, M357_EXPRESS,
|
||||
M44_SP, M44_FMJ, M44_JHP, M44_AP, M44_EXPRESS,
|
||||
}
|
||||
}
|
||||
|
||||
@ -63,6 +63,7 @@ public class GunStateDecider {
|
||||
if(cfg.getReceivers(stack)[recIndex].getMagazine(stack).canReload(stack, player)) {
|
||||
ItemGunBaseNT.setState(stack, GunState.RELOADING);
|
||||
ItemGunBaseNT.setTimer(stack, cfg.getReceivers(stack)[recIndex].getReloadDuration(stack));
|
||||
ItemGunBaseNT.playAnimation(player, stack, AnimType.RELOAD_CYCLE);
|
||||
//if no more reloading can be done, go idle
|
||||
} else {
|
||||
|
||||
@ -73,6 +74,7 @@ public class GunStateDecider {
|
||||
} else {
|
||||
ItemGunBaseNT.setState(stack, GunState.IDLE);
|
||||
ItemGunBaseNT.setTimer(stack, 0);
|
||||
ItemGunBaseNT.playAnimation(player, stack, AnimType.RELOAD_END);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -18,6 +18,7 @@ import com.hbm.render.anim.HbmAnimations.AnimType;
|
||||
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.Vec3;
|
||||
|
||||
/**
|
||||
* "LEGO" - i.e. standardized building blocks which can be used to set up gun configs easily.
|
||||
@ -39,11 +40,12 @@ public class Lego {
|
||||
if(state == GunState.IDLE) {
|
||||
|
||||
ItemGunBaseNT.setIsAiming(stack, false);
|
||||
IMagazine mag = rec.getMagazine(stack);
|
||||
|
||||
if(rec.getMagazine(stack).canReload(stack, ctx.player)) {
|
||||
if(mag.canReload(stack, ctx.player)) {
|
||||
ItemGunBaseNT.setState(stack, GunState.RELOADING);
|
||||
ItemGunBaseNT.setTimer(stack, rec.getReloadDuration(stack));
|
||||
ItemGunBaseNT.playAnimation(player, stack, AnimType.RELOAD);
|
||||
ItemGunBaseNT.playAnimation(player, stack, mag.getAmount(stack) == 0 ? AnimType.RELOAD_EMPTY : AnimType.RELOAD);
|
||||
} else {
|
||||
ItemGunBaseNT.playAnimation(player, stack, AnimType.INSPECT);
|
||||
}
|
||||
@ -104,19 +106,23 @@ public class Lego {
|
||||
EntityPlayer player = ctx.player;
|
||||
ItemGunBaseNT.playAnimation(player, stack, AnimType.CYCLE);
|
||||
|
||||
double sideOffset = ItemGunBaseNT.getIsAiming(stack) ? 0 : -0.3125D;
|
||||
float aim = ItemGunBaseNT.getIsAiming(stack) ? 0.25F : 1F;
|
||||
Receiver primary = ctx.config.getReceivers(stack)[0];
|
||||
IMagazine mag = primary.getMagazine(stack);
|
||||
BulletConfig config = (BulletConfig) mag.getType(stack);
|
||||
|
||||
Vec3 offset = primary.getProjectileOffset(stack);
|
||||
double forwardOffset = offset.xCoord;
|
||||
double heightOffset = offset.yCoord;
|
||||
double sideOffset = ItemGunBaseNT.getIsAiming(stack) ? 0 : offset.zCoord;
|
||||
|
||||
int projectiles = config.projectilesMin;
|
||||
if(config.projectilesMax > config.projectilesMin) projectiles += player.getRNG().nextInt(config.projectilesMax - config.projectilesMin + 1);
|
||||
|
||||
for(int i = 0; i < projectiles; i++) {
|
||||
float damage = primary.getBaseDamage(stack) * getStandardWearDamage(stack, ctx.config);
|
||||
float spread = primary.getGunSpread(stack) * aim + getStandardWearSpread(stack, ctx.config) * 0.125F;
|
||||
EntityBulletBaseMK4 mk4 = new EntityBulletBaseMK4(player, config, damage, spread, sideOffset, -0.0625, 0.75);
|
||||
EntityBulletBaseMK4 mk4 = new EntityBulletBaseMK4(player, config, damage, spread, sideOffset, heightOffset, forwardOffset);
|
||||
player.worldObj.spawnEntityInWorld(mk4);
|
||||
}
|
||||
|
||||
|
||||
@ -8,11 +8,16 @@ import com.hbm.items.weapon.sedna.ItemGunBaseNT;
|
||||
import com.hbm.items.weapon.sedna.Receiver;
|
||||
import com.hbm.items.weapon.sedna.ItemGunBaseNT.LambdaContext;
|
||||
import com.hbm.items.weapon.sedna.mags.IMagazine;
|
||||
import com.hbm.particle.SpentCasing;
|
||||
import com.hbm.particle.helper.CasingCreator;
|
||||
import com.hbm.render.anim.HbmAnimations.AnimType;
|
||||
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
/** Orchestras are server-side components that run along client-side animations.
|
||||
* The orchestra only knows what animation is or was playing and how long it started, but not if it is still active.
|
||||
* Orchestras are useful for things like playing server-side sound, spawning casings or sending particle packets.*/
|
||||
public class Orchestras {
|
||||
|
||||
public static BiConsumer<ItemStack, LambdaContext> DEBUG_ORCHESTRA = (stack, ctx) -> {
|
||||
@ -103,26 +108,25 @@ public class Orchestras {
|
||||
EntityPlayer player = ctx.player;
|
||||
AnimType type = ItemGunBaseNT.getLastAnim(stack);
|
||||
int timer = ItemGunBaseNT.getAnimTimer(stack);
|
||||
boolean aiming = ItemGunBaseNT.getIsAiming(stack);
|
||||
|
||||
if(type == AnimType.RELOAD) {
|
||||
if(timer == 2) player.worldObj.playSoundAtEntity(player, "hbm:weapon.reload.magSmallRemove", 1F, 1F);
|
||||
if(timer == 36) player.worldObj.playSoundAtEntity(player, "hbm:weapon.reload.magSmallInsert", 1F, 1F);
|
||||
if(timer == 44) player.worldObj.playSoundAtEntity(player, "hbm:weapon.reload.revolverClose", 1F, 1F);
|
||||
}
|
||||
if(type == AnimType.CYCLE) {
|
||||
if(timer == 14) {
|
||||
SpentCasing casing = ctx.config.getReceivers(stack)[0].getMagazine(stack).getCasing(stack);
|
||||
casing.setupSmoke(1F, 0.5D, 60, 20);
|
||||
CasingCreator.composeEffect(player.worldObj, player, 0.5, -0.125, aiming ? -0.125 : -0.375D, 0, 0.12, -0.12, casing.getName());
|
||||
}
|
||||
if(timer == 12) player.worldObj.playSoundAtEntity(player, "hbm:weapon.reload.leverCock", 1F, 1F);
|
||||
}
|
||||
if(type == AnimType.CYCLE_DRY) {
|
||||
if(timer == 2) player.worldObj.playSoundAtEntity(player, "hbm:weapon.reload.dryFireClick", 1F, 1F);
|
||||
if(timer == 14) player.worldObj.playSoundAtEntity(player, "hbm:weapon.reload.revolverCock", 1F, 0.9F);
|
||||
if(timer == 12) player.worldObj.playSoundAtEntity(player, "hbm:weapon.reload.leverCock", 1F, 1F);
|
||||
}
|
||||
if(type == AnimType.INSPECT) {
|
||||
if(timer == 2) player.worldObj.playSoundAtEntity(player, "hbm:weapon.reload.magSmallRemove", 1F, 1F);
|
||||
if(timer == 24) player.worldObj.playSoundAtEntity(player, "hbm:weapon.reload.revolverClose", 1F, 1F);
|
||||
}
|
||||
if(type == AnimType.JAMMED) {
|
||||
if(timer == 12) player.worldObj.playSoundAtEntity(player, "hbm:weapon.reload.magSmallRemove", 1F, 1F);
|
||||
if(timer == 34) player.worldObj.playSoundAtEntity(player, "hbm:weapon.reload.revolverClose", 1F, 1F);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@ -38,6 +38,7 @@ public class XFactory357 {
|
||||
.rec(new Receiver(0)
|
||||
.dmg(10F).delay(16).reload(55).sound("hbm:weapon.fire.blackPowder", 1.0F, 1.0F)
|
||||
.mag(new MagazineFullReload(0, 6).addConfigs(m357_sp, m357_fmj, m357_jhp, m357_ap, m357_express))
|
||||
.offset(0.75, -0.0625, -0.3125D)
|
||||
.canFire(Lego.LAMBDA_STANDARD_CAN_FIRE).fire(Lego.LAMBDA_STANDARD_FIRE).recoil(Lego.LAMBDA_STANDARD_RECOIL))
|
||||
.setupStandardConfiguration().anim(LAMBDA_ATLAS_ANIMS)
|
||||
).setUnlocalizedName("gun_atlas").setTextureName(RefStrings.MODID + ":gun_darter");
|
||||
|
||||
@ -9,8 +9,10 @@ import com.hbm.items.weapon.sedna.GunConfig;
|
||||
import com.hbm.items.weapon.sedna.ItemGunBaseNT;
|
||||
import com.hbm.items.weapon.sedna.Receiver;
|
||||
import com.hbm.items.weapon.sedna.factory.GunFactory.EnumAmmo;
|
||||
import com.hbm.items.weapon.sedna.mags.MagazineFullReload;
|
||||
import com.hbm.items.weapon.sedna.mags.MagazineSingleReload;
|
||||
import com.hbm.lib.RefStrings;
|
||||
import com.hbm.particle.SpentCasing;
|
||||
import com.hbm.particle.SpentCasing.CasingType;
|
||||
import com.hbm.render.anim.BusAnimation;
|
||||
import com.hbm.render.anim.BusAnimationSequence;
|
||||
import com.hbm.render.anim.BusAnimationKeyframe.IType;
|
||||
@ -27,17 +29,24 @@ public class XFactory44 {
|
||||
public static BulletConfig m44_express;
|
||||
|
||||
public static void init() {
|
||||
m44_sp = new BulletConfig().setItem(EnumAmmo.M357_SP);
|
||||
m44_fmj = new BulletConfig().setItem(EnumAmmo.M357_FMJ).setDamage(0.8F).setArmorPiercing(0.1F);
|
||||
m44_jhp = new BulletConfig().setItem(EnumAmmo.M357_JHP).setDamage(1.5F).setArmorPiercing(-0.25F);
|
||||
m44_ap = new BulletConfig().setItem(EnumAmmo.M357_AP).setDoesPenetrate(true).setDamageFalloutByPen(false).setDamage(1.5F);
|
||||
m44_express = new BulletConfig().setItem(EnumAmmo.M357_EXPRESS).setDoesPenetrate(true).setDamage(1.5F).setArmorPiercing(0.1F).setWear(1.5F);
|
||||
SpentCasing casing44 = new SpentCasing(CasingType.STRAIGHT).setColor(SpentCasing.COLOR_CASE_BRASS).setupSmoke(1F, 0.5D, 60, 20);
|
||||
m44_sp = new BulletConfig().setItem(EnumAmmo.M44_SP)
|
||||
.setCasing(casing44.clone().register("m44"));
|
||||
m44_fmj = new BulletConfig().setItem(EnumAmmo.M44_FMJ).setDamage(0.8F).setArmorPiercing(0.1F)
|
||||
.setCasing(casing44.clone().register("m44fmj"));
|
||||
m44_jhp = new BulletConfig().setItem(EnumAmmo.M44_JHP).setDamage(1.5F).setArmorPiercing(-0.25F)
|
||||
.setCasing(casing44.clone().register("m44jhp"));
|
||||
m44_ap = new BulletConfig().setItem(EnumAmmo.M44_AP).setDoesPenetrate(true).setDamageFalloutByPen(false).setDamage(1.5F)
|
||||
.setCasing(casing44.clone().setColor(SpentCasing.COLOR_CASE_44).register("m44ap"));
|
||||
m44_express = new BulletConfig().setItem(EnumAmmo.M44_EXPRESS).setDoesPenetrate(true).setDamage(1.5F).setArmorPiercing(0.1F).setWear(1.5F)
|
||||
.setCasing(casing44.clone().register("m44express"));
|
||||
|
||||
ModItems.gun_henry = new ItemGunBaseNT(new GunConfig()
|
||||
.dura(300).draw(15).inspect(23).jam(45).crosshair(Crosshair.CIRCLE).smoke(true).orchestra(Orchestras.ORCHESTRA_HENRY)
|
||||
.dura(300).draw(15).inspect(23).jam(45).reloadSequential(true).crosshair(Crosshair.CIRCLE).smoke(true).orchestra(Orchestras.ORCHESTRA_HENRY)
|
||||
.rec(new Receiver(0)
|
||||
.dmg(12F).delay(16).reload(55).sound("hbm:weapon.fire.blackPowder", 1.0F, 1.0F)
|
||||
.mag(new MagazineFullReload(0, 6).addConfigs(m44_sp, m44_fmj, m44_jhp, m44_ap, m44_express))
|
||||
.dmg(12F).delay(16).reload(10).sound("hbm:weapon.fire.blackPowder", 1.0F, 1.0F)
|
||||
.mag(new MagazineSingleReload(0, 14).addConfigs(m44_sp, m44_fmj, m44_jhp, m44_ap, m44_express))
|
||||
.offset(0.75, -0.0625, -0.3125D)
|
||||
.canFire(Lego.LAMBDA_STANDARD_CAN_FIRE).fire(Lego.LAMBDA_STANDARD_FIRE).recoil(Lego.LAMBDA_STANDARD_RECOIL))
|
||||
.setupStandardConfiguration().anim(LAMBDA_HENRY_ANIMS)
|
||||
).setUnlocalizedName("gun_henry").setTextureName(RefStrings.MODID + ":gun_darter");
|
||||
@ -54,8 +63,13 @@ public class XFactory44 {
|
||||
.addBus("LEVER", new BusAnimationSequence().addPos(0, 0, 0, 600).addPos(-90, 0, 0, 200).addPos(0, 0, 0, 200))
|
||||
.addBus("TURN", new BusAnimationSequence().addPos(0, 0, 0, 600).addPos(0, 0, 45, 200, IType.SIN_DOWN).addPos(0, 0, 0, 200, IType.SIN_UP))
|
||||
.addBus("HAMMER", new BusAnimationSequence().addPos(30, 0, 0, 50).addPos(30, 0, 0, 550).addPos(0, 0, 0, 200));
|
||||
case CYCLE_DRY: return new BusAnimation();
|
||||
case CYCLE_DRY: return new BusAnimation()
|
||||
.addBus("LEVER", new BusAnimationSequence().addPos(0, 0, 0, 600).addPos(-90, 0, 0, 200).addPos(0, 0, 0, 200))
|
||||
.addBus("TURN", new BusAnimationSequence().addPos(0, 0, 0, 600).addPos(0, 0, 45, 200, IType.SIN_DOWN).addPos(0, 0, 0, 200, IType.SIN_UP))
|
||||
.addBus("HAMMER", new BusAnimationSequence().addPos(30, 0, 0, 50).addPos(30, 0, 0, 550).addPos(0, 0, 0, 200));
|
||||
case RELOAD: return new BusAnimation();
|
||||
case RELOAD_CYCLE: return new BusAnimation();
|
||||
case RELOAD_END: return new BusAnimation();
|
||||
case INSPECT: return new BusAnimation();
|
||||
case JAMMED: return new BusAnimation();
|
||||
}
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
package com.hbm.items.weapon.sedna.mags;
|
||||
|
||||
import com.hbm.particle.SpentCasing;
|
||||
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
@ -29,4 +31,6 @@ public interface IMagazine<T> {
|
||||
public ItemStack getIconForHUD(ItemStack stack);
|
||||
/** It explains itself */
|
||||
public String reportAmmoStateForHUD(ItemStack stack);
|
||||
/** Casing config to use then ejecting */
|
||||
public SpentCasing getCasing(ItemStack stack);
|
||||
}
|
||||
|
||||
@ -0,0 +1,74 @@
|
||||
package com.hbm.items.weapon.sedna.mags;
|
||||
|
||||
import com.hbm.items.weapon.sedna.BulletConfig;
|
||||
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
/** Uses individual bullets which are loaded all at once */
|
||||
public class MagazineSingleReload extends MagazineSingleTypeBase {
|
||||
|
||||
public MagazineSingleReload(int index, int capacity) {
|
||||
super(index, capacity);
|
||||
}
|
||||
|
||||
/** Returns true if the player has the same ammo if partially loaded, or any valid ammo if not */
|
||||
@Override
|
||||
public boolean canReload(ItemStack stack, EntityPlayer player) {
|
||||
|
||||
if(this.getAmount(stack) >= this.getCapacity(stack)) return false;
|
||||
|
||||
for(ItemStack slot : player.inventory.mainInventory) {
|
||||
|
||||
if(slot != null) {
|
||||
if(this.getAmount(stack) == 0) {
|
||||
for(BulletConfig config : this.acceptedBullets) {
|
||||
if(config.ammo.matchesRecipe(slot, true)) return true;
|
||||
}
|
||||
} else {
|
||||
BulletConfig config = this.getType(stack);
|
||||
if(config == null) { config = this.acceptedBullets.get(0); this.setType(stack, config); }
|
||||
if(config.ammo.matchesRecipe(slot, true)) return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Reloads all rounds at once. If the mag is empty, the mag's type will change to the first valid ammo type */
|
||||
@Override
|
||||
public void reloadAction(ItemStack stack, EntityPlayer player) {
|
||||
|
||||
for(int i = 0; i < player.inventory.mainInventory.length; i++) {
|
||||
ItemStack slot = player.inventory.mainInventory[i];
|
||||
|
||||
if(slot != null) {
|
||||
|
||||
//mag is empty, assume next best type
|
||||
if(this.getAmount(stack) == 0) {
|
||||
|
||||
for(BulletConfig config : this.acceptedBullets) {
|
||||
if(config.ammo.matchesRecipe(slot, true)) {
|
||||
this.setType(stack, config);
|
||||
this.setAmount(stack, 1);
|
||||
player.inventory.decrStackSize(i, 1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
//mag has a type set, only load that
|
||||
} else {
|
||||
BulletConfig config = this.getType(stack);
|
||||
if(config == null) { config = this.acceptedBullets.get(0); this.setType(stack, config); } //fixing broken NBT
|
||||
|
||||
if(config.ammo.matchesRecipe(slot, true)) {
|
||||
int alreadyLoaded = this.getAmount(stack);
|
||||
this.setAmount(stack, alreadyLoaded + 1);
|
||||
player.inventory.decrStackSize(i, 1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -5,6 +5,7 @@ import java.util.List;
|
||||
|
||||
import com.hbm.items.weapon.sedna.BulletConfig;
|
||||
import com.hbm.items.weapon.sedna.ItemGunBaseNT;
|
||||
import com.hbm.particle.SpentCasing;
|
||||
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
@ -57,6 +58,11 @@ public abstract class MagazineSingleTypeBase implements IMagazine<BulletConfig>
|
||||
return getAmount(stack) + " / " + getCapacity(stack);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpentCasing getCasing(ItemStack stack) {
|
||||
return this.getType(stack).casing;
|
||||
}
|
||||
|
||||
@Override public int getCapacity(ItemStack stack) { return capacity; }
|
||||
@Override public int getAmount(ItemStack stack) { return getMagCount(stack, index); }
|
||||
@Override public void setAmount(ItemStack stack, int amount) { setMagCount(stack, index, amount); }
|
||||
|
||||
@ -89,8 +89,7 @@ import com.hbm.items.ModItems;
|
||||
import com.hbm.items.weapon.sedna.factory.GunFactoryClient;
|
||||
import com.hbm.lib.RefStrings;
|
||||
import com.hbm.particle.*;
|
||||
import com.hbm.particle.helper.ExplosionCreator;
|
||||
import com.hbm.particle.helper.IParticleCreator;
|
||||
import com.hbm.particle.helper.*;
|
||||
import com.hbm.particle.psys.engine.EventHandlerParticleEngine;
|
||||
import com.hbm.render.anim.*;
|
||||
import com.hbm.render.anim.HbmAnimations.Animation;
|
||||
@ -989,6 +988,7 @@ public class ClientProxy extends ServerProxy {
|
||||
|
||||
static {
|
||||
particleCreators.put("explosionLarge", new ExplosionCreator());
|
||||
particleCreators.put("casingNT", new CasingCreator());
|
||||
}
|
||||
|
||||
//mk3, only use this one
|
||||
|
||||
@ -42,8 +42,6 @@ public class ParticleSpentCasing extends EntityFX {
|
||||
private boolean isSmoking;
|
||||
|
||||
private float momentumPitch, momentumYaw;
|
||||
private boolean onGroundPreviously = false;
|
||||
private double maxHeight;
|
||||
|
||||
public ParticleSpentCasing(TextureManager textureManager, World world, double x, double y, double z, double mx, double my, double mz, float momentumPitch, float momentumYaw, SpentCasing config) {
|
||||
super(world, x, y, z, 0, 0, 0);
|
||||
@ -66,9 +64,7 @@ public class ParticleSpentCasing extends EntityFX {
|
||||
this.motionY = my;
|
||||
this.motionZ = mz;
|
||||
|
||||
particleGravity = 8F;
|
||||
|
||||
maxHeight = y;
|
||||
particleGravity = 1F;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -78,24 +74,34 @@ public class ParticleSpentCasing extends EntityFX {
|
||||
|
||||
@Override
|
||||
public void onUpdate() {
|
||||
super.onUpdate();
|
||||
|
||||
this.prevPosX = this.posX;
|
||||
this.prevPosY = this.posY;
|
||||
this.prevPosZ = this.posZ;
|
||||
|
||||
if(motionY > 0 && posY > maxHeight)
|
||||
maxHeight = posY;
|
||||
if(this.particleAge++ >= this.particleMaxAge) {
|
||||
this.setDead();
|
||||
}
|
||||
|
||||
if(!onGroundPreviously && onGround)
|
||||
tryPlayBounceSound();
|
||||
this.motionY -= 0.04D * (double) this.particleGravity;
|
||||
double prevMotionY = this.motionY;
|
||||
this.moveEntity(this.motionX, this.motionY, this.motionZ);
|
||||
this.motionX *= 0.98D;
|
||||
this.motionY *= 0.98D;
|
||||
this.motionZ *= 0.98D;
|
||||
|
||||
if(!onGroundPreviously && onGround) {
|
||||
if(this.onGround) {
|
||||
this.motionX *= 0.7D;
|
||||
this.motionZ *= 0.7D;
|
||||
}
|
||||
|
||||
if(onGround) {
|
||||
this.onGround = false;
|
||||
motionY = prevMotionY * -0.5;
|
||||
this.rotationPitch = 0;
|
||||
//momentumPitch = (float) rand.nextGaussian() * config.getBouncePitch();
|
||||
//momentumYaw = (float) rand.nextGaussian() * config.getBounceYaw();
|
||||
|
||||
onGroundPreviously = true;
|
||||
motionY = Math.log10(maxHeight - posY + 2);
|
||||
momentumPitch = (float) rand.nextGaussian() * config.getBouncePitch();
|
||||
momentumYaw = (float) rand.nextGaussian() * config.getBounceYaw();
|
||||
maxHeight = posY;
|
||||
|
||||
} else if(onGroundPreviously && !onGround) {
|
||||
onGroundPreviously = false;
|
||||
}
|
||||
|
||||
if(particleAge > maxSmokeGen && !smokeNodes.isEmpty())
|
||||
@ -193,8 +199,6 @@ public class ParticleSpentCasing extends EntityFX {
|
||||
|
||||
GL11.glPushMatrix();
|
||||
GL11.glTranslated(pX - dX, pY - dY - this.height / 4, pZ - dZ);
|
||||
//GL11.glScalef(dScale, dScale, dScale);
|
||||
//GL11.glScalef(config.getScaleX(), config.getScaleY(), config.getScaleZ());
|
||||
|
||||
if(!smokeNodes.isEmpty()) {
|
||||
tessellator.startDrawingQuads();
|
||||
@ -271,17 +275,17 @@ public class ParticleSpentCasing extends EntityFX {
|
||||
@Override
|
||||
@SideOnly(Side.CLIENT)
|
||||
public int getBrightnessForRender(float p_70070_1_) {
|
||||
int i = MathHelper.floor_double(this.posX);
|
||||
int j = MathHelper.floor_double(this.posZ);
|
||||
int x = MathHelper.floor_double(this.posX);
|
||||
int z = MathHelper.floor_double(this.posZ);
|
||||
|
||||
if(this.worldObj.blockExists(i, 0, j)) {
|
||||
if(this.worldObj.blockExists(x, 0, z)) {
|
||||
double d0 = (this.boundingBox.maxY - this.boundingBox.minY) * 0.66D;
|
||||
int k = MathHelper.floor_double(this.posY - (double) this.yOffset + d0);
|
||||
return this.worldObj.getLightBrightnessForSkyBlocks(i, k, j, 0);
|
||||
int y = MathHelper.floor_double(this.posY - (double) this.yOffset + d0);
|
||||
return this.worldObj.getLightBrightnessForSkyBlocks(x, y, z, 0);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void tryPlayBounceSound() {
|
||||
|
||||
|
||||
65
src/main/java/com/hbm/particle/helper/CasingCreator.java
Normal file
65
src/main/java/com/hbm/particle/helper/CasingCreator.java
Normal file
@ -0,0 +1,65 @@
|
||||
package com.hbm.particle.helper;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
import com.hbm.particle.ParticleSpentCasing;
|
||||
import com.hbm.particle.SpentCasing;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.texture.TextureManager;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.util.Vec3;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public class CasingCreator implements IParticleCreator {
|
||||
|
||||
public static void composeEffect(World world, EntityPlayer player, double frontOffset, double heightOffset, double sideOffset, double frontMotion, double heightMotion, double sideMotion, String casing) {
|
||||
|
||||
if(player.isSneaking()) heightOffset -= 0.075F;
|
||||
|
||||
Vec3 offset = Vec3.createVectorHelper(sideOffset, heightOffset, frontOffset);
|
||||
offset.rotateAroundX(-player.rotationPitch / 180F * (float) Math.PI);
|
||||
offset.rotateAroundY(-player.rotationYaw / 180F * (float) Math.PI);
|
||||
|
||||
double x = player.posX + offset.xCoord;
|
||||
double y = player.posY + player.getEyeHeight() + offset.yCoord;
|
||||
double z = player.posZ + offset.zCoord;
|
||||
|
||||
Vec3 motion = Vec3.createVectorHelper(sideMotion, heightMotion, frontMotion);
|
||||
motion.rotateAroundX(-player.rotationPitch / 180F * (float) Math.PI);
|
||||
motion.rotateAroundY(-player.rotationYaw / 180F * (float) Math.PI);
|
||||
|
||||
double mX = player.motionX + motion.xCoord;
|
||||
double mY = player.motionY + motion.yCoord;
|
||||
double mZ = player.motionZ + motion.zCoord;
|
||||
|
||||
NBTTagCompound data = new NBTTagCompound();
|
||||
data.setString("type", "casingNT");
|
||||
data.setDouble("mX", mX);
|
||||
data.setDouble("mY", mY);
|
||||
data.setDouble("mZ", mZ);
|
||||
data.setFloat("yaw", player.rotationYaw);
|
||||
data.setFloat("pitch", player.rotationPitch);
|
||||
data.setString("name", casing);
|
||||
|
||||
IParticleCreator.sendPacket(world, x, y, z, 50, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void makeParticle(World world, EntityPlayer player, TextureManager texman, Random rand, double x, double y, double z, NBTTagCompound data) {
|
||||
|
||||
String name = data.getString("name");
|
||||
SpentCasing casingConfig = SpentCasing.casingMap.get(name);
|
||||
double mX = data.getDouble("mX");
|
||||
double mY = data.getDouble("mY");
|
||||
double mZ = data.getDouble("mZ");
|
||||
float yaw = data.getFloat("yaw");
|
||||
float pitch = data.getFloat("pitch");
|
||||
ParticleSpentCasing casing = new ParticleSpentCasing(texman, world, x, y, z, mX, mY, mZ, 0, 0, casingConfig);
|
||||
casing.prevRotationYaw = casing.rotationYaw = yaw;
|
||||
casing.prevRotationPitch = casing.rotationPitch = pitch;
|
||||
Minecraft.getMinecraft().effectRenderer.addEffect(casing);
|
||||
}
|
||||
|
||||
}
|
||||
@ -18,8 +18,8 @@ public class HbmAnimations {
|
||||
public static final Animation[] hotbar = new Animation[9];
|
||||
|
||||
public static enum AnimType {
|
||||
RELOAD, //animation for reloading the weapon
|
||||
RELOAD_EMPTY, //animation for reloading from empty
|
||||
RELOAD, //either a full reload or start of a reload
|
||||
RELOAD_EMPTY, //same as reload, but the mag is completely empty
|
||||
RELOAD_CYCLE, //animation that plays for every individual round (for shotguns and similar single round loading weapons)
|
||||
RELOAD_END, //animation for transitioning from our RELOAD_CYCLE to idle
|
||||
CYCLE, //animation for every firing cycle
|
||||
|
||||
@ -53,6 +53,13 @@ public class ItemRenderHenry extends ItemRenderWeaponBase {
|
||||
GL11.glRotated(equip[0], -1, 0, 0);
|
||||
GL11.glTranslated(0, -2, 4);
|
||||
|
||||
GL11.glPushMatrix();
|
||||
GL11.glTranslated(0, 1, 8);
|
||||
GL11.glRotated(turn[2], 0, 0, -1);
|
||||
GL11.glRotated(90, 0, 1, 0);
|
||||
this.renderSmokeNodes(gun.smokeNodes, 0.25D);
|
||||
GL11.glPopMatrix();
|
||||
|
||||
ResourceManager.henry.renderPart("Gun");
|
||||
|
||||
GL11.glPushMatrix();
|
||||
|
||||
@ -28,8 +28,6 @@ import net.minecraftforge.common.util.ForgeDirection;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
@Optional.InterfaceList({@Optional.Interface(iface = "li.cil.oc.api.network.SimpleComponent", modid = "OpenComputers")})
|
||||
public class TileEntityCraneConsole extends TileEntity implements INBTPacketReceiver, SimpleComponent, CompatHandler.OCComponent {
|
||||
|
||||
|
||||
@ -1153,6 +1153,11 @@ item.ammo_standard.m357_express.name=.357 Magnumkugel (VMG Express)
|
||||
item.ammo_standard.m357_fmj.name=.357 Magnumkugel (Vollmantelgeschoss)
|
||||
item.ammo_standard.m357_jhp.name=.357 Magnumkugel (Hohlspitz)
|
||||
item.ammo_standard.m357_sp.name=.357 Magnumkugel (Teilmantelgeschoss)
|
||||
item.ammo_standard.m44_ap.name=.44 Magnumkugel (Panzerbrechend)
|
||||
item.ammo_standard.m44_express.name=.44 Magnumkugel (VMG Express)
|
||||
item.ammo_standard.m44_fmj.name=.44 Magnumkugel (Vollmantelgeschoss)
|
||||
item.ammo_standard.m44_jhp.name=.44 Magnumkugel (Hohlspitz)
|
||||
item.ammo_standard.m44_sp.name=.44 Magnumkugel (Teilmantelgeschoss)
|
||||
item.ammo_standard.stone.name=Kugel und Pulver
|
||||
item.ammo_standard.stone_ap.name=Feuerstein und Pulver
|
||||
item.ammo_standard.stone_iron.name=Eisenkugel und Pulver
|
||||
|
||||
@ -1876,6 +1876,11 @@ item.ammo_standard.m357_express.name=.357 Magnum Round (FMJ Express)
|
||||
item.ammo_standard.m357_fmj.name=.357 Magnum Round (Full Metal Jacket)
|
||||
item.ammo_standard.m357_jhp.name=.357 Magnum Round (Jacketed Hollow Point)
|
||||
item.ammo_standard.m357_sp.name=.357 Magnum Round (Soft Point)
|
||||
item.ammo_standard.m44_ap.name=.44 Magnum Round (Armor Piercing)
|
||||
item.ammo_standard.m44_express.name=.44 Magnum Round (FMJ Express)
|
||||
item.ammo_standard.m44_fmj.name=.44 Magnum Round (Full Metal Jacket)
|
||||
item.ammo_standard.m44_jhp.name=.44 Magnum Round (Jacketed Hollow Point)
|
||||
item.ammo_standard.m44_sp.name=.44 Magnum Round (Soft Point)
|
||||
item.ammo_standard.stone.name=Ball and Powder
|
||||
item.ammo_standard.stone_ap.name=Flint and Powder
|
||||
item.ammo_standard.stone_iron.name=Iron Ball and Powder
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 297 B |
Binary file not shown.
|
After Width: | Height: | Size: 302 B |
Binary file not shown.
|
After Width: | Height: | Size: 269 B |
Binary file not shown.
|
After Width: | Height: | Size: 289 B |
Binary file not shown.
|
After Width: | Height: | Size: 283 B |
Loading…
x
Reference in New Issue
Block a user