v0.8.1: balance/design improvements to assassin and sniper:
- sniper's mark now lasts 4 turns, up from 2 - further increased distance-based damage scaling on sniper shot - assassin preparation now maxes at 11 turns, and becomes stronger faster - preparation now executes enemies below a health threshold, rather than dealing more damage at low enemy HP.
This commit is contained in:
@@ -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.
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user