diff --git a/core/src/main/assets/messages/actors/actors.properties b/core/src/main/assets/messages/actors/actors.properties index bbe83d0d6..449782c98 100644 --- a/core/src/main/assets/messages/actors/actors.properties +++ b/core/src/main/assets/messages/actors/actors.properties @@ -232,9 +232,7 @@ actors.buffs.poison.desc=Poison works its way through the body, slowly impairing actors.buffs.preparation.name=Preparation actors.buffs.preparation.desc=The Assassin is waiting patiently, preparing to strike from the shadows. -actors.buffs.preparation.desc_dmg=His next attack will do _%d%% bonus damage._ -actors.buffs.preparation.desc_dmg_scale=His next attack will do _%d%%-%d%% bonus damage,_ depending on how injured the target is. -actors.buffs.preparation.desc_dmg_instakill=His next attack will _instantly kill_ any non-boss enemy!\n\nOtherwise it will do _%d%%-%d%% bonus damage,_ depending on how injured the target is. +actors.buffs.preparation.desc_dmg=His next attack will deal _%1$d%% bonus damage_, and will execute regular enemies below _%2$d%% health_, or bosses below _%3$d%% health_. actors.buffs.preparation.desc_dmg_likely=The attack will also be more likely to deal a larger amount of damage. actors.buffs.preparation.desc_blink=He is able to blink towards an enemy before striking them, with a max distance of _%d._ actors.buffs.preparation.desc_invis_time=The Assassin has been invisible for _%d turns._ @@ -242,6 +240,7 @@ actors.buffs.preparation.desc_invis_next=His attack will become stronger at _%d actors.buffs.preparation.prompt=Select a target to attack!\nMax blink distance: %d actors.buffs.preparation.no_target=There's nothing to attack there. actors.buffs.preparation.out_of_reach=That target is out of reach. +actors.buffs.preparation.assassinated=assassinated actors.buffs.prismaticguard.name=Prismatic Guard actors.buffs.prismaticguard.desc=You are being guarded by a prismatic image which is currently inactive. When enemies are present the prismatic image will spring to action and protect you!\n\nWhile inactive, the prismatic image will steadily recover from any damage it has taken.\n\nCurrent HP: %d/%d. diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/Char.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/Char.java index fdc8289c6..305d2165f 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/Char.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/Char.java @@ -265,7 +265,7 @@ public abstract class Char extends Actor { int dmg; Preparation prep = buff(Preparation.class); if (prep != null){ - dmg = prep.damageRoll(this, enemy); + dmg = prep.damageRoll(this); } else { dmg = damageRoll(); } @@ -298,6 +298,11 @@ public abstract class Char extends Actor { if (buff(FrostImbue.class) != null) buff(FrostImbue.class).proc(enemy); + if (prep != null && prep.canKO(enemy)){ + enemy.die(this); + enemy.sprite.showStatus(CharSprite.NEGATIVE, Messages.get(Preparation.class, "assassinated")); + } + enemy.sprite.bloodBurstA( sprite.center(), effectiveDamage ); enemy.sprite.flash(); diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/buffs/Preparation.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/buffs/Preparation.java index c18bce206..716c95869 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/buffs/Preparation.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/buffs/Preparation.java @@ -54,36 +54,37 @@ public class Preparation extends Buff implements ActionIndicator.Action { } public enum AttackLevel{ - LVL_1( 1, 0.1f, 0.0f, 1, 0), - LVL_2( 3, 0.2f, 0.0f, 1, 1), - LVL_3( 6, 0.3f, 0.0f, 2, 3), - LVL_4( 11, 0.4f, 0.6f, 2, 5), - LVL_5( 16, 0.5f, 1.0f, 3, 7); + LVL_1( 1, 0.15f, 0.05f, 1, 1), + LVL_2( 3, 0.30f, 0.15f, 1, 3), + LVL_3( 6, 0.45f, 0.30f, 2, 5), + LVL_4( 11, 0.60f, 0.50f, 3, 7); final int turnsReq; - final float baseDmgBonus, missingHPBonus; + final float baseDmgBonus, KOThreshold; final int damageRolls, blinkDistance; - AttackLevel( int turns, float base, float missing, int rolls, int dist){ + AttackLevel( int turns, float base, float threshold, int rolls, int dist){ turnsReq = turns; - baseDmgBonus = base; missingHPBonus = missing; - damageRolls =rolls; blinkDistance = dist; + baseDmgBonus = base; KOThreshold = threshold; + damageRolls = rolls; blinkDistance = dist; } - public boolean canInstakill(Char defender){ - return this == LVL_5 - && !defender.properties().contains(Char.Property.MINIBOSS) - && !defender.properties().contains(Char.Property.BOSS); + public boolean canKO(Char defender){ + if (defender.properties().contains(Char.Property.MINIBOSS) + || defender.properties().contains(Char.Property.BOSS)){ + return (defender.HP/(float)defender.HT) <= (KOThreshold/5f); + } else { + return (defender.HP/(float)defender.HT) <= KOThreshold; + } } - public int damageRoll( Char attacker, Char defender){ + public int damageRoll( Char attacker ){ int dmg = attacker.damageRoll(); for( int i = 1; i < damageRolls; i++){ int newDmg = attacker.damageRoll(); if (newDmg > dmg) dmg = newDmg; } - float defenderHPPercent = 1f - (defender.HP / (float)defender.HT); - return Math.round(dmg * (1f + baseDmgBonus + (missingHPBonus * defenderHPPercent))); + return Math.round(dmg * (1f + baseDmgBonus)); } public static AttackLevel getLvl(int turnsInvis){ @@ -120,16 +121,12 @@ public class Preparation extends Buff implements ActionIndicator.Action { ActionIndicator.clearAction(this); } - public int damageRoll(Char attacker, Char defender ){ - AttackLevel lvl = AttackLevel.getLvl(turnsInvis); - if (lvl.canInstakill(defender)){ - int dmg = lvl.damageRoll(attacker, defender); - defender.damage( Math.max(defender.HT, dmg), attacker ); - //even though the defender is dead, other effects should still proc (enchants, etc.) - return Math.max( defender.HT, dmg); - } else { - return lvl.damageRoll(attacker, defender); - } + public int damageRoll( Char attacker ){ + return AttackLevel.getLvl(turnsInvis).damageRoll(attacker); + } + + public boolean canKO( Char defender ){ + return AttackLevel.getLvl(turnsInvis).canKO(defender); } @Override @@ -141,18 +138,15 @@ public class Preparation extends Buff implements ActionIndicator.Action { public void tintIcon(Image icon) { switch (AttackLevel.getLvl(turnsInvis)){ case LVL_1: - icon.hardlight(1f, 1f, 1f); - break; - case LVL_2: icon.hardlight(0f, 1f, 0f); break; - case LVL_3: + case LVL_2: icon.hardlight(1f, 1f, 0f); break; - case LVL_4: + case LVL_3: icon.hardlight(1f, 0.6f, 0f); break; - case LVL_5: + case LVL_4: icon.hardlight(1f, 0f, 0f); break; } @@ -160,7 +154,7 @@ public class Preparation extends Buff implements ActionIndicator.Action { @Override public float iconFadePercent() { - if (AttackLevel.getLvl(turnsInvis) == AttackLevel.LVL_5){ + if (AttackLevel.getLvl(turnsInvis) == AttackLevel.LVL_4){ return 0; } else { float turnsForCur = AttackLevel.getLvl(turnsInvis).turnsReq; @@ -181,18 +175,11 @@ public class Preparation extends Buff implements ActionIndicator.Action { String desc = Messages.get(this, "desc"); AttackLevel lvl = AttackLevel.getLvl(turnsInvis); - - if (lvl.canInstakill(new Rat())){ - desc += "\n\n" + Messages.get(this, "desc_dmg_instakill", - (int)(lvl.baseDmgBonus*100), - (int)(lvl.baseDmgBonus*100 + lvl.missingHPBonus*100)); - } else if (lvl.missingHPBonus > 0){ - desc += "\n\n" + Messages.get(this, "desc_dmg_scale", - (int)(lvl.baseDmgBonus*100), - (int)(lvl.baseDmgBonus*100 + lvl.missingHPBonus*100)); - } else { - desc += "\n\n" + Messages.get(this, "desc_dmg", (int)(lvl.baseDmgBonus*100)); - } + + desc += "\n\n" + Messages.get(this, "desc_dmg", + (int)(lvl.baseDmgBonus*100), + (int)(lvl.KOThreshold*100), + (int)(lvl.KOThreshold*20)); if (lvl.damageRolls > 1){ desc += " " + Messages.get(this, "desc_dmg_likely"); diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/buffs/SnipersMark.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/buffs/SnipersMark.java index 2185b8e84..1fabefe93 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/buffs/SnipersMark.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/buffs/SnipersMark.java @@ -41,7 +41,7 @@ public class SnipersMark extends FlavourBuff implements ActionIndicator.Action { private static final String OBJECT = "object"; - public static final float DURATION = 2f; + public static final float DURATION = 4f; { type = buffType.POSITIVE; diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/weapon/SpiritBow.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/weapon/SpiritBow.java index f9e0e3d72..44fa9f46a 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/weapon/SpiritBow.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/weapon/SpiritBow.java @@ -166,10 +166,10 @@ public class SpiritBow extends Weapon { damage = Math.round(damage * 0.5f); break; case DAMAGE: - //as distance increases so does damage, capping at 2.5x: - //1.20x|1.32x|1.45x|1.59x|1.76x|1.93x|2.13x|2.34x|2.50x + //as distance increases so does damage, capping at 3x: + //1.20x|1.35x|1.52x|1.71x|1.92x|2.16x|2.43x|2.74x|3.00x int distance = Dungeon.level.distance(owner.pos, targetPos) - 1; - float multiplier = Math.min(2.5f, 1.2f * (float)Math.pow(1.1f, distance)); + float multiplier = Math.min(2.5f, 1.2f * (float)Math.pow(1.125f, distance)); damage = Math.round(damage * multiplier); break; }