diff --git a/core/src/main/assets/messages/actors/actors.properties b/core/src/main/assets/messages/actors/actors.properties index caf52ff94..27adb60a7 100644 --- a/core/src/main/assets/messages/actors/actors.properties +++ b/core/src/main/assets/messages/actors/actors.properties @@ -274,20 +274,18 @@ actors.buffs.monkenergy.name=energy 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=An instant strike that deals %1$d-%2$d damage and ignores armor. This ability has no cooldown if the Monk just attacked normally or with a weapon ability. +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$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$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 garunteed to parry the next incoming physical attack.\n\nTurns remaining: %s. actors.buffs.monkenergy$monkability$dash.name=dash -actors.buffs.monkenergy$monkability$dash.prompt=Choose a location -actors.buffs.monkenergy$monkability$dash.too_far=That location is too far away. -actors.buffs.monkenergy$monkability$dash.blocked=There is something blocking that location. -actors.buffs.monkenergy$monkability$dash.desc=An instant dash up to 2 tiles away. This ability can go over hazards, but not through enemies or walls. +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 walls. actors.buffs.monkenergy$monkability$dragonkick.name=dragon kick -actors.buffs.monkenergy$monkability$dragonkick.desc=A devastating kick that deals X-Y damage and ignores armor. The force of the kick is so strong that the target is knocked away and paralyzed for 10 turns. +actors.buffs.monkenergy$monkability$dragonkick.desc=A devastating kick that deals %1$d-%2$d damage and ignores armor. The kick also knocks the target away and paralyzes them for 5 turns. actors.buffs.monkenergy$monkability$meditate.name=meditate -actors.buffs.monkenergy$monkability$meditate.desc=The Monk focuses energy into her body for 5 turns. This clears most negative effects and restores charge to her magical items. +actors.buffs.monkenergy$monkability$meditate.desc=The Monk focuses energy into her body for 5 turns. This clears most negative effects and grants her 10 turns of wand and artifact recharging. actors.buffs.ooze.name=caustic ooze actors.buffs.ooze.heromsg=Caustic ooze eats your flesh. Wash it away! 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 d348bd826..ab6799d8f 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/Char.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/Char.java @@ -335,6 +335,13 @@ public abstract class Char extends Actor { && !Dungeon.level.adjacent(h.pos, enemy.pos)){ dr = 0; } + + 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); + } } //we use a float here briefly so that we don't have to constantly round while diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/buffs/MonkEnergy.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/buffs/MonkEnergy.java index 6bf873ba5..239ca2779 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/buffs/MonkEnergy.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/buffs/MonkEnergy.java @@ -29,17 +29,18 @@ import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero; import com.shatteredpixel.shatteredpixeldungeon.actors.hero.HeroSubClass; import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Ghoul; import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob; -import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Monk; import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.RipperDemon; import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Wraith; import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.YogDzewa; import com.shatteredpixel.shatteredpixeldungeon.effects.Speck; +import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.MeleeWeapon; import com.shatteredpixel.shatteredpixeldungeon.levels.Terrain; import com.shatteredpixel.shatteredpixeldungeon.levels.features.Door; import com.shatteredpixel.shatteredpixeldungeon.mechanics.Ballistica; import com.shatteredpixel.shatteredpixeldungeon.messages.Messages; import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene; import com.shatteredpixel.shatteredpixeldungeon.ui.ActionIndicator; +import com.shatteredpixel.shatteredpixeldungeon.ui.AttackIndicator; import com.shatteredpixel.shatteredpixeldungeon.ui.BuffIndicator; import com.shatteredpixel.shatteredpixeldungeon.ui.HeroIcon; import com.shatteredpixel.shatteredpixeldungeon.utils.GLog; @@ -204,6 +205,9 @@ 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 Flurry extends MonkAbility { @Override @@ -213,19 +217,18 @@ public class MonkEnergy extends Buff implements ActionIndicator.Action { @Override public int cooldown() { - return 3; + return Dungeon.hero.buff(JustHitTracker.class) != null ? 0 : 3; } @Override public String desc() { - //double hero unarmed damage - //TODO maybe two hits at regular unarmed damage instead? - return Messages.get(this, "desc", 2, 2*(Dungeon.hero.STR()-8)); + //hero unarmed damage + return Messages.get(this, "desc", 1, Dungeon.hero.STR()-8); } @Override public String targetingPrompt() { - return "choose a target"; + return Messages.get(MeleeWeapon.class, "prompt"); } @Override @@ -234,15 +237,49 @@ public class MonkEnergy extends Buff implements ActionIndicator.Action { return; } - //TODO check for target viability + Char enemy = Actor.findChar(target); + if (enemy == null || enemy == hero || hero.isCharmedBy(enemy) || !Dungeon.level.heroFOV[target]) { + GLog.w(Messages.get(MeleeWeapon.class, "ability_no_target")); + return; + } - //TODO add a buff that forces melee only (and no RoF!) + UnarmedAbilityTracker tracker = Buff.affect(hero, UnarmedAbilityTracker.class); + if (!hero.canAttack(enemy)){ + GLog.w(Messages.get(MeleeWeapon.class, "ability_bad_position")); + tracker.detach(); + return; + } - //check for can attack + hero.sprite.attack(enemy.pos, new Callback() { + @Override + public void call() { + AttackIndicator.target(enemy); + hero.attack(enemy, 1, 0, Char.INFINITE_ACCURACY); - //clear buff if can't + if (enemy.isAlive()){ + hero.sprite.attack(enemy.pos, new Callback() { + @Override + public void call() { + hero.attack(enemy, 1, 0, Char.INFINITE_ACCURACY); + Invisibility.dispel(); + tracker.detach(); - //do attack logic + Buff.affect(hero, MonkEnergy.class).abilityUsed(Flurry.this); + if (hero.buff(JustHitTracker.class) != null) { + hero.buff(JustHitTracker.class).detach(); + } + } + }); + } else { + Invisibility.dispel(); + tracker.detach(); + Buff.affect(hero, MonkEnergy.class).abilityUsed(Flurry.this); + if (hero.buff(JustHitTracker.class) != null) { + hero.buff(JustHitTracker.class).detach(); + } + } + } + }); } } @@ -315,7 +352,7 @@ public class MonkEnergy extends Buff implements ActionIndicator.Action { } if (Dungeon.level.distance(hero.pos, target) > 3){ - GLog.w(Messages.get(this, "too_far")); + GLog.w(Messages.get(MeleeWeapon.class, "ability_no_target")); return; } @@ -324,7 +361,7 @@ public class MonkEnergy extends Buff implements ActionIndicator.Action { if (!dash.collisionPos.equals(target) || Actor.findChar(target) != null || (Dungeon.level.solid[target] && !Dungeon.level.passable[target])){ - GLog.w(Messages.get(this, "blocked")); + GLog.w(Messages.get(MeleeWeapon.class, "ability_bad_position")); return; } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/Belongings.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/Belongings.java index 68c869a09..fa4a8fd87 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/Belongings.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/Belongings.java @@ -25,6 +25,7 @@ import com.shatteredpixel.shatteredpixeldungeon.Badges; import com.shatteredpixel.shatteredpixeldungeon.Dungeon; import com.shatteredpixel.shatteredpixeldungeon.GamesInProgress; import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.LostInventory; +import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.MonkEnergy; import com.shatteredpixel.shatteredpixeldungeon.items.EquipableItem; import com.shatteredpixel.shatteredpixeldungeon.items.Item; import com.shatteredpixel.shatteredpixeldungeon.items.KindOfWeapon; @@ -98,6 +99,7 @@ public class Belongings implements Iterable { public KindOfWeapon attackingWeapon(){ if (thrownWeapon != null) return thrownWeapon; if (abilityWeapon != null) return abilityWeapon; + if (owner.buff(MonkEnergy.MonkAbility.UnarmedAbilityTracker.class) != null) return null; return weapon(); } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/rings/RingOfForce.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/rings/RingOfForce.java index 3068f9b85..938bc52e5 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/rings/RingOfForce.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/rings/RingOfForce.java @@ -24,6 +24,7 @@ package com.shatteredpixel.shatteredpixeldungeon.items.rings; import com.shatteredpixel.shatteredpixeldungeon.Dungeon; import com.shatteredpixel.shatteredpixeldungeon.actors.Char; import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff; +import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.MonkEnergy; import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero; import com.shatteredpixel.shatteredpixeldungeon.actors.hero.HeroClass; import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.MeleeWeapon; @@ -77,7 +78,8 @@ public class RingOfForce extends Ring { } public static int damageRoll( Hero hero ){ - if (hero.buff(Force.class) != null) { + if (hero.buff(Force.class) != null + && hero.buff(MonkEnergy.MonkAbility.UnarmedAbilityTracker.class) == null) { int level = getBuffedBonus(hero, Force.class); float tier = tier(hero.STR()); return Random.NormalIntRange(min(level, tier), max(level, tier));