/* * This file is part of Matter Overdrive * Copyright (c) 2015., Simeon Radivoev, All rights reserved. * * Matter Overdrive is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Matter Overdrive is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Matter Overdrive. If not, see <http://www.gnu.org/licenses>. */ package matteroverdrive.items.weapon; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; import matteroverdrive.MatterOverdrive; import matteroverdrive.Reference; import matteroverdrive.api.weapon.WeaponShot; import matteroverdrive.client.sound.MOPositionedSound; import matteroverdrive.client.sound.WeaponSound; import matteroverdrive.entity.weapon.PlasmaBolt; import matteroverdrive.handler.weapon.ClientWeaponHandler; import matteroverdrive.init.MatterOverdriveItems; import matteroverdrive.items.weapon.module.WeaponModuleBarrel; import matteroverdrive.network.packet.bi.PacketFirePlasmaShot; import matteroverdrive.util.WeaponHelper; import net.minecraft.client.Minecraft; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; import net.minecraft.util.MovingObjectPosition; import net.minecraft.util.ResourceLocation; import net.minecraft.util.Vec3; import net.minecraft.world.World; import org.lwjgl.input.Mouse; import org.lwjgl.util.vector.Vector2f; import java.util.List; /** * Created by Simeon on 12/6/2015. */ public class PlasmaShotgun extends EnergyWeapon { private static final int MAX_CHARGE_TIME = 20; private static final int ENERGY_PER_SHOT = 2560; public static final int RANGE = 16; @SideOnly(Side.CLIENT) private MOPositionedSound lastChargingSound; public PlasmaShotgun(String name) { super(name, 32000, 128, 128, RANGE); this.setFull3D(); leftClickFire = true; } @Override protected void addCustomDetails(ItemStack weapon, EntityPlayer player, List infos) { } @Override public int getBaseEnergyUse(ItemStack item) { return ENERGY_PER_SHOT / getShootCooldown(item); } @Override protected int getBaseMaxHeat(ItemStack item) { return 80; } @Override public float getWeaponBaseDamage(ItemStack weapon) { return 16; } @Override public float getWeaponBaseAccuracy(ItemStack weapon, boolean zoomed) { return 5f + getHeat(weapon)*0.3f; } @Override public boolean canFire(ItemStack itemStack, World world, EntityLivingBase shooter) { return DrainEnergy(itemStack, getShootCooldown(itemStack), true) && !isOverheated(itemStack); } @Override public float getShotSpeed(ItemStack weapon, EntityLivingBase shooter) { return 3; } @Override public int getBaseShootCooldown(ItemStack weapon) { return 22; } @Override public float getBaseZoom(ItemStack weapon, EntityLivingBase shooter) { return 0; } @Override @SideOnly(Side.CLIENT) public void onClientShot(ItemStack weapon, EntityLivingBase shooter, Vec3 position, Vec3 dir, WeaponShot shot) { MOPositionedSound sound = new MOPositionedSound(new ResourceLocation(Reference.MOD_ID + ":" + "plasma_shotgun_shot"),0.3f + itemRand.nextFloat() * 0.2f, 0.9f + itemRand.nextFloat() * 0.2f); sound.setPosition((float) position.xCoord,(float)position.yCoord,(float)position.zCoord); Minecraft.getMinecraft().getSoundHandler().playDelayedSound(sound,1); spawnProjectile(weapon,shooter,position,dir,shot); } public PlasmaBolt[] spawnProjectile(ItemStack weapon, EntityLivingBase shooter, Vec3 position, Vec3 dir, WeaponShot shot) { //PlasmaBolt fire = new PlasmaBolt(entityPlayer.worldObj, entityPlayer,position,dir, getWeaponScaledDamage(weapon), 2, getAccuracy(weapon, zoomed), getRange(weapon), WeaponHelper.getColor(weapon).getColor(), zoomed,seed); PlasmaBolt[] bolts = new PlasmaBolt[shot.getCount()]; for (int i = 0;i < shot.getCount();i++) { WeaponShot newShot = new WeaponShot(shot); newShot.setSeed(shot.getSeed()+i); newShot.setDamage(shot.getDamage()/shot.getCount()); bolts[i] = new PlasmaBolt(shooter.worldObj, shooter, position, dir, newShot, getShotSpeed(weapon, shooter)); bolts[i].setWeapon(weapon); bolts[i].setRenderSize((getShotCount(weapon,shooter)/shot.getCount())*0.5f); bolts[i].setFireDamageMultiply(WeaponHelper.modifyStat(Reference.WS_FIRE_DAMAGE, weapon,0)); bolts[i].setKnockBack(0.5f); shooter.worldObj.spawnEntityInWorld(bolts[i]); } return bolts; } public int getShotCount(ItemStack weapon,EntityLivingBase shooter) { return 10; } @Override public void onProjectileHit(MovingObjectPosition hit, ItemStack weapon, World world, float amount) { } @Override @SideOnly(Side.CLIENT) public Vector2f getSlotPosition(int slot, ItemStack weapon) { switch (slot) { case Reference.MODULE_BATTERY: return new Vector2f(170,115); case Reference.MODULE_COLOR: return new Vector2f(60,45); case Reference.MODULE_BARREL: return new Vector2f(60,115); case Reference.MODULE_OTHER: return new Vector2f(205,80); case Reference.MODULE_SIGHTS: return new Vector2f(150,35); } return new Vector2f(0,0); } @Override @SideOnly(Side.CLIENT) public Vector2f getModuleScreenPosition(int slot, ItemStack weapon) { switch(slot) { case Reference.MODULE_BATTERY: return new Vector2f(165,80); case Reference.MODULE_COLOR: return new Vector2f(100,80); case Reference.MODULE_BARREL: return new Vector2f(90,90); case Reference.MODULE_SIGHTS: return new Vector2f(140,72); } return getSlotPosition(slot,weapon); } @Override public boolean supportsModule(int slot,ItemStack weapon) { return true; } @Override public boolean supportsModule(ItemStack weapon, ItemStack module) { if (module != null) { return module.getItem() == MatterOverdriveItems.weapon_module_color || (module.getItem() == MatterOverdriveItems.weapon_module_barrel && module.getItemDamage() != WeaponModuleBarrel.EXPLOSION_BARREL_ID && module.getItemDamage() != WeaponModuleBarrel.HEAL_BARREL_ID); } return false; } @Override public ItemStack onItemRightClick(ItemStack weapon, World world, EntityPlayer entityPlayer) { if (world.isRemote && canFire(weapon,world,entityPlayer) && hasShootDelayPassed() && !entityPlayer.isUsingItem()) { entityPlayer.setItemInUse(weapon, getMaxItemUseDuration(weapon)); playChargingSound(entityPlayer); } return weapon; } @SideOnly(Side.CLIENT) public void playChargingSound(EntityPlayer entityPlayer) { lastChargingSound = new MOPositionedSound(new ResourceLocation(Reference.MOD_ID + ":" + "plasma_shotgun_charging"),3f + itemRand.nextFloat()*0.2f,0.9f * itemRand.nextFloat() * 0.2f); lastChargingSound.setPosition((float) entityPlayer.posX,(float)entityPlayer.posY,(float)entityPlayer.posZ); Minecraft.getMinecraft().getSoundHandler().playSound(lastChargingSound); } @SideOnly(Side.CLIENT) public void stopChargingSound() { Minecraft.getMinecraft().getSoundHandler().stopSound(lastChargingSound); } @Override public void onUsingTick(ItemStack stack, EntityPlayer player, int count) { //if (getMaxItemUseDuration(stack) - count >= MAX_CHARGE_TIME) //{ //player.stopUsingItem(); //} } @Override public void onPlayerStoppedUsing(ItemStack weapon, World world, EntityPlayer entityPlayer, int time) { if (world.isRemote) { int maxCount = getShotCount(weapon,entityPlayer); int timeElapsed = (getMaxItemUseDuration(weapon) - time); int count = Math.max(1, (int) ((1f - (timeElapsed / (float) MAX_CHARGE_TIME)) * maxCount)); float shotPercent = count / (float) getShotCount(weapon, entityPlayer); ClientWeaponHandler.RECOIL_AMOUNT = 15 + (maxCount - count) * 2 + getAccuracy(weapon, entityPlayer, isWeaponZoomed(entityPlayer, weapon)) * 2; ClientWeaponHandler.RECOIL_TIME = 1 + (maxCount - count) * 0.03f; Minecraft.getMinecraft().renderViewEntity.hurtTime = 15 + (maxCount - count); Minecraft.getMinecraft().renderViewEntity.maxHurtTime = 30 + (maxCount - count); Vec3 dir = entityPlayer.getLook(1); Vec3 pos = getFirePosition(entityPlayer, dir, Mouse.isButtonDown(1)); WeaponShot shot = createShot(weapon, entityPlayer, Mouse.isButtonDown(1)); shot.setCount(count); shot.setAccuracy(shot.getAccuracy() * shotPercent); shot.setRange(shot.getRange() + (int) (shot.getRange() * (1 - shotPercent))); onClientShot(weapon, entityPlayer, pos, dir, shot); MatterOverdrive.packetPipeline.sendToServer(new PacketFirePlasmaShot(entityPlayer.getEntityId(), pos, dir, shot)); addShootDelay(weapon); stopChargingSound(); entityPlayer.clearItemInUse(); } } @Override public ItemStack onEaten(ItemStack weapon, World world, EntityPlayer entityPlayer) { return weapon; } @Override public int getMaxItemUseDuration(ItemStack weapon) { return 72000; } @SideOnly(Side.CLIENT) private Vec3 getFirePosition(EntityPlayer entityPlayer,Vec3 dir,boolean isAiming) { Vec3 pos = Vec3.createVectorHelper(entityPlayer.posX, entityPlayer.posY, entityPlayer.posZ); if (!isAiming) { //pos.xCoord -= (double)(MathHelper.cos(entityPlayer.rotationYaw / 180.0F * (float) Math.PI) * 0.16F); //pos.zCoord -= (double)(MathHelper.sin(entityPlayer.rotationYaw / 180.0F * (float) Math.PI) * 0.16F); } pos = pos.addVector(dir.xCoord,dir.yCoord,dir.zCoord); return pos; } @Override @SideOnly(Side.CLIENT) public void onShooterClientUpdate(ItemStack itemStack, World world, EntityPlayer entityPlayer, boolean sendServerTick) { if (Mouse.isButtonDown(0) && hasShootDelayPassed()) { if (canFire(itemStack, world, entityPlayer)) { itemStack.getTagCompound().setLong("LastShot", world.getTotalWorldTime()); ClientWeaponHandler.RECOIL_AMOUNT = 12 + getAccuracy(itemStack, entityPlayer, isWeaponZoomed(entityPlayer, itemStack)) * 2; ClientWeaponHandler.RECOIL_TIME = 1; Minecraft.getMinecraft().renderViewEntity.hurtTime = 15; Minecraft.getMinecraft().renderViewEntity.maxHurtTime = 30; Vec3 dir = entityPlayer.getLook(1); Vec3 pos = getFirePosition(entityPlayer, dir, Mouse.isButtonDown(1)); WeaponShot shot = createShot(itemStack, entityPlayer, Mouse.isButtonDown(1)); onClientShot(itemStack, entityPlayer, pos, dir, shot); addShootDelay(itemStack); sendShootTickToServer(world, shot, dir, pos); return; } else if (needsRecharge(itemStack)) { chargeFromEnergyPack(itemStack, entityPlayer); } } super.onShooterClientUpdate(itemStack,world,entityPlayer,sendServerTick); } public WeaponShot createShot(ItemStack weapon, EntityLivingBase shooter, boolean zoomed) { WeaponShot shot = new WeaponShot(itemRand.nextInt(),getWeaponScaledDamage(weapon,shooter),getAccuracy(weapon,shooter,zoomed),WeaponHelper.getColor(weapon),getRange(weapon)); shot.setCount(getShotCount(weapon,shooter)); return shot; } @Override public boolean onServerFire(ItemStack weapon, EntityLivingBase shooter, WeaponShot shot, Vec3 position, Vec3 dir,int delay) { DrainEnergy(weapon, getShootCooldown(weapon), false); int heatAdd = (getShotCount(weapon,shooter) - shot.getCount()) * 2; float newHeat = (getHeat(weapon)+ heatAdd + 6) * 4.2f ; setHeat(weapon, Math.max(newHeat,0)); manageOverheat(weapon, shooter.worldObj, shooter); PlasmaBolt[] fires = spawnProjectile(weapon,shooter,position,dir,shot); for (PlasmaBolt bolt : fires) { bolt.simulateDelay(delay); } return true; } @Override public boolean isAlwaysEquipped(ItemStack weapon) { return false; } @Override @SideOnly(Side.CLIENT) public boolean isWeaponZoomed(EntityPlayer entityPlayer, ItemStack weapon) { return false; } @Override @SideOnly(Side.CLIENT) public WeaponSound getFireSound(ItemStack weapon, EntityLivingBase entity) { return null; } }