v2.0.0: implemented the flurry of blows ability
This commit is contained in:
@@ -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!
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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<Item> {
|
||||
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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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));
|
||||
|
||||
Reference in New Issue
Block a user