/*
* 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.data.biostats;
import com.google.common.collect.Multimap;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import matteroverdrive.Reference;
import matteroverdrive.api.events.bionicStats.MOEventBionicStat;
import matteroverdrive.client.sound.MOPositionedSound;
import matteroverdrive.entity.player.AndroidAttributes;
import matteroverdrive.entity.player.AndroidPlayer;
import matteroverdrive.handler.ConfigurationHandler;
import matteroverdrive.handler.KeyHandler;
import matteroverdrive.proxy.ClientProxy;
import matteroverdrive.util.IConfigSubscriber;
import net.minecraft.client.Minecraft;
import net.minecraft.entity.ai.attributes.AttributeModifier;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.util.DamageSource;
import net.minecraft.util.MathHelper;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.event.entity.living.LivingAttackEvent;
import net.minecraftforge.event.entity.living.LivingEvent;
import net.minecraftforge.event.entity.living.LivingHurtEvent;
import org.lwjgl.input.Keyboard;
import java.util.EnumSet;
import java.util.Random;
import java.util.UUID;
/**
* Created by Simeon on 6/9/2015.
*/
public class BioticStatShield extends AbstractBioticStat implements IConfigSubscriber
{
public static int ENERGY_PER_TICK = 64;
public static int ENERGY_PER_DAMAGE = 256;
public static int SHIELD_COOLDOWN = 20*16;
public static int SHIELD_TIME = 20*8;
public static final String TAG_SHIELD = "Shield";
public static final String TAG_SHIELD_LAST_USE = "ShieldLastUse";
public static final String TAG_HITS = "Hits";
@SideOnly(Side.CLIENT)
private MOPositionedSound shieldSound;
private AttributeModifier modifyer;
private Random random;
public BioticStatShield(String name, int xp)
{
super(name, xp);
setShowOnHud(true);
modifyer = new AttributeModifier(UUID.fromString("ead117ad-105a-43fe-ab22-a31aee6adc42"),"Shield Slowdown",-0.4,2);
random = new Random();
setShowOnWheel(true);
}
@Override
public void onAndroidUpdate(AndroidPlayer android, int level)
{
if (!android.getPlayer().worldObj.isRemote)
{
if (android.getEffects().getBoolean(TAG_SHIELD))
{
android.extractEnergyScaled(ENERGY_PER_TICK);
}
if (android.getEffects().hasKey(TAG_HITS)) {
NBTTagList attackList = android.getEffects().getTagList(TAG_HITS, 10);
if (attackList.tagCount() > 0)
{
if (attackList.getCompoundTagAt(0).getInteger("time") > 0)
{
attackList.getCompoundTagAt(0).setInteger("time",attackList.getCompoundTagAt(0).getInteger("time") - 1);
}
else
{
attackList.removeTag(0);
}
} else {
android.getEffects().removeTag(TAG_HITS);
}
android.sync(EnumSet.of(AndroidPlayer.DataType.EFFECTS),true);
}
}
}
@Override
public void onActionKeyPress(AndroidPlayer androidPlayer, int level, boolean server)
{
if (this.equals(androidPlayer.getActiveStat()) && canActivate(androidPlayer) && !MinecraftForge.EVENT_BUS.post(new MOEventBionicStat(this,level, androidPlayer)))
{
setShield(androidPlayer,true);
androidPlayer.sync(EnumSet.of(AndroidPlayer.DataType.EFFECTS),true);
}
}
@Override
public void onKeyPress(AndroidPlayer androidPlayer, int level, int keycode, boolean down)
{
}
public void setShield(AndroidPlayer androidPlayer,boolean on)
{
androidPlayer.getEffects().setBoolean(TAG_SHIELD,on);
setLastShieldTime(androidPlayer,androidPlayer.getPlayer().worldObj.getTotalWorldTime() + SHIELD_COOLDOWN + SHIELD_TIME);
androidPlayer.sync(EnumSet.of(AndroidPlayer.DataType.EFFECTS),true);
androidPlayer.getPlayer().worldObj.playSoundAtEntity(androidPlayer.getPlayer(),Reference.MOD_ID + ":" + "shield_power_up",0.6f + random.nextFloat()*0.2f,1);
//androidPlayer.getPlayer().getAttributeMap().getAttributeInstance(SharedMonsterAttributes.movementSpeed).removeModifier(modifyer);
//androidPlayer.getPlayer().getAttributeMap().getAttributeInstance(SharedMonsterAttributes.movementSpeed).applyModifier(modifyer);
}
public String getDetails(int level)
{
String key = "Unknown";
try
{
key = Keyboard.getKeyName(ClientProxy.keyHandler.getBinding(KeyHandler.ABILITY_USE_KEY).getKeyCode());
}catch (Exception e)
{
}
return String.format(super.getDetails(level), key);
}
public boolean getShieldState(AndroidPlayer androidPlayer)
{
return androidPlayer.getEffects().getBoolean(TAG_SHIELD);
}
public long getLastShieldTime(AndroidPlayer androidPlayer)
{
return androidPlayer.getEffects().getLong("TAG_SHIELD_LAST_USE");
}
public void setLastShieldTime(AndroidPlayer androidPlayer,long time)
{
androidPlayer.getEffects().setLong("TAG_SHIELD_LAST_USE",time);
}
public boolean canActivate(AndroidPlayer androidPlayer)
{
return getLastShieldTime(androidPlayer) - androidPlayer.getPlayer().worldObj.getTotalWorldTime() <= 0;
}
@Override
public void onLivingEvent(AndroidPlayer androidPlayer, int level, LivingEvent event)
{
if (event instanceof LivingAttackEvent)
{
DamageSource source = ((LivingAttackEvent) event).source;
if (getShieldState(androidPlayer))
{
int energyReqired = MathHelper.ceiling_float_int(((LivingAttackEvent) event).ammount * ENERGY_PER_DAMAGE);
if (isDamageValid(source) && event.isCancelable())
{
if (source.getSourceOfDamage() != null) {
NBTTagCompound attack = new NBTTagCompound();
NBTTagList attackList = androidPlayer.getEffects().getTagList(TAG_HITS, 10);
attack.setDouble("x", source.getSourceOfDamage().posX - event.entityLiving.posX);
attack.setDouble("y", source.getSourceOfDamage().posY - (event.entityLiving.posY + 1.5));
attack.setDouble("z", source.getSourceOfDamage().posZ - event.entityLiving.posZ);
attack.setInteger("time", 10);
attackList.appendTag(attack);
androidPlayer.getEffects().setTag(TAG_HITS, attackList);
androidPlayer.sync(EnumSet.of(AndroidPlayer.DataType.EFFECTS),true);
androidPlayer.getPlayer().worldObj.playSoundAtEntity(androidPlayer.getPlayer(),Reference.MOD_ID + ":" + "shield_hit",0.5f,0.9f + random.nextFloat() * 0.2f);
}
if (androidPlayer.hasEnoughEnergyScaled(energyReqired))
{
androidPlayer.extractEnergyScaled(energyReqired);
event.setCanceled(true);
}
}
}
}else if (event instanceof LivingHurtEvent)
{
DamageSource source = ((LivingHurtEvent) event).source;
if (getShieldState(androidPlayer)) {
int energyReqired = MathHelper.ceiling_float_int(((LivingHurtEvent) event).ammount * ENERGY_PER_DAMAGE);
if (isDamageValid(source)) {
double energyMultiply = androidPlayer.getPlayer().getAttributeMap().getAttributeInstance(AndroidAttributes.attributeBatteryUse).getAttributeValue();
energyReqired *= energyMultiply;
int energyExtracted = androidPlayer.extractEnergy(energyReqired, true);
((LivingHurtEvent) event).ammount *= (float) energyExtracted / (float) energyReqired;
}
}
}
}
public boolean isDamageValid(DamageSource damageSource)
{
return damageSource.isExplosion() || damageSource.isProjectile();
}
@Override
public void changeAndroidStats(AndroidPlayer androidPlayer, int level, boolean enabled)
{
if (androidPlayer.getPlayer().worldObj.isRemote)
{
if (!androidPlayer.getEffects().getBoolean(TAG_SHIELD))
{
stopShieldSound();
} else
{
playShieldSound();
}
}else
{
long shieldTime = getLastShieldTime(androidPlayer) - androidPlayer.getPlayer().worldObj.getTotalWorldTime();
if (shieldTime < SHIELD_COOLDOWN && androidPlayer.getEffects().getBoolean(TAG_SHIELD))
{
androidPlayer.getEffects().setBoolean(TAG_SHIELD,false);
androidPlayer.getEffects().removeTag(TAG_HITS);
androidPlayer.sync(EnumSet.of(AndroidPlayer.DataType.EFFECTS),true);
androidPlayer.getPlayer().worldObj.playSoundAtEntity(androidPlayer.getPlayer(),Reference.MOD_ID + ":" + "shield_power_down",0.6f + random.nextFloat() * 0.2f,1);
//androidPlayer.init(androidPlayer.getPlayer(),androidPlayer.getPlayer().worldObj);
}
}
}
@Override
public Multimap attributes(AndroidPlayer androidPlayer, int level)
{
//Multimap multimap = HashMultimap.create();
//multimap.put(SharedMonsterAttributes.movementSpeed.getAttributeUnlocalizedName(),modifyer);
return null;
}
@SideOnly(Side.CLIENT)
protected void playShieldSound()
{
if(shieldSound == null && !Minecraft.getMinecraft().getSoundHandler().isSoundPlaying(shieldSound))
{
shieldSound = new MOPositionedSound(new ResourceLocation(Reference.MOD_ID + ":" + "shield_loop"),0.3f + random.nextFloat() * 0.2f,1);
shieldSound.setRepeat(true);
Minecraft.getMinecraft().getSoundHandler().playSound(shieldSound);
}
}
@SideOnly(Side.CLIENT)
protected void stopShieldSound()
{
if(shieldSound != null && Minecraft.getMinecraft().getSoundHandler().isSoundPlaying(shieldSound))
{
Minecraft.getMinecraft().getSoundHandler().stopSound(shieldSound);
shieldSound = null;
}
}
@Override
public boolean isEnabled(AndroidPlayer androidPlayer,int level)
{
long shieldTime = getLastShieldTime(androidPlayer) - androidPlayer.getPlayer().worldObj.getTotalWorldTime();
return super.isEnabled(androidPlayer,level) && androidPlayer.hasEnoughEnergyScaled(ENERGY_PER_TICK) && (shieldTime <= 0 || shieldTime > SHIELD_COOLDOWN);
}
@Override
public boolean isActive(AndroidPlayer androidPlayer, int level)
{
return getShieldState(androidPlayer);
}
@Override
public boolean showOnHud(AndroidPlayer android,int level)
{
return this.equals(android.getActiveStat()) || getShieldState(android);
}
@Override
public int getDelay(AndroidPlayer androidPlayer, int level)
{
long shieldTime = getLastShieldTime(androidPlayer) - androidPlayer.getPlayer().worldObj.getTotalWorldTime();
if (shieldTime > 0)
{
return (int)shieldTime;
}
return 0;
}
@Override
public void onConfigChanged(ConfigurationHandler config)
{
ENERGY_PER_DAMAGE = config.getInt("shield_energy_per_damage",ConfigurationHandler.CATEGORY_ABILITIES,256,"The energy cost of each hit to the shield");
ENERGY_PER_TICK = config.getInt("shield_energy_per_tick",ConfigurationHandler.CATEGORY_ABILITIES,64,"The energy cost of the shield per tick");
}
}