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=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.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.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.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.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.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$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.name=dash
|
||||||
actors.buffs.monkenergy$monkability$dash.prompt=Choose a location
|
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.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$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$dragonkick.name=dragon kick
|
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.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.name=caustic ooze
|
||||||
actors.buffs.ooze.heromsg=Caustic ooze eats your flesh. Wash it away!
|
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)){
|
&& !Dungeon.level.adjacent(h.pos, enemy.pos)){
|
||||||
dr = 0;
|
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
|
//we use a float here briefly so that we don't have to constantly round while
|
||||||
|
|||||||
+50
-13
@@ -29,17 +29,18 @@ import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
|
|||||||
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.HeroSubClass;
|
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.HeroSubClass;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Ghoul;
|
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Ghoul;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob;
|
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.RipperDemon;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Wraith;
|
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Wraith;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.YogDzewa;
|
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.YogDzewa;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.effects.Speck;
|
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.Terrain;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.levels.features.Door;
|
import com.shatteredpixel.shatteredpixeldungeon.levels.features.Door;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.mechanics.Ballistica;
|
import com.shatteredpixel.shatteredpixeldungeon.mechanics.Ballistica;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
|
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
|
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.ui.ActionIndicator;
|
import com.shatteredpixel.shatteredpixeldungeon.ui.ActionIndicator;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.ui.AttackIndicator;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.ui.BuffIndicator;
|
import com.shatteredpixel.shatteredpixeldungeon.ui.BuffIndicator;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.ui.HeroIcon;
|
import com.shatteredpixel.shatteredpixeldungeon.ui.HeroIcon;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
|
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 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 {
|
public static class Flurry extends MonkAbility {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -213,19 +217,18 @@ public class MonkEnergy extends Buff implements ActionIndicator.Action {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int cooldown() {
|
public int cooldown() {
|
||||||
return 3;
|
return Dungeon.hero.buff(JustHitTracker.class) != null ? 0 : 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String desc() {
|
public String desc() {
|
||||||
//double hero unarmed damage
|
//hero unarmed damage
|
||||||
//TODO maybe two hits at regular unarmed damage instead?
|
return Messages.get(this, "desc", 1, Dungeon.hero.STR()-8);
|
||||||
return Messages.get(this, "desc", 2, 2*(Dungeon.hero.STR()-8));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String targetingPrompt() {
|
public String targetingPrompt() {
|
||||||
return "choose a target";
|
return Messages.get(MeleeWeapon.class, "prompt");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -234,15 +237,49 @@ public class MonkEnergy extends Buff implements ActionIndicator.Action {
|
|||||||
return;
|
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){
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -324,7 +361,7 @@ public class MonkEnergy extends Buff implements ActionIndicator.Action {
|
|||||||
if (!dash.collisionPos.equals(target)
|
if (!dash.collisionPos.equals(target)
|
||||||
|| Actor.findChar(target) != null
|
|| Actor.findChar(target) != null
|
||||||
|| (Dungeon.level.solid[target] && !Dungeon.level.passable[target])){
|
|| (Dungeon.level.solid[target] && !Dungeon.level.passable[target])){
|
||||||
GLog.w(Messages.get(this, "blocked"));
|
GLog.w(Messages.get(MeleeWeapon.class, "ability_bad_position"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
@@ -25,6 +25,7 @@ import com.shatteredpixel.shatteredpixeldungeon.Badges;
|
|||||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.GamesInProgress;
|
import com.shatteredpixel.shatteredpixeldungeon.GamesInProgress;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.LostInventory;
|
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.EquipableItem;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
|
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.items.KindOfWeapon;
|
import com.shatteredpixel.shatteredpixeldungeon.items.KindOfWeapon;
|
||||||
@@ -98,6 +99,7 @@ public class Belongings implements Iterable<Item> {
|
|||||||
public KindOfWeapon attackingWeapon(){
|
public KindOfWeapon attackingWeapon(){
|
||||||
if (thrownWeapon != null) return thrownWeapon;
|
if (thrownWeapon != null) return thrownWeapon;
|
||||||
if (abilityWeapon != null) return abilityWeapon;
|
if (abilityWeapon != null) return abilityWeapon;
|
||||||
|
if (owner.buff(MonkEnergy.MonkAbility.UnarmedAbilityTracker.class) != null) return null;
|
||||||
return weapon();
|
return weapon();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+3
-1
@@ -24,6 +24,7 @@ package com.shatteredpixel.shatteredpixeldungeon.items.rings;
|
|||||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
|
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
|
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.Hero;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.HeroClass;
|
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.HeroClass;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.MeleeWeapon;
|
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.MeleeWeapon;
|
||||||
@@ -77,7 +78,8 @@ public class RingOfForce extends Ring {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static int damageRoll( Hero hero ){
|
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);
|
int level = getBuffedBonus(hero, Force.class);
|
||||||
float tier = tier(hero.STR());
|
float tier = tier(hero.STR());
|
||||||
return Random.NormalIntRange(min(level, tier), max(level, tier));
|
return Random.NormalIntRange(min(level, tier), max(level, tier));
|
||||||
|
|||||||
Reference in New Issue
Block a user