/**
Copyright (C) <2015> <coolAlias>
This file is part of coolAlias' Zelda Sword Skills Minecraft Mod; as such,
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.
This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
package zeldaswordskills.skills.sword;
import java.util.List;
import net.minecraft.client.Minecraft;
import net.minecraft.client.settings.KeyBinding;
import net.minecraft.entity.Entity;
import net.minecraft.entity.SharedMonsterAttributes;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.world.World;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import zeldaswordskills.client.ZSSClientEvents;
import zeldaswordskills.client.ZSSKeyHandler;
import zeldaswordskills.entity.player.ZSSPlayerSkills;
import zeldaswordskills.entity.projectile.EntityLeapingBlow;
import zeldaswordskills.network.PacketDispatcher;
import zeldaswordskills.network.bidirectional.ActivateSkillPacket;
import zeldaswordskills.ref.Sounds;
import zeldaswordskills.skills.SkillActive;
import zeldaswordskills.util.PlayerUtils;
import zeldaswordskills.util.TargetUtils;
import zeldaswordskills.util.WorldUtils;
/**
*
* LEAPING BLOW
* Activation: Jump while holding block
* Damage: Regular sword damage (without enchantment bonuses), +1 extra damage per skill level
* Effect: Adds Weakness I for (50 + (10 * level)) ticks
* Range: Technique travels roughly 3 blocks + 1/2 block per level
* Area: Approximately (0.5F + (0.25F * level)) radius in a straight line
* Exhaustion: 2.0F minus 0.1F per level (1.5F at level 5)
* Special: Wielding a Master Sword causes double bonus damage and weakness time,
* but only while at full health
*
* Upon landing, all targets directly in front of the player take damage and
* are weakened temporarily.
*
*/
public class LeapingBlow extends SkillActive
{
/** Set to true when jumping and 'attack' key pressed; set to false upon landing */
private boolean isActive;
/** Whether the player is wielding a Master Sword */
private boolean isMaster;
public LeapingBlow(String name) {
super(name);
}
private LeapingBlow(LeapingBlow skill) {
super(skill);
}
@Override
public LeapingBlow newInstance() {
return new LeapingBlow(this);
}
@Override
@SideOnly(Side.CLIENT)
public void addInformation(List<String> desc, EntityPlayer player) {
desc.add(getDamageDisplay((PlayerUtils.isHoldingMasterSword(player) ? level * 2 : level), true));
desc.add(getRangeDisplay(3.0F + 0.5F * level));
desc.add(getAreaDisplay(0.5F + 0.25F * level));
desc.add(getDurationDisplay(getPotionDuration(player), false));
desc.add(getExhaustionDisplay(getExhaustion()));
}
@Override
public boolean isActive() {
return isActive;
}
@Override
protected float getExhaustion() {
return 2.0F - (0.1F * level);
}
/**
* LeapingBlow adds exhaustion after entity is spawned, rather than on initial activation
*/
@Override
protected boolean autoAddExhaustion() {
return false;
}
/** Returns player's base damage (which includes all attribute bonuses) plus 1.0F per level */
private float getDamage(EntityPlayer player) {
return (float)((PlayerUtils.isHoldingMasterSword(player) ? level * 2 : level)
+ player.getEntityAttribute(SharedMonsterAttributes.attackDamage).getAttributeValue());
}
/** Duration of weakness effect; used for tooltip display only */
private int getPotionDuration(EntityPlayer player) {
return ((PlayerUtils.isHoldingMasterSword(player) ? 110 : 50) + (level * 10));
}
@Override
public boolean canUse(EntityPlayer player) {
return super.canUse(player) && !isActive() && PlayerUtils.isSword(player.getHeldItem()) && !TargetUtils.isInLiquid(player);
}
@Override
@SideOnly(Side.CLIENT)
public boolean canExecute(EntityPlayer player) {
// changed from !onGround now that jump key handled immediately from KeyInputEvent
return !isActive() && player.onGround && PlayerUtils.isBlocking(player) && !TargetUtils.isInLiquid(player);
}
@Override
@SideOnly(Side.CLIENT)
public boolean isKeyListener(Minecraft mc, KeyBinding key) {
return key == mc.gameSettings.keyBindJump;
}
@Override
@SideOnly(Side.CLIENT)
public boolean keyPressed(Minecraft mc, KeyBinding key, EntityPlayer player) {
if (canExecute(player)) {
PacketDispatcher.sendToServer(new ActivateSkillPacket(this));
KeyBinding.setKeyBindState(mc.gameSettings.keyBindUseItem.getKeyCode(), false);
KeyBinding.setKeyBindState(ZSSKeyHandler.keys[ZSSKeyHandler.KEY_BLOCK].getKeyCode(), false);
return true;
}
return false;
}
@Override
protected boolean onActivated(World world, EntityPlayer player) {
isActive = true;
isMaster = (PlayerUtils.isHoldingMasterSword(player) && PlayerUtils.getHealthMissing(player) == 0.0F);
return isActive();
}
@Override
protected void onDeactivated(World world, EntityPlayer player) {
isActive = false;
}
@Override
public void onUpdate(EntityPlayer player) {
// Handle on client because onGround is always true on the server
if (player.worldObj.isRemote && isActive() && (player.onGround || TargetUtils.isInLiquid(player))) {
deactivate(player);
}
}
/**
* Called from Forge fall Events (note that these are not fired if player lands in liquid!)
* @param distance distance fallen, passed from Forge fall Event
*/
public void onImpact(EntityPlayer player, float distance) {
SwordBasic swordSkill = (SwordBasic) ZSSPlayerSkills.get(player).getPlayerSkill(swordBasic);
if (isActive() && swordSkill != null && swordSkill.isActive() && PlayerUtils.isSword(player.getHeldItem())) {
if (player.worldObj.isRemote) {
if (distance < 1.0F) {
ZSSClientEvents.performComboAttack(Minecraft.getMinecraft(), swordSkill);
} else {
player.swingItem();
}
} else if (distance >= 1.0F) {
// add exhaustion here, now that skill has truly activated:
player.addExhaustion(getExhaustion());
Entity entity = new EntityLeapingBlow(player.worldObj, player).setDamage(getDamage(player)).setLevel(level, isMaster);
player.worldObj.spawnEntityInWorld(entity);
WorldUtils.playSoundAtEntity(player, Sounds.LEAPING_BLOW, 0.4F, 0.5F);
}
}
onDeactivated(player.worldObj, player);
}
}