v2.0.0: implemented a window and basic functionality for monk abilities

This commit is contained in:
Evan Debenham
2023-02-24 15:52:35 -05:00
parent 442982ea50
commit c8c433cc6e
4 changed files with 269 additions and 13 deletions

View File

@@ -273,6 +273,16 @@ actors.buffs.momentum.resting_desc=As he moves, the Freerunner builds momentum,
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 X-Y damage and ignores armor. This ability has no cooldown if the Monk just attacked normally or with a weapon ability.
actors.buffs.monkenergy$monkability$dash.name=dash
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$focus.name=focus
actors.buffs.monkenergy$monkability$focus.desc=The monk takes a turn to focus, letting them dodge the next physical attack made against them within 20 turns.
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$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.ooze.name=caustic ooze
actors.buffs.ooze.heromsg=Caustic ooze eats your flesh. Wash it away!

View File

@@ -163,6 +163,9 @@ windows.wndkeybindings$wndchangebinding.cant_unbind=You must have at least one k
windows.wndkeybindings$wndchangebinding.confirm=Confirm
windows.wndkeybindings$wndchangebinding.cancel=Cancel
windows.wndmonkabilities.title=choose an ability
windows.wndmonkabilities.energycost=(%d energy)
windows.wndquickbag.title=quick-use an item
windows.wndranking.error=Unable to load additional information

View File

@@ -21,20 +21,28 @@
package com.shatteredpixel.shatteredpixeldungeon.actors.buffs;
import com.shatteredpixel.shatteredpixeldungeon.Assets;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
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.RipperDemon;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Wraith;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.YogDzewa;
import com.shatteredpixel.shatteredpixeldungeon.levels.Terrain;
import com.shatteredpixel.shatteredpixeldungeon.levels.features.Door;
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
import com.shatteredpixel.shatteredpixeldungeon.ui.ActionIndicator;
import com.shatteredpixel.shatteredpixeldungeon.ui.BuffIndicator;
import com.shatteredpixel.shatteredpixeldungeon.ui.HeroIcon;
import com.shatteredpixel.shatteredpixeldungeon.windows.WndMonkAbilities;
import com.watabou.noosa.Image;
import com.watabou.noosa.audio.Sample;
import com.watabou.utils.Bundle;
import com.watabou.utils.Callback;
public class MonkEnergy extends Buff implements ActionIndicator.Action {
@@ -152,20 +160,157 @@ public class MonkEnergy extends Buff implements ActionIndicator.Action {
@Override
public void doAction() {
energy -= 1;
cooldown = 3;
ActionIndicator.clearAction(this);
BuffIndicator.refreshHero();
//GameScene.show(new WndMonk(this));
GameScene.show(new WndMonkAbilities(this));
}
public enum MonkAbility {
FLURRY_OF_BLOWS, //1
CLEANSE, //Just part of meditate?
DASH, //2 or 3 energy?
UPPERCUT, //2
FOCUS, //3
DRAGON_KICK, //5
MEDITATE //5
public static abstract class MonkAbility {
public static MonkAbility[] abilities = new MonkAbility[]{
new Flurry(),
new Dash(),
new Focus(),
new DragonKick(),
new Meditate()
};
public String name(){
return Messages.get(this, "name");
}
public String desc(){
return Messages.get(this, "desc");
}
public abstract int energyCost();
public abstract int cooldown();
public String targetingPrompt(){
return null; //return a string if uses targeting
}
public abstract void doAbility(Hero hero, Integer target );
public static class Flurry extends MonkAbility {
@Override
public int energyCost() {
return 1;
}
@Override
public int cooldown() {
return 3;
}
@Override
public String targetingPrompt() {
return "choose a location";
}
@Override
public void doAbility(Hero hero, Integer target) {
//TODO
}
}
public static class Dash extends MonkAbility {
@Override
public int energyCost() {
return 2;
}
@Override
public int cooldown() {
return 3; //extra turn as no time is spend dashing
}
@Override
public String targetingPrompt() {
return "choose a location";
}
@Override
public void doAbility(Hero hero, Integer target) {
if (target == null || target == -1){
return;
}
//TODO check conditions
hero.busy();
Sample.INSTANCE.play(Assets.Sounds.MISS);
hero.sprite.jump(hero.pos, target, 0, 0.1f, new Callback() {
@Override
public void call() {
if (Dungeon.level.map[hero.pos] == Terrain.OPEN_DOOR) {
Door.leave( hero.pos );
}
hero.pos = target;
Dungeon.level.occupyCell(hero);
hero.next();
}
});
//TODO decrement energy
}
}
public static class Focus extends MonkAbility {
@Override
public int energyCost() {
return 3;
}
@Override
public int cooldown() {
return 3;
}
@Override
public void doAbility(Hero hero, Integer target) {
//TODO
}
}
public static class DragonKick extends MonkAbility {
@Override
public int energyCost() {
return 4;
}
@Override
public int cooldown() {
return 3;
}
@Override
public void doAbility(Hero hero, Integer target) {
//TODO
}
}
public static class Meditate extends MonkAbility {
@Override
public int energyCost() {
return 5;
}
@Override
public int cooldown() {
return 3;
}
@Override
public void doAbility(Hero hero, Integer target) {
//TODO
}
}
}
}

View File

@@ -0,0 +1,98 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2015 Oleg Dolya
*
* Shattered Pixel Dungeon
* Copyright (C) 2014-2023 Evan Debenham
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.windows;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.MonkEnergy;
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
import com.shatteredpixel.shatteredpixeldungeon.scenes.CellSelector;
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
import com.shatteredpixel.shatteredpixeldungeon.scenes.PixelScene;
import com.shatteredpixel.shatteredpixeldungeon.ui.RedButton;
import com.shatteredpixel.shatteredpixeldungeon.ui.RenderedTextBlock;
import com.shatteredpixel.shatteredpixeldungeon.ui.Window;
public class WndMonkAbilities extends Window {
private static final int WIDTH_P = 120;
private static final int WIDTH_L = 160;
private static final int MARGIN = 2;
public WndMonkAbilities( MonkEnergy energyBuff ){
super();
int width = PixelScene.landscape() ? WIDTH_L : WIDTH_P;
float pos = MARGIN;
RenderedTextBlock title = PixelScene.renderTextBlock(Messages.titleCase(Messages.get(this, "title")), 9);
title.hardlight(TITLE_COLOR);
title.setPos((width-title.width())/2, pos);
title.maxWidth(width - MARGIN * 2);
add(title);
pos = title.bottom() + 3*MARGIN;
for (MonkEnergy.MonkAbility abil : MonkEnergy.MonkAbility.abilities) {
String text = "_" + Messages.titleCase(abil.name()) + " " + Messages.get(this, "energycost", abil.energyCost()) + ":_ " + abil.desc();
RedButton moveBtn = new RedButton(text, 6){
@Override
protected void onClick() {
super.onClick();
hide();
if (abil.targetingPrompt() != null) {
abilityBeingUsed = abil;
GameScene.selectCell(listener);
} else {
abil.doAbility(Dungeon.hero, null);
}
}
};
moveBtn.leftJustify = true;
moveBtn.multiline = true;
moveBtn.setSize(width, moveBtn.reqHeight());
moveBtn.setRect(0, pos, width, moveBtn.reqHeight());
moveBtn.enable(energyBuff.energy >= abil.energyCost());
add(moveBtn);
pos = moveBtn.bottom() + MARGIN;
}
resize(width, (int)pos);
}
MonkEnergy.MonkAbility abilityBeingUsed;
private CellSelector.Listener listener = new CellSelector.Listener() {
@Override
public void onSelect(Integer cell) {
abilityBeingUsed.doAbility(Dungeon.hero, cell);
}
@Override
public String prompt() {
return abilityBeingUsed.targetingPrompt();
}
};
}