v0.9.2: implemented a new window where combo moves can be selected

This commit is contained in:
Evan Debenham 2021-02-03 18:55:23 -05:00
parent 4e95d6e238
commit a8967b6ece
5 changed files with 160 additions and 55 deletions

View File

@ -121,17 +121,13 @@ actors.buffs.chill.desc=Not quite frozen, but still much too cold.\n\nChilled ta
actors.buffs.combo.name=Combo
actors.buffs.combo.combo=%d hit combo!
actors.buffs.combo.bad_target=You must target an enemy in attack range.
actors.buffs.combo.clobber_prompt=Select a target to Clobber\nDazes and knocks back
actors.buffs.combo.clobber_desc=_Clobber_ is currently available. This attack _knocks an enemy back and dazes them,_ but deals reduced damage. It's excellent for buying a little time during a fight.
actors.buffs.combo.cleave_prompt=Select a target to Cleave\nIf it kills, preserves combo
actors.buffs.combo.cleave_desc=_Cleave_ is currently available. This attack deals increased damage, and _if it kills an enemy, it will preserve combo instead of resetting it._ It's great for building combo when fighting multiple enemies.
actors.buffs.combo.slam_prompt=Select a target to Slam\nShields and damages based on armor
actors.buffs.combo.slam_desc=_Slam_ is currently available. This attack deals _increased damage and shields you based on the blocking power of your armor._ It's great for finishing a fight, letting you carry over endurance to the next one.
actors.buffs.combo.crush_prompt=Select a target to Crush\nDeals lots of damage
actors.buffs.combo.crush_desc=_Crush_ is currently available. This devastating attack _deals massive damage very consistently._ It's great for taking down a powerful opponent from high health!
actors.buffs.combo.fury_prompt=Unload fury on which enemy?\nAttacks many times rapidly
actors.buffs.combo.fury_desc=_Fury_ is currently available. This devastating attack _hits as many times as your current combo count,_ albeit at reduced damage. Fury is great if you have a weapon enchant, as the enchant will activate on each hit!
actors.buffs.combo.desc=The gladiator builds momentum as they land successful blows. Each attack increases the combo counter by one, but taking too long between hits will reset the combo counter to 0.\n\nBuilding combo unlocks special finisher abilities: powerful attacks that cannot miss! A different finisher is available at 2, 4, 6, 8, and 10 combo count, and using a finisher will reset your combo.
actors.buffs.combo.prompt=Select a target to attack.
actors.buffs.combo.desc=The gladiator builds momentum as they land successful blows. Each attack increases the combo counter by one, but taking too long between hits will reset the combo counter to 0.\n\nBuilding combo unlocks special combo attacks that cannot miss! A different attack is unlocked at 2, 4, 6, 8, and 10 combo count.
actors.buffs.combo$combomove.clobber_desc=_Clobber_ knocks an enemy back 2 tiles, but not into a pit. Requires 2 combo, increments combo by 1, 1 use per combo.
actors.buffs.combo$combomove.cleave_desc=_Clobber_ knocks an enemy back 2 tiles, but not into a pit. Requires 2 combo, increments combo by 1, 1 use per combo.
actors.buffs.combo$combomove.slam_desc=_Clobber_ knocks an enemy back 2 tiles, but not into a pit. Requires 2 combo, increments combo by 1, 1 use per combo.
actors.buffs.combo$combomove.crush_desc=_Clobber_ knocks an enemy back 2 tiles, but not into a pit. Requires 2 combo, increments combo by 1, 1 use per combo.
actors.buffs.combo$combomove.fury_desc=_Clobber_ knocks an enemy back 2 tiles, but not into a pit. Requires 2 combo, increments combo by 1, 1 use per combo.
actors.buffs.corruption.name=Corrupted
actors.buffs.corruption.desc=Corruption seeps into the essence of a being, twisting them against their former nature.\n\nCorrupted creatures will attack their allies, and ignore their former enemies. Corruption is damaging as well, and will slowly cause its target to succumb.\n\nCorruption is permanent, its effects only end in death.

View File

@ -9,6 +9,8 @@ windows.wndchooseway.cancel=I'll decide later
windows.wndclass.mastery=Mastery
windows.wndcombo.title=choose a combo move
windows.wnddocument.missing=page missing
windows.wnderror.title=ERROR

View File

@ -42,6 +42,7 @@ import com.shatteredpixel.shatteredpixeldungeon.ui.ActionIndicator;
import com.shatteredpixel.shatteredpixeldungeon.ui.AttackIndicator;
import com.shatteredpixel.shatteredpixeldungeon.ui.BuffIndicator;
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
import com.shatteredpixel.shatteredpixeldungeon.windows.WndCombo;
import com.watabou.noosa.Image;
import com.watabou.noosa.audio.Sample;
import com.watabou.utils.Bundle;
@ -60,12 +61,12 @@ public class Combo extends Buff implements ActionIndicator.Action {
@Override
public void tintIcon(Image icon) {
if (count >= 10) icon.hardlight(1f, 0f, 0f);
else if (count >= 8)icon.hardlight(1f, 0.8f, 0f);
else if (count >= 6)icon.hardlight(1f, 1f, 0f);
else if (count >= 4)icon.hardlight(0.8f, 1f, 0f);
else if (count >= 2)icon.hardlight(0f, 1f, 0f);
else icon.resetColor();
ComboMove move = getHighestMove();
if (move != null){
icon.hardlight(move.tintColor & 0x00FFFFFF);
} else {
icon.resetColor();
}
}
@Override
@ -83,11 +84,12 @@ public class Combo extends Buff implements ActionIndicator.Action {
count++;
comboTime = 5f;
//TODO this won't count a kill on an enemy that gets corruped by corrupting I think?
if (!enemy.isAlive() || enemy.buff(Corruption.class) != null){
comboTime = Math.max(comboTime, 10*((Hero)target).pointsInTalent(Talent.CLEAVE));
}
if (count >= 2) {
if ((getHighestMove() != null)) {
ActionIndicator.setAction( this );
Badges.validateMasteryCombo( count );
@ -118,15 +120,7 @@ public class Combo extends Buff implements ActionIndicator.Action {
@Override
public String desc() {
String desc = Messages.get(this, "desc");
if (count >= 10) desc += "\n\n" + Messages.get(this, "fury_desc");
else if (count >= 8)desc += "\n\n" + Messages.get(this, "crush_desc");
else if (count >= 6)desc += "\n\n" + Messages.get(this, "slam_desc");
else if (count >= 4)desc += "\n\n" + Messages.get(this, "cleave_desc");
else if (count >= 2)desc += "\n\n" + Messages.get(this, "clobber_desc");
return desc;
return Messages.get(this, "desc");
}
private static final String COUNT = "count";
@ -142,7 +136,7 @@ public class Combo extends Buff implements ActionIndicator.Action {
public void restoreFromBundle(Bundle bundle) {
super.restoreFromBundle(bundle);
count = bundle.getInt( COUNT );
if (count >= 2) ActionIndicator.setAction(this);
if (getHighestMove() != null) ActionIndicator.setAction(this);
comboTime = bundle.getFloat( TIME );
}
@ -155,28 +149,60 @@ public class Combo extends Buff implements ActionIndicator.Action {
icon = new ItemSprite(new Item(){ {image = ItemSpriteSheet.WEAPON_HOLDER; }});
}
if (count >= 10) icon.tint(0xFFFF0000);
else if (count >= 8)icon.tint(0xFFFFCC00);
else if (count >= 6)icon.tint(0xFFFFFF00);
else if (count >= 4)icon.tint(0xFFCCFF00);
else icon.tint(0xFF00FF00);
icon.tint(getHighestMove().tintColor);
return icon;
}
@Override
public void doAction() {
GameScene.selectCell(finisher);
GameScene.show(new WndCombo(this));
//GameScene.selectCell(finisher);
}
private enum finisherType{
//TODO rework these, as well as finisher mechanics in general
CLOBBER, CLEAVE, SLAM, CRUSH, FURY
public enum ComboMove {
//TODO rework these moves
CLOBBER(2, 0xFF00FF00),
CLEAVE(4, 0xFFCCFF00),
SLAM(6, 0xFFFFFF00),
CRUSH(8, 0xFFFFCC00),
FURY(10, 0xFFFF0000);
public int comboReq, tintColor;
ComboMove(int comboReq, int tintColor){
this.comboReq = comboReq;
this.tintColor = tintColor;
}
public String desc(){
return Messages.get(this, name()+"_desc");
}
}
private CellSelector.Listener finisher = new CellSelector.Listener() {
public ComboMove getHighestMove(){
ComboMove best = null;
for (ComboMove move : ComboMove.values()){
if (count >= move.comboReq){
best = move;
}
}
return best;
}
private finisherType type;
public boolean canUseMove(ComboMove move){
return move.comboReq <= count;
}
public void useMove(ComboMove move){
moveBeingUsed = move;
GameScene.selectCell(listener);
}
private static ComboMove moveBeingUsed;
private CellSelector.Listener listener = new CellSelector.Listener() {
@Override
public void onSelect(Integer cell) {
@ -191,11 +217,6 @@ public class Combo extends Buff implements ActionIndicator.Action {
target.sprite.attack(cell, new Callback() {
@Override
public void call() {
if (count >= 10) type = finisherType.FURY;
else if (count >= 8)type = finisherType.CRUSH;
else if (count >= 6)type = finisherType.SLAM;
else if (count >= 4)type = finisherType.CLEAVE;
else type = finisherType.CLOBBER;
doAttack(enemy);
}
});
@ -221,7 +242,7 @@ public class Combo extends Buff implements ActionIndicator.Action {
int dmg = target.damageRoll();
//variance in damage dealt
switch (type) {
switch (moveBeingUsed) {
case CLOBBER:
dmg = Math.round(dmg * 0.6f);
break;
@ -255,7 +276,7 @@ public class Combo extends Buff implements ActionIndicator.Action {
enemy.damage(dmg, target);
//special effects
switch (type) {
switch (moveBeingUsed) {
case CLOBBER:
if (enemy.isAlive()) {
//trace a ballistica to our target (which will also extend past them
@ -282,7 +303,7 @@ public class Combo extends Buff implements ActionIndicator.Action {
if (target.buff(FrostImbue.class) != null) target.buff(FrostImbue.class).proc(enemy);
target.hitSound(Random.Float(0.87f, 1.15f));
if (type != finisherType.FURY) Sample.INSTANCE.play(Assets.Sounds.HIT_STRONG);
if (moveBeingUsed != ComboMove.FURY) Sample.INSTANCE.play(Assets.Sounds.HIT_STRONG);
enemy.sprite.bloodBurstA(target.sprite.center(), dmg);
enemy.sprite.flash();
@ -295,7 +316,7 @@ public class Combo extends Buff implements ActionIndicator.Action {
Hero hero = (Hero)target;
//Post-attack behaviour
switch(type){
switch(moveBeingUsed){
case CLEAVE:
//combo isn't reset, but rather increments with a cleave kill, and grants more time.
//this includes corrupting kills (which is why we check alignment
@ -338,11 +359,7 @@ public class Combo extends Buff implements ActionIndicator.Action {
@Override
public String prompt() {
if (count >= 10) return Messages.get(Combo.class, "fury_prompt");
else if (count >= 8)return Messages.get(Combo.class, "crush_prompt");
else if (count >= 6)return Messages.get(Combo.class, "slam_prompt");
else if (count >= 4)return Messages.get(Combo.class, "cleave_prompt");
else return Messages.get(Combo.class, "clobber_prompt");
return Messages.get(Combo.class, "prompt");
}
};
}

View File

@ -65,8 +65,9 @@ public class StyledButton extends Button {
if (icon != null) componentWidth += icon.width() + 2;
if (text != null && !text.text().equals("")){
text.maxWidth( (int)(width - componentWidth - 2) );
componentWidth += text.width() + 2;
text.setPos(
x + (width() + componentWidth)/2f - text.width() - 1,
y + (height() - text.height()) / 2f

View File

@ -0,0 +1,89 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2015 Oleg Dolya
*
* Shattered Pixel Dungeon
* Copyright (C) 2014-2021 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.Combo;
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
import com.shatteredpixel.shatteredpixeldungeon.scenes.PixelScene;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSprite;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet;
import com.shatteredpixel.shatteredpixeldungeon.ui.RedButton;
import com.shatteredpixel.shatteredpixeldungeon.ui.RenderedTextBlock;
import com.shatteredpixel.shatteredpixeldungeon.ui.Window;
import com.watabou.noosa.Image;
public class WndCombo extends Window {
private static final int WIDTH_P = 120;
private static final int WIDTH_L = 144;
private static final int MARGIN = 2;
public WndCombo( Combo combo ){
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;
Image icon;
if (Dungeon.hero.belongings.weapon != null){
icon = new ItemSprite(Dungeon.hero.belongings.weapon.image, null);
} else {
icon = new ItemSprite(new Item(){ {image = ItemSpriteSheet.WEAPON_HOLDER; }});
}
for (Combo.ComboMove move : Combo.ComboMove.values()) {
Image ic = new Image(icon);
RedButton moveBtn = new RedButton(move.desc(), 6){
@Override
protected void onClick() {
super.onClick();
hide();
combo.useMove(move);
}
};
ic.tint(move.tintColor);
moveBtn.icon(ic);
moveBtn.setSize(width, moveBtn.reqHeight());
moveBtn.setRect(0, pos, width, moveBtn.reqHeight());
moveBtn.enable(combo.canUseMove(move));
add(moveBtn);
pos = moveBtn.bottom() + MARGIN;
}
resize(width, (int)pos);
}
}