diff --git a/src/com/shatteredpixel/shatteredpixeldungeon/actors/buffs/Berserk.java b/src/com/shatteredpixel/shatteredpixeldungeon/actors/buffs/Berserk.java new file mode 100644 index 000000000..e5a890f49 --- /dev/null +++ b/src/com/shatteredpixel/shatteredpixeldungeon/actors/buffs/Berserk.java @@ -0,0 +1,145 @@ +package com.shatteredpixel.shatteredpixeldungeon.actors.buffs; + +import com.shatteredpixel.shatteredpixeldungeon.items.BrokenSigil.SigilShield; +import com.shatteredpixel.shatteredpixeldungeon.ui.BuffIndicator; +import com.watabou.utils.Bundle; + +/** + * Created by Evan on 20/03/2016. + */ +public class Berserk extends Buff { + + private enum State{ + NORMAL, BERSERK, EXHAUSTED, RECOVERING; + } + private State state = State.NORMAL; + + private static final int EXHAUSTION_START = 40; + private int exhaustion; + + private static final float LEVEL_RECOVER_START = 2f; + private float levelRecovery; + + private static final String STATE = "state"; + private static final String EXHAUSTION = "exhaustion"; + private static final String LEVEL_RECOVERY = "levelrecovery"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(STATE, state); + if (state == State.EXHAUSTED) bundle.put(EXHAUSTION, exhaustion); + if (state == State.EXHAUSTED || state == State.RECOVERING) bundle.put(LEVEL_RECOVERY, levelRecovery); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + state = bundle.getEnum(STATE, State.class); + if (state == State.EXHAUSTED) exhaustion = bundle.getInt(EXHAUSTION); + if (state == State.EXHAUSTED || state == State.RECOVERING) levelRecovery = bundle.getFloat(LEVEL_RECOVERY); + } + + @Override + public boolean act() { + if (berserking()){ + if (target.HP <= 0) { + target.SHLD -= Math.min(target.SHLD, 2); + if (target.SHLD == 0) { + target.die(this); + } + } else { + state = State.EXHAUSTED; + exhaustion = EXHAUSTION_START; + levelRecovery = LEVEL_RECOVER_START; + BuffIndicator.refreshHero(); + target.SHLD = 0; + } + } else if (state == State.EXHAUSTED){ + exhaustion--; + if (exhaustion == 0){ + state = State.RECOVERING; + BuffIndicator.refreshHero(); + } + } + spend(TICK); + return true; + } + + public int damageFactor(int dmg){ + float percentMissing = 1f - target.HP/(float)target.HT; + float bonus = 1f + (percentMissing * percentMissing); + + if (state == State.EXHAUSTED) bonus *= (50 - exhaustion) / 50f; + + return Math.round(dmg * bonus); + } + + public boolean berserking(){ + if (target.HP == 0 && state == State.NORMAL){ + + SigilShield sigil = target.buff(SigilShield.class); + if (sigil != null){ + state = State.BERSERK; + BuffIndicator.refreshHero(); + target.SHLD = sigil.maxShield() * 5; + } + + } + + return state == State.BERSERK; + } + + public void recover(float percent){ + if (levelRecovery > 0){ + levelRecovery -= percent; + if (levelRecovery <= 0) { + state = State.NORMAL; + BuffIndicator.refreshHero(); + levelRecovery = 0; + } + } + } + + @Override + public int icon() { + switch (state){ + case NORMAL: default: + return BuffIndicator.NONE; + case BERSERK: + return BuffIndicator.FURY; + case EXHAUSTED: + return BuffIndicator.FURY; + case RECOVERING: + return BuffIndicator.FURY; + } + } + + @Override + public String toString() { + switch (state){ + case NORMAL: default: + return ""; + case BERSERK: + return "BERSERK!"; + case EXHAUSTED: + return "Exhausted"; + case RECOVERING: + return "Recovering"; + } + } + + @Override + public String desc() { + switch (state){ + case NORMAL: default: + return ""; + case BERSERK: + return "Berserking, you're invincible!"; + case EXHAUSTED: + return "Exhausted! Damage down!"; + case RECOVERING: + return "Recovering from rage, can't do it again."; + } + } +} diff --git a/src/com/shatteredpixel/shatteredpixeldungeon/actors/hero/Hero.java b/src/com/shatteredpixel/shatteredpixeldungeon/actors/hero/Hero.java index 172b604f0..b21b03d01 100644 --- a/src/com/shatteredpixel/shatteredpixeldungeon/actors/hero/Hero.java +++ b/src/com/shatteredpixel/shatteredpixeldungeon/actors/hero/Hero.java @@ -29,6 +29,7 @@ import com.shatteredpixel.shatteredpixeldungeon.Statistics; import com.shatteredpixel.shatteredpixeldungeon.actors.Actor; import com.shatteredpixel.shatteredpixeldungeon.actors.Char; import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Barkskin; +import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Berserk; import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Bless; import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff; import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Combo; @@ -321,6 +322,9 @@ public class Hero extends Char { } } if (dmg < 0) dmg = 0; + if (subClass == HeroSubClass.BERSERKER){ + dmg = Buff.affect(this, Berserk.class).damageFactor(dmg); + } return buff( Fury.class ) != null ? (int)(dmg * 1.5f) : dmg; } @@ -905,10 +909,6 @@ public class Hero extends Char { dmg = (int)Math.ceil((float)dmg * Math.pow(0.9, tenacity*((float)(HT - HP)/HT))); super.damage( dmg, src ); - - if (subClass == HeroSubClass.BERSERKER && 0 < HP && HP <= HT * Fury.LEVEL) { - Buff.affect( this, Fury.class ); - } } private void checkVisibleMobs() { @@ -1081,6 +1081,7 @@ public class Hero extends Char { EtherealChains.chainsRecharge chains = buff(EtherealChains.chainsRecharge.class); if (chains != null) chains.gainExp(percent); + if (subClass == HeroSubClass.BERSERKER) Buff.affect(this, Berserk.class).recover(percent); boolean levelUp = false; while (this.exp >= maxExp()) { @@ -1288,7 +1289,12 @@ public class Hero extends Char { Dungeon.deleteGame( Dungeon.hero.heroClass, true ); } - + + @Override + public boolean isAlive() { + return super.isAlive() || (subClass == HeroSubClass.BERSERKER && Buff.affect(this, Berserk.class).berserking()); + } + @Override public void move( int step ) { super.move( step ); diff --git a/src/com/shatteredpixel/shatteredpixeldungeon/items/BrokenSigil.java b/src/com/shatteredpixel/shatteredpixeldungeon/items/BrokenSigil.java index 2bdcd1d24..ca85c9aab 100644 --- a/src/com/shatteredpixel/shatteredpixeldungeon/items/BrokenSigil.java +++ b/src/com/shatteredpixel/shatteredpixeldungeon/items/BrokenSigil.java @@ -77,9 +77,8 @@ public class BrokenSigil extends Item { public boolean act() { if (armor == null) detach(); else if (armor.isEquipped((Hero)target)) { - int maxShield = 1 + armor.tier + armor.level(); - if (target.SHLD < maxShield){ - partialShield += 1/(30*Math.pow(0.9f, (maxShield - target.SHLD))); + if (target.SHLD < maxShield()){ + partialShield += 1/(30*Math.pow(0.9f, (maxShield() - target.SHLD))); } } while (partialShield >= 1){ @@ -93,5 +92,9 @@ public class BrokenSigil extends Item { public void setArmor(Armor arm){ armor = arm; } + + public int maxShield() { + return 1 + armor.tier + armor.level(); + } } }