/*
* 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.common.FMLCommonHandler;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import matteroverdrive.Reference;
import matteroverdrive.api.weapon.IWeapon;
import matteroverdrive.api.weapon.WeaponShot;
import matteroverdrive.client.sound.WeaponSound;
import matteroverdrive.handler.SoundHandler;
import matteroverdrive.init.MatterOverdriveItems;
import matteroverdrive.util.MOPhysicsHelper;
import matteroverdrive.util.WeaponHelper;
import matteroverdrive.util.animation.MOEasing;
import net.minecraft.block.Block;
import net.minecraft.client.renderer.texture.IIconRegister;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.Blocks;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.potion.Potion;
import net.minecraft.potion.PotionEffect;
import net.minecraft.server.MinecraftServer;
import net.minecraft.util.*;
import net.minecraft.world.World;
import net.minecraftforge.common.util.ForgeDirection;
import org.lwjgl.util.vector.Vector2f;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class Phaser extends EnergyWeapon implements IWeapon{
private static final double ENERGY_MULTIPLY = 2.1;
private static final int MAX_USE_TIME = 60;
private static final int MAX_HEAT = 80;
public static final int MAX_LEVEL = 6;
private static final int KILL_MODE_LEVEL = 3;
private static final float KILL_DAMAGE_MULTIPLY = 2f;
private static final int STUN_SLEEP_MULTIPLY = 5;
public static final int RANGE = 18;
Map<EntityPlayer,WeaponSound> soundMap;
public Phaser(String name) {
super(name,32000,128,128,RANGE);
this.bFull3D = true;
soundMap = new HashMap<>();
}
@SideOnly(Side.CLIENT)
public void registerIcons(IIconRegister iconRegistry)
{
}
@Override
public int getBaseEnergyUse(ItemStack item)
{
this.TagCompountCheck(item);
byte level = getPowerLevel(item);
return (int)Math.pow(ENERGY_MULTIPLY, level + 1);
}
@Override
protected int getBaseMaxHeat(ItemStack item) {
return MAX_HEAT;
}
@Override
@SideOnly(Side.CLIENT)
protected void addCustomDetails(ItemStack weapon,EntityPlayer player,List infos)
{
infos.add(EnumChatFormatting.BLUE + "Stun: " + (GetSleepTime(weapon) / 20f) + "s");
}
/**
* How long it takes to use or consume an item
*/
@Override
public int getMaxItemUseDuration(ItemStack item)
{
return MAX_USE_TIME;
}
public static boolean isKillMode(ItemStack item)
{
if(!item.hasTagCompound())
{
item.setTagCompound(new NBTTagCompound());
}
return item.getTagCompound().getByte("power") >= KILL_MODE_LEVEL;
}
private void ManageShooting(ItemStack item, World w, EntityPlayer player,int useCount)
{
if (w.isRemote)
return;
Vec3 dir = getPlayerLook(player,item);
MovingObjectPosition hit = MOPhysicsHelper.rayTrace(player, w, getRange(item), 0, Vec3.createVectorHelper(0, player.getEyeHeight(), 0), false, true,dir);
if (hit != null)
{
Vec3 hitVector = hit.hitVec;
if (hit.entityHit != null && hit.entityHit instanceof EntityLivingBase)
{
if (hit.entityHit instanceof EntityPlayer && FMLCommonHandler.instance().getSide() == Side.SERVER && !MinecraftServer.getServer().isPVPEnabled()) return;
DamageSource damageInfo = getDamageSource(item,player);
float damage = getWeaponScaledDamage(item,player);
EntityLivingBase el = (EntityLivingBase) hit.entityHit;
double motionX = el.motionX;
double motionY = el.motionY;
double moutionZ = el.motionZ;
if (damage > 0)
{
el.attackEntityFrom(damageInfo, damage);
el.motionX = motionX;
el.motionY = motionY;
el.motionZ = moutionZ;
}
el.addPotionEffect(new PotionEffect(Potion.moveSlowdown.id, GetSleepTime(item), 100));
//el.addPotionEffect(new PotionEffect(Potion.moveSpeed.id, GetSleepTime(item), -10));
el.addPotionEffect(new PotionEffect(Potion.digSlowdown.id, GetSleepTime(item), 100));
el.addPotionEffect(new PotionEffect(Potion.jump.id, GetSleepTime(item), -10));
if (WeaponHelper.hasStat(Reference.WS_FIRE_DAMAGE,item) && isKillMode(item))
{
el.setFire(Math.round(WeaponHelper.modifyStat(Reference.WS_FIRE_DAMAGE,item,0) * item.getTagCompound().getByte("power")));
}
else if (WeaponHelper.hasStat(Reference.WS_HEAL,item))
{
el.heal((WeaponHelper.modifyStat(Reference.WS_HEAL,item,0) * item.getTagCompound().getByte("power")));
}
}else
{
if (WeaponHelper.hasStat(Reference.WS_FIRE_DAMAGE,item))
{
int x = hit.blockX;
int y = hit.blockY;
int z = hit.blockZ;
if (player.worldObj.getBlock(x,y,z).isFlammable(player.worldObj,x,y,z, ForgeDirection.getOrientation(hit.sideHit))) {
if (hit.sideHit == 0) {
--y;
}
if (hit.sideHit == 1) {
++y;
}
if (hit.sideHit == 2) {
--z;
}
if (hit.sideHit == 3) {
++z;
}
if (hit.sideHit == 4) {
--x;
}
if (hit.sideHit == 5) {
++x;
}
if (player.canPlayerEdit(x, y, z, hit.sideHit, item)) {
if (player.worldObj.isAirBlock(x, y, z)) {
//player.worldObj.playSoundEffect((double) x + 0.5D, (double) y + 0.5D, (double) z + 0.5D, "fire.ignite", 1.0F, itemRand.nextFloat() * 0.4F + 0.8F);
player.worldObj.setBlock(x, y, z, Blocks.fire);
}
}
}
}
}
if (isKillMode(item) && useCount % getShootCooldown(item) == getShootCooldown(item)/2)
{
if (WeaponHelper.hasStat(Reference.WS_EXPLOSION_DAMAGE, item))
{
w.createExplosion(player, hitVector.xCoord, hitVector.yCoord, hitVector.zCoord, (float) WeaponHelper.modifyStat(Reference.WS_EXPLOSION_DAMAGE, item,0) * item.getTagCompound().getByte("power") - (MAX_LEVEL/2), true);
}
}
}
}
public Vec3 getPlayerLook(EntityPlayer player,ItemStack weapon)
{
Vec3 dir = player.getLookVec();
Vec3 rot = getBeamRotation(weapon,player);
dir.rotateAroundX((float)rot.xCoord);
dir.rotateAroundY((float) rot.yCoord);
dir.rotateAroundZ((float)rot.zCoord);
return dir;
}
public Vec3 getBeamRotation(ItemStack weapon,EntityPlayer entityPlayer)
{
double rotationY = (float)Math.toRadians(5) * MOEasing.Quart.easeIn(getAccuracy(weapon,entityPlayer,false),0,1,1);
return Vec3.createVectorHelper(0,rotationY,0);
}
@Override
public float getWeaponBaseAccuracy(ItemStack weapon,boolean zoomed)
{
return getHeat(weapon) / getMaxHeat(weapon);
}
@Override
public ItemStack onItemRightClick(ItemStack item, World world, EntityPlayer player)
{
this.TagCompountCheck(item);
if(player.isSneaking())
{
SwitchModes(world,player,item);
}
else
{
if (canFire(item, world,player))
{
player.setItemInUse(item, getMaxItemUseDuration(item));
}
if (needsRecharge(item))
{
chargeFromEnergyPack(item,player);
}
return item;
}
return item;
}
@Override
public void onUsingTick(ItemStack itemStack, EntityPlayer player, int count)
{
if (canFire(itemStack,player.worldObj,player))
{
DrainEnergy(itemStack,1,false);
int powerLevelMultiply = (getPowerLevel(itemStack)+1) / MAX_LEVEL;
float newHeat = (getHeat(itemStack)+1)*(1.1f + (0.05f*powerLevelMultiply));
setHeat(itemStack, newHeat);
ManageShooting(itemStack, player.worldObj, player,count);
manageOverheat(itemStack, player.worldObj, player);
}
else {
player.stopUsingItem();
}
}
private void SwitchModes(World world,EntityPlayer player,ItemStack item)
{
this.TagCompountCheck(item);
SoundHandler.PlaySoundAt(world, "phaser_switch_mode", player);
byte level = getPowerLevel(item);
level++;
if(level >= MAX_LEVEL)
{
level = 0;
}
setPowerLevel(item,level);
}
@Override
public float getWeaponBaseDamage(ItemStack item)
{
float damage = 0;
this.TagCompountCheck(item);
byte level = getPowerLevel(item);
if(level >= KILL_MODE_LEVEL)
{
damage = (float)Math.pow(KILL_DAMAGE_MULTIPLY,level - (KILL_MODE_LEVEL-1));
}
return damage;
}
@Override
public boolean canFire(ItemStack itemStack, World world,EntityLivingBase shooter) {
return !isOverheated(itemStack) && DrainEnergy(itemStack,1,true);
}
@Override
public float getShotSpeed(ItemStack weapon, EntityLivingBase shooter) {
return 0;
}
@Override
@SideOnly(Side.CLIENT)
public void onClientShot(ItemStack weapon, EntityLivingBase shooter, Vec3 position, Vec3 dir,WeaponShot shot)
{
}
private int GetSleepTime(ItemStack item)
{
this.TagCompountCheck(item);
byte level = getPowerLevel(item);
if(level < KILL_MODE_LEVEL)
{
return (int)(Math.pow(level+1,STUN_SLEEP_MULTIPLY) * sleepTimeMultipy(item));
}
return 0;
}
private double sleepTimeMultipy(ItemStack phaser)
{
return WeaponHelper.modifyStat(Reference.WS_DAMAGE,phaser,1);
}
@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(200,45);
}
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,90);
case Reference.MODULE_COLOR:
return new Vector2f(100,80);
case Reference.MODULE_BARREL:
return new Vector2f(85,90);
}
return getSlotPosition(slot,weapon);
}
@Override
@SideOnly(Side.CLIENT)
public void onProjectileHit(MovingObjectPosition hit, ItemStack weapon, World world,float amount)
{
Block b = world.getBlock(hit.blockX,hit.blockY,hit.blockZ);
if (hit.entityHit != null && hit.entityHit instanceof EntityLivingBase)
{
if (WeaponHelper.hasStat(Reference.WS_HEAL,weapon))
{
world.spawnParticle("happyVillager",hit.hitVec.xCoord,hit.hitVec.yCoord,hit.hitVec.zCoord,0,0,0);
}
else if (WeaponHelper.hasStat(Reference.WS_FIRE_DAMAGE,weapon) && MatterOverdriveItems.phaser.isKillMode(weapon))
{
world.spawnParticle("flame",hit.hitVec.xCoord,hit.hitVec.yCoord,hit.hitVec.zCoord,0,0,0);
}
else
{
if (MatterOverdriveItems.phaser.isKillMode(weapon)) {
world.spawnParticle("reddust", hit.hitVec.xCoord, hit.hitVec.yCoord, hit.hitVec.zCoord, 0, 0, 0);
}else
{
world.spawnParticle("magicCrit", hit.hitVec.xCoord, hit.hitVec.yCoord, hit.hitVec.zCoord, 0, 0, 0);
}
}
}
else if(b != null && b != Blocks.air)
{
if (WeaponHelper.hasStat(Reference.WS_FIRE_DAMAGE,weapon) && MatterOverdriveItems.phaser.isKillMode(weapon))
{
world.spawnParticle("flame",hit.hitVec.xCoord,hit.hitVec.yCoord,hit.hitVec.zCoord,0,0,0);
}
world.spawnParticle("smoke",hit.hitVec.xCoord,hit.hitVec.yCoord,hit.hitVec.zCoord,0,0,0);
}
}
@Override
public boolean supportsModule(int slot,ItemStack weapon)
{
return slot != Reference.MODULE_SIGHTS;
}
@Override
public boolean supportsModule(ItemStack weapon, ItemStack module)
{
if (module != null)
{
return module.getItem() == MatterOverdriveItems.weapon_module_barrel || module.getItem() == MatterOverdriveItems.weapon_module_color;
}
return false;
}
@Override
public boolean onServerFire(ItemStack weapon, EntityLivingBase shooter, WeaponShot shot,Vec3 position,Vec3 dir,int delay)
{
return false;
}
@Override
public boolean isAlwaysEquipped(ItemStack weapon) {
return false;
}
@Override
public int getBaseShootCooldown(ItemStack weapon) {
return 10;
}
@Override
public float getBaseZoom(ItemStack weapon, EntityLivingBase shooter)
{
return 0;
}
@Override
@SideOnly(Side.CLIENT)
public boolean isWeaponZoomed(EntityPlayer entityPlayer,ItemStack weapon) {
return false;
}
@Override
public WeaponSound getFireSound(ItemStack weapon,EntityLivingBase entity)
{
//return Reference.MOD_ID + ":" +"phaser_beam_1";
return new WeaponSound(new ResourceLocation(Reference.MOD_ID + ":" +"phaser_beam_1"),(float)entity.posX,(float)entity.posY,(float)entity.posZ,itemRand.nextFloat() * 0.05f + 0.2f,1);
}
public byte getPowerLevel(ItemStack weapon)
{
if (weapon.hasTagCompound())
{
return weapon.getTagCompound().getByte("power");
}
return 0;
}
public void setPowerLevel(ItemStack weapon,byte level)
{
if (weapon.hasTagCompound())
{
weapon.getTagCompound().setByte("power",level);
}
}
}