v2.5.0: various monk adjustments.

Meant to nerf meditate spam and buff everything else:

Abilities:
- removed overall ability cooldown, but added a short one for flurry
- flurry dmg +50%
- focus now blocks magic and has infinite duration
- dash range +1 (+2 when empowered)
- dragon kick dmg x2
- mediate unchanged

talents:
- unencumbered spirit boost changed to 50/75/100, from 40/80/120
- combined energy is now more permissive and always reduces charge use by 1
This commit is contained in:
Evan Debenham
2024-07-26 14:22:09 -04:00
parent 6217f64f13
commit bf56446d04
7 changed files with 68 additions and 94 deletions

View File

@@ -293,17 +293,17 @@ actors.buffs.monkenergy.action=Monk Abilities
actors.buffs.monkenergy.desc=As she defeats enemies, the Monk gains energy that she can use on a variety of abilities. Most enemies grant 1 energy when defeated, and the Monk does not lose energy over time.\n\nCurrent energy: %1$d/%2$d.
actors.buffs.monkenergy.desc_cooldown=The Monk has recently used an ability, and must wait before using another.\n\nCurrent cooldown: %d turns.
actors.buffs.monkenergy$monkability$flurry.name=flurry of blows
actors.buffs.monkenergy$monkability$flurry.desc=Two instant strikes that deal %1$d-%2$d damage and ignore armor. This ability has no cooldown if the Monk just successfully attacked an enemy.
actors.buffs.monkenergy$monkability$flurry.empower_desc=Two instant strikes that deal %1$d-%2$d damage, ignore armor, _and use your weapon's enchantment._ No cooldown if the Monk just attacked.
actors.buffs.monkenergy$monkability$flurry.desc=Two instant strikes that deal %1$d-%2$d damage and ignore armor. This ability cannot be used repeatedly.
actors.buffs.monkenergy$monkability$flurry.empower_desc=Two instant strikes that deal %1$d-%2$d damage, ignore armor, _and use your weapon's enchantment._ This ability cannot be used repeatedly.
actors.buffs.monkenergy$monkability$focus.name=focus
actors.buffs.monkenergy$monkability$focus.desc=The Monk takes a turn to focus, letting her parry the next physical attack made against her within 30 turns.
actors.buffs.monkenergy$monkability$focus.empower_desc=The Monk _instantly focuses,_ letting her parry the next physical attack made against her within 30 turns.
actors.buffs.monkenergy$monkability$focus.desc=The Monk takes a turn to focus, letting her parry the next attack made against her.
actors.buffs.monkenergy$monkability$focus.empower_desc=The Monk _instantly focuses,_ letting her parry the next attack made against her.
actors.buffs.monkenergy$monkability$focus$focusbuff.name=focused
actors.buffs.monkenergy$monkability$focus$focusbuff.desc=The Monk is focused on her surroundings, anticipating the next physical attack made against her. While focused, she is guaranteed to parry the next incoming physical attack.\n\nTurns remaining: %s.
actors.buffs.monkenergy$monkability$focus$focusbuff.desc=The Monk is focused on her surroundings, anticipating the next attack made against her. While focused, she is guaranteed to parry the next incoming physical attack.
actors.buffs.monkenergy$monkability$dash.name=dash
actors.buffs.monkenergy$monkability$dash.prompt=Choose a Location
actors.buffs.monkenergy$monkability$dash.desc=An instant dash up to 3 tiles away. This ability can go over hazards, but not through enemies or solid terrain.
actors.buffs.monkenergy$monkability$dash.empower_desc=An instant dash up to _6 tiles_ away. This ability can go over hazards, but not through enemies or solid terrain.
actors.buffs.monkenergy$monkability$dash.desc=An instant dash up to 4 tiles away. This ability can go over hazards, but not through enemies or solid terrain.
actors.buffs.monkenergy$monkability$dash.empower_desc=An instant dash up to _8 tiles_ away. This ability can go over hazards, but not through enemies or solid terrain.
actors.buffs.monkenergy$monkability$dragonkick.name=dragon kick
actors.buffs.monkenergy$monkability$dragonkick.desc=A devastating kick that deals %1$d-%2$d damage and ignores armor. The kick knocks the target away and paralyzes them for each tile they travel.
actors.buffs.monkenergy$monkability$dragonkick.empower_desc=A devastating kick that deals _%1$d-%2$d damage_ and ignores armor. The kick knocks _all adjacent targets_ away and paralyzes them for each tile they travel.
@@ -927,11 +927,11 @@ actors.hero.talent.combined_lethality.title=combined lethality
actors.hero.talent.combined_lethality.desc=_+1:_ If the Champion uses two different weapon abilities successively, the second ability will execute any non-boss enemy left at _below 13% HP_.\n\n_+2:_ If the Champion uses two different weapon abilities successively, the second ability will execute any non-boss enemy left at _below 27% HP_.\n\n_+3:_ If the Champion uses two different weapon abilities successively, the second ability will execute any non-boss enemy left at _below 40% HP_.\n\nIf the second ability does not contain an attack, this talent will instead trigger on the Champion's next attack within 5 turns.
actors.hero.talent.unencumbered_spirit.title=unencumbered spirit
actors.hero.talent.unencumbered_spirit.desc=_+1:_ The Monk gains _40% more energy_ for each piece of _tier 3 or lower_ equipment she is using.\n\n_+2:_ The Monk gains _80% more energy_ for each piece of _tier 2 or lower_ equipment she is using.\n\n_+3:_ The Monk gains _120% more energy_ for each piece of _tier 1_ equipment she is using. She also gains a free cloth armor and studded gloves.\n\nNote that this talent gives no benefit from being unarmed or attacking with a Ring of Force.
actors.hero.talent.unencumbered_spirit.desc=_+1:_ The Monk gains _50% more energy_ for each piece of _tier 3 or lower_ equipment she is using.\n\n_+2:_ This talent's effect is increased to _75% more energy_ for each piece of _tier 2 or lower_ equipment the Monk is using.\n\n_+3:_ This talent's effect is increased to _100% more energy_ for each piece of _tier 1_ equipment the Monk is using. She also gains a free cloth armor and studded gloves.\n\nNote that this talent gives no benefit from being unarmed or attacking with a Ring of Force.
actors.hero.talent.monastic_vigor.title=monastic vigor
actors.hero.talent.monastic_vigor.desc=_+1:_ If the Monk has _100% energy_, her abilities are empowered.\n\n_+2:_ If the Monk has _80% or more energy_, her abilities are empowered.\n\n_+3:_ If the Monk has _60% or more energy_, her abilities are empowered.\n\nWhen empowered:\n- Flurry applies your weapon's enchantment\n- Focus is instantaneous\n- Dash gains +3 range\n- Dragon Kick deals +50% damage and applies its knock back and stun effect to all adjacent enemies\n- Meditate slowly heals 20% of missing HP and grants 80% damage resistance.
actors.hero.talent.monastic_vigor.desc=_+1:_ If the Monk has _100% energy_, her abilities are empowered.\n\n_+2:_ If the Monk has _80% or more energy_, her abilities are empowered.\n\n_+3:_ If the Monk has _60% or more energy_, her abilities are empowered.\n\nWhen empowered:\n- Flurry applies your weapon's enchantment\n- Focus is instantaneous\n- Dash gains +4 range\n- Dragon Kick deals +50% damage and applies its knock back and stun effect to all adjacent enemies\n- Meditate slowly heals 20% of missing HP and grants 80% damage resistance.
actors.hero.talent.combined_energy.title=combined energy
actors.hero.talent.combined_energy.desc=_+1:_ If the Monk uses a weapon ability and a _4+ energy_ ability successively, she regains 50% of her spent energy and resets her ability cooldown.\n\n_+2:_ If the Monk uses a weapon ability and a _3+ energy_ ability successively, she regains 50% of her spent energy and resets her ability cooldown.\n\n_+3:_ If the Monk uses a weapon ability and a _2+ energy_ ability successively, she regains 50% of her spent energy and resets her ability cooldown.
actors.hero.talent.combined_energy.desc=_+1:_ If the Monk uses a weapon ability and a _4+ energy_ ability within 5 turns of each other, she regains 1 spent energy.\n\n_+2:_ If the Monk uses a weapon ability and a _3+ energy_ ability within 5 turns of each other, she regains 1 spent energy.\n\n_+3:_ If the Monk uses a weapon ability and a _2+ energy_ ability within 5 turns of each other, she regains 1 spent energy.
actors.hero.talent.close_the_gap.title=close the gap
actors.hero.talent.close_the_gap.desc=_+1:_ The Duelist blinks _up to two tiles_ toward her target when starting a duel.\n\n_+2:_ The Duelist blinks _up to three tiles_ toward her target when starting a duel.\n\n_+3:_ The Duelist blinks _up to four tiles_ toward her target when starting a duel.\n\n_+4:_ The Duelist blinks _up to five tiles_ toward her target when starting a duel.\n\nThis blink can go through hazards and enemies, but not solid terrain like walls. The blink is taken into account when determining if an enemy is in range to be challenged.

View File

@@ -371,9 +371,6 @@ public abstract class Char extends Actor {
if (h.buff(MonkEnergy.MonkAbility.UnarmedAbilityTracker.class) != null){
dr = 0;
} else if (h.subClass == HeroSubClass.MONK) {
//3 turns with standard attack delay
Buff.prolong(h, MonkEnergy.MonkAbility.JustHitTracker.class, 4f);
}
}
@@ -557,10 +554,8 @@ public abstract class Char extends Actor {
acuStat = INFINITE_ACCURACY;
}
if (defender.buff(MonkEnergy.MonkAbility.Focus.FocusBuff.class) != null && !magic){
if (defender.buff(MonkEnergy.MonkAbility.Focus.FocusBuff.class) != null){
defStat = INFINITE_EVASION;
defender.buff(MonkEnergy.MonkAbility.Focus.FocusBuff.class).detach();
Buff.affect(defender, MonkEnergy.MonkAbility.Focus.FocusActivation.class, 0);
}
//if accuracy or evasion are large enough, treat them as infinite.

View File

@@ -65,7 +65,7 @@ public class MonkEnergy extends Buff implements ActionIndicator.Action {
}
public float energy;
public int cooldown;
public int cooldown; //currently unused, abilities had cooldowns prior to v2.5
private static final float MAX_COOLDOWN = 5;
@@ -167,11 +167,11 @@ public class MonkEnergy extends Buff implements ActionIndicator.Action {
if (hero.belongings.armor() != null){
if (hero.belongings.armor().tier <= 1 && points >= 3){
enGainMulti += 1.20f;
enGainMulti += 1.00f;
} else if (hero.belongings.armor().tier <= 2 && points >= 2){
enGainMulti += 0.80f;
enGainMulti += 0.75f;
} else if (hero.belongings.armor().tier <= 3 && points >= 1){
enGainMulti += 0.40f;
enGainMulti += 0.50f;
}
}
@@ -179,11 +179,11 @@ public class MonkEnergy extends Buff implements ActionIndicator.Action {
&& (hero.buff(RingOfForce.BrawlersStance.class) == null
|| !hero.buff(RingOfForce.BrawlersStance.class).active)){
if (((MeleeWeapon) hero.belongings.weapon()).tier <= 1 && points >= 3){
enGainMulti += 1.20f;
enGainMulti += 1.00f;
} else if (((MeleeWeapon) hero.belongings.weapon()).tier <= 2 && points >= 2){
enGainMulti += 0.80f;
enGainMulti += 0.75f;
} else if (((MeleeWeapon) hero.belongings.weapon()).tier <= 3 && points >= 1){
enGainMulti += 0.40f;
enGainMulti += 0.50f;
}
}
@@ -206,15 +206,14 @@ public class MonkEnergy extends Buff implements ActionIndicator.Action {
public void abilityUsed( MonkAbility abil ){
energy -= abil.energyCost();
cooldown = abil.cooldown() + (int)target.cooldown();
if (target instanceof Hero && ((Hero) target).hasTalent(Talent.COMBINED_ENERGY)
&& abil.energyCost() >= 5-((Hero) target).pointsInTalent(Talent.COMBINED_ENERGY)) {
Talent.CombinedEnergyAbilityTracker tracker = target.buff(Talent.CombinedEnergyAbilityTracker.class);
if (tracker == null || tracker.wepAbilUsed == false){
Buff.prolong(target, Talent.CombinedEnergyAbilityTracker.class, target.cooldown()).energySpent = abil.energyCost();
if (tracker == null || !tracker.wepAbilUsed){
Buff.prolong(target, Talent.CombinedEnergyAbilityTracker.class, 5f).monkAbilused = true;
} else {
tracker.energySpent = abil.energyCost();
tracker.monkAbilused = true;
processCombinedEnergy(tracker);
}
}
@@ -233,8 +232,7 @@ public class MonkEnergy extends Buff implements ActionIndicator.Action {
}
public void processCombinedEnergy(Talent.CombinedEnergyAbilityTracker tracker){
energy = Math.min(energy+tracker.energySpent/2f, energyCap());
cooldown = 0;
energy = Math.min(energy+1, energyCap());
tracker.detach();
if (energy >= 1){
ActionIndicator.setAction(this);
@@ -298,7 +296,10 @@ public class MonkEnergy extends Buff implements ActionIndicator.Action {
}
public abstract int energyCost();
public abstract int cooldown();
public boolean usable(MonkEnergy buff){
return buff.energy >= energyCost();
}
public String targetingPrompt(){
return null; //return a string if uses targeting
@@ -307,10 +308,11 @@ public class MonkEnergy extends Buff implements ActionIndicator.Action {
public abstract void doAbility(Hero hero, Integer target );
public static class UnarmedAbilityTracker extends FlavourBuff{};
public static class JustHitTracker extends FlavourBuff{};
public static class FlurryEmpowerTracker extends FlavourBuff{};
public static class FlurryCooldownTracker extends FlavourBuff{};
public static class Flurry extends MonkAbility {
@Override
@@ -319,18 +321,18 @@ public class MonkEnergy extends Buff implements ActionIndicator.Action {
}
@Override
public int cooldown() {
return Dungeon.hero.buff(JustHitTracker.class) != null ? 0 : 5;
public boolean usable(MonkEnergy buff) {
return super.usable(buff) && buff.target.buff(FlurryCooldownTracker.class) == null;
}
@Override
public String desc() {
if (Buff.affect(Dungeon.hero, MonkEnergy.class).abilitiesEmpowered(Dungeon.hero)){
//hero unarmed damage
return Messages.get(this, "empower_desc", 1, Dungeon.hero.STR()-8);
//1.5x hero unarmed damage (rounds the result)
return Messages.get(this, "empower_desc", 2, Math.round(1.5f*(Dungeon.hero.STR()-8)));
} else {
//hero unarmed damage
return Messages.get(this, "desc", 1, Dungeon.hero.STR()-8);
//1.5x hero unarmed damage (rounds the result)
return Messages.get(this, "desc", 2, Math.round(1.5f*(Dungeon.hero.STR()-8)));
}
}
@@ -370,23 +372,21 @@ public class MonkEnergy extends Buff implements ActionIndicator.Action {
@Override
public void call() {
AttackIndicator.target(enemy);
hero.attack(enemy, 1, 0, Char.INFINITE_ACCURACY);
hero.attack(enemy, 1.5f, 0, Char.INFINITE_ACCURACY);
if (enemy.isAlive()){
hero.sprite.attack(enemy.pos, new Callback() {
@Override
public void call() {
hero.attack(enemy, 1, 0, Char.INFINITE_ACCURACY);
hero.attack(enemy, 1.5f, 0, Char.INFINITE_ACCURACY);
Invisibility.dispel();
hero.next();
tracker.detach();
Buff.affect(hero, MonkEnergy.class).abilityUsed(Flurry.this);
if (hero.buff(JustHitTracker.class) != null) {
hero.buff(JustHitTracker.class).detach();
}
if (hero.buff(FlurryEmpowerTracker.class) != null){
hero.buff(FlurryEmpowerTracker.class).detach();
}
Buff.affect(hero, FlurryCooldownTracker.class, 0f);
}
});
} else {
@@ -394,12 +394,10 @@ public class MonkEnergy extends Buff implements ActionIndicator.Action {
hero.next();
tracker.detach();
Buff.affect(hero, MonkEnergy.class).abilityUsed(Flurry.this);
if (hero.buff(JustHitTracker.class) != null) {
hero.buff(JustHitTracker.class).detach();
}
if (hero.buff(FlurryEmpowerTracker.class) != null){
hero.buff(FlurryEmpowerTracker.class).detach();
}
Buff.affect(hero, FlurryCooldownTracker.class, 0f);
}
}
});
@@ -413,14 +411,9 @@ public class MonkEnergy extends Buff implements ActionIndicator.Action {
return 2;
}
@Override
public int cooldown() {
return 5;
}
@Override
public void doAbility(Hero hero, Integer target) {
Buff.prolong(hero, FocusBuff.class, 30f);
Buff.affect(hero, FocusBuff.class);
if (Buff.affect(hero, MonkEnergy.class).abilitiesEmpowered(hero)){
hero.next();
@@ -430,7 +423,7 @@ public class MonkEnergy extends Buff implements ActionIndicator.Action {
Buff.affect(hero, MonkEnergy.class).abilityUsed(this);
}
public static class FocusBuff extends FlavourBuff {
public static class FocusBuff extends Buff {
{
type = buffType.POSITIVE;
@@ -447,20 +440,6 @@ public class MonkEnergy extends Buff implements ActionIndicator.Action {
icon.hardlight(0.25f, 1.5f, 1f);
}
@Override
public float iconFadePercent() {
return Math.max(0, (30 - visualcooldown()) / 30);
}
}
//tracks just the activation of focus, needed as magical attacks do not trigger it
// but may be dodged normally
public static class FocusActivation extends FlavourBuff {
{
actPriority = VFX_PRIO;
}
}
}
@@ -472,11 +451,6 @@ public class MonkEnergy extends Buff implements ActionIndicator.Action {
return 3;
}
@Override
public int cooldown() {
return 5;
}
@Override
public String targetingPrompt() {
return Messages.get(this, "prompt");
@@ -488,9 +462,9 @@ public class MonkEnergy extends Buff implements ActionIndicator.Action {
return;
}
int range = 3;
int range = 4;
if (Buff.affect(hero, MonkEnergy.class).abilitiesEmpowered(hero)){
range += 3;
range += 4;
}
if (Dungeon.hero.rooted){
@@ -543,19 +517,14 @@ public class MonkEnergy extends Buff implements ActionIndicator.Action {
return 4;
}
@Override
public int cooldown() {
return 5;
}
@Override
public String desc() {
if (Buff.affect(Dungeon.hero, MonkEnergy.class).abilitiesEmpowered(Dungeon.hero)){
//4.5x hero unarmed damage (rounds the result)
return Messages.get(this, "empower_desc", 5, Math.round(4.5f*(Dungeon.hero.STR()-8)));
//9x hero unarmed damage
return Messages.get(this, "empower_desc", 9, 9*(Dungeon.hero.STR()-8));
} else {
//3x hero unarmed damage
return Messages.get(this, "desc", 3, 3*(Dungeon.hero.STR()-8));
//6x hero unarmed damage
return Messages.get(this, "desc", 6, 6*(Dungeon.hero.STR()-8));
}
}
@@ -590,7 +559,7 @@ public class MonkEnergy extends Buff implements ActionIndicator.Action {
boolean empowered = Buff.affect(hero, MonkEnergy.class).abilitiesEmpowered(hero);
int oldPos = enemy.pos;
if (hero.attack(enemy, empowered ? 4.5f : 3f, 0, Char.INFINITE_ACCURACY)){
if (hero.attack(enemy, empowered ? 9f : 6f, 0, Char.INFINITE_ACCURACY)){
Sample.INSTANCE.play(Assets.Sounds.HIT_STRONG);
}
@@ -641,11 +610,6 @@ public class MonkEnergy extends Buff implements ActionIndicator.Action {
return 5;
}
@Override
public int cooldown() {
return 5;
}
@Override
public void doAbility(Hero hero, Integer target) {

View File

@@ -552,8 +552,8 @@ public class Hero extends Char {
return Messages.get(RoundShield.GuardTracker.class, "guarded");
}
if (buff(MonkEnergy.MonkAbility.Focus.FocusActivation.class) != null){
buff(MonkEnergy.MonkAbility.Focus.FocusActivation.class).detach();
if (buff(MonkEnergy.MonkAbility.Focus.FocusBuff.class) != null){
buff(MonkEnergy.MonkAbility.Focus.FocusBuff.class).detach();
if (sprite != null && sprite.visible) {
Sample.INSTANCE.play(Assets.Sounds.HIT_PARRY, 1, Random.Float(0.96f, 1.05f));
}

View File

@@ -367,8 +367,23 @@ public enum Talent {
public float iconFadePercent() { return Math.max(0, 1f - (visualcooldown() / 5)); }
};
public static class CombinedEnergyAbilityTracker extends FlavourBuff{
public int energySpent = -1;
public boolean monkAbilused = false;
public boolean wepAbilUsed = false;
private static final String MONK_ABIL_USED = "monk_abil_used";
private static final String WEP_ABIL_USED = "wep_abil_used";
@Override
public void storeInBundle(Bundle bundle) {
super.storeInBundle(bundle);
bundle.put(MONK_ABIL_USED, monkAbilused);
bundle.put(WEP_ABIL_USED, wepAbilUsed);
}
@Override
public void restoreFromBundle(Bundle bundle) {
super.restoreFromBundle(bundle);
monkAbilused = bundle.getBoolean(MONK_ABIL_USED);
wepAbilUsed = bundle.getBoolean(WEP_ABIL_USED);
}
}
public static class CounterAbilityTacker extends FlavourBuff{};

View File

@@ -219,8 +219,8 @@ public class MeleeWeapon extends Weapon {
}
if (hero.hasTalent(Talent.COMBINED_ENERGY)){
Talent.CombinedEnergyAbilityTracker tracker = hero.buff(Talent.CombinedEnergyAbilityTracker.class);
if (tracker == null || tracker.energySpent == -1){
Buff.prolong(hero, Talent.CombinedEnergyAbilityTracker.class, hero.cooldown()).wepAbilUsed = true;
if (tracker == null || !tracker.monkAbilused){
Buff.prolong(hero, Talent.CombinedEnergyAbilityTracker.class, 5f).wepAbilUsed = true;
} else {
tracker.wepAbilUsed = true;
Buff.affect(hero, MonkEnergy.class).processCombinedEnergy(tracker);

View File

@@ -71,7 +71,7 @@ public class WndMonkAbilities extends Window {
moveBtn.multiline = true;
moveBtn.setSize(width, moveBtn.reqHeight());
moveBtn.setRect(0, pos, width, moveBtn.reqHeight());
moveBtn.enable(energyBuff.energy >= abil.energyCost());
moveBtn.enable(abil.usable(energyBuff));
add(moveBtn);
pos = moveBtn.bottom() + MARGIN;
}