v0.9.2: finished reworking combo

This commit is contained in:
Evan Debenham 2021-02-13 14:34:50 -05:00
parent 70e080ca6f
commit c1dd816a36
4 changed files with 218 additions and 161 deletions

View File

@ -122,12 +122,12 @@ 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.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 deals no damage and cannot knock into pits. Requires 2 combo, increments combo by 1, 1 use per combo.
actors.buffs.combo$combomove.slam_desc=_Slam_ deals 20% of your armor's blocking power as bonus damage for each combo you have. Requires 4 combo, resets combo when used.
actors.buffs.combo$combomove.parry_desc=_Parry_ ... . Requires 6 combo, resets combo if nothing is parried, 1 use per combo.
actors.buffs.combo$combomove.crush_desc=_???_ ... . Requires 8 combo, resets combo when used.
actors.buffs.combo$combomove.fury_desc=_???_ ... . Requires 10 combo, resets combo when used.
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. Some moves reset combo and some do not, but each move can only be used once per combo session.
actors.buffs.combo$combomove.clobber_desc=_2 Combo: Clobber_ knocks an enemy back 2 tiles, but deals no damage and cannot knock into pits. Increments combo by 1.
actors.buffs.combo$combomove.slam_desc=_4 Combo: Slam_ deals combo*20% of your armor's blocking power as bonus damage. Resets combo when used.
actors.buffs.combo$combomove.parry_desc=_6 Combo: Parry_ blocks the next attack within 1 turn when activated, and instantly retaliates to it. Resets combo if nothing is parried.
actors.buffs.combo$combomove.crush_desc=_8 Combo: Crush_ deals combo*25% of your melee damage to the primary target, and half that damage to all other enemies in a 7x7 AOE. Resets combo when used.
actors.buffs.combo$combomove.fury_desc=_10 Combo: Fury_ hits an enemy once for each combo you have, each hit deals 60% damage and can trigger enchantments. Resets combo when used.
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

@ -47,6 +47,7 @@ import com.watabou.noosa.Image;
import com.watabou.noosa.audio.Sample;
import com.watabou.utils.Bundle;
import com.watabou.utils.Callback;
import com.watabou.utils.PathFinder;
import com.watabou.utils.Random;
public class Combo extends Buff implements ActionIndicator.Action {
@ -167,15 +168,14 @@ public class Combo extends Buff implements ActionIndicator.Action {
@Override
public void doAction() {
GameScene.show(new WndCombo(this));
//GameScene.selectCell(finisher);
}
public enum ComboMove {
CLOBBER(2, 0xFF00FF00),
SLAM (4, 0xFFCCFF00),
PARRY (6, 0xFFFFFF00), //TODO implement
CRUSH (8, 0xFFFFCC00), //TODO rework
FURY (10, 0xFFFF0000); //TODO rework
PARRY (6, 0xFFFFFF00),
CRUSH (8, 0xFFFFCC00),
FURY (10, 0xFFFF0000); //TODO can currently input other actions while attacking with fury
public int comboReq, tintColor;
@ -211,42 +211,54 @@ public class Combo extends Buff implements ActionIndicator.Action {
public void useMove(ComboMove move){
if (move == ComboMove.PARRY){
//TODO
parryUsed = true;
Buff.affect(target, ParryTracker.class, Actor.TICK);
((Hero)target).spendAndNext(Actor.TICK);
} else {
moveBeingUsed = move;
GameScene.selectCell(listener);
}
}
private static ComboMove moveBeingUsed;
public static class ParryTracker extends FlavourBuff{
{ actPriority = HERO_PRIO+1;}
private CellSelector.Listener listener = new CellSelector.Listener() {
public boolean parried;
@Override
public void onSelect(Integer cell) {
if (cell == null) return;
final Char enemy = Actor.findChar( cell );
if (enemy == null
|| !Dungeon.level.heroFOV[cell]
|| !((Hero)target).canAttack(enemy)
|| target.isCharmedBy( enemy )){
GLog.w( Messages.get(Combo.class, "bad_target") );
} else {
target.sprite.attack(cell, new Callback() {
public void detach() {
if (!parried) target.buff(Combo.class).detach();
super.detach();
}
}
public static class RiposteTracker extends Buff{
{ actPriority = VFX_PRIO;}
public Char enemy;
@Override
public boolean act() {
moveBeingUsed = ComboMove.PARRY;
target.sprite.attack(enemy.pos, new Callback() {
@Override
public void call() {
doAttack(enemy);
target.buff(Combo.class).doAttack(enemy);
}
});
detach();
return true;
}
}
private static ComboMove moveBeingUsed;
private void doAttack(final Char enemy){
AttackIndicator.target(enemy);
boolean wasAlly = enemy.alignment == target.alignment;
Hero hero = (Hero)target;
if (enemy.defenseSkill(target) >= Char.INFINITE_EVASION){
enemy.sprite.showStatus( CharSprite.NEUTRAL, enemy.defenseVerb() );
@ -269,12 +281,7 @@ public class Combo extends Buff implements ActionIndicator.Action {
dmg += Math.round(target.drRoll() * count/5f);
break;
case CRUSH:
//rolls 4 times, takes the highest roll
for (int i = 1; i < 4; i++) {
int dmgReroll = target.damageRoll();
if (dmgReroll > dmg) dmg = dmgReroll;
}
dmg = Math.round(dmg * 2.5f);
dmg = Math.round(dmg * 0.25f*count);
break;
case FURY:
dmg = Math.round(dmg * 0.6f);
@ -294,6 +301,7 @@ public class Combo extends Buff implements ActionIndicator.Action {
//special effects
switch (moveBeingUsed) {
case CLOBBER:
hit( enemy );
if (enemy.isAlive()) {
//trace a ballistica to our target (which will also extend past them
Ballistica trajectory = new Ballistica(target.pos, enemy.pos, Ballistica.STOP_TARGET);
@ -305,13 +313,32 @@ public class Combo extends Buff implements ActionIndicator.Action {
dist--;
}
WandOfBlastWave.throwChar(enemy, trajectory, dist, true, false);
hit( enemy );
}
break;
case SLAM:
BrokenSeal.WarriorShield shield = Buff.affect(target, BrokenSeal.WarriorShield.class);
if (shield != null) {
shield.supercharge(dmg / 2);
case PARRY:
hit( enemy );
break;
case CRUSH:
WandOfBlastWave.BlastWave.blast(enemy.pos);
PathFinder.buildDistanceMap(target.pos, Dungeon.level.passable, 3);
for (Char ch : Actor.chars()){
if (ch != enemy && ch.alignment == Char.Alignment.ENEMY
&& PathFinder.distance[ch.pos] < Integer.MAX_VALUE){
int aoeHit = Math.round(target.damageRoll() * 0.25f*count);
aoeHit /= 2;
aoeHit -= ch.drRoll();
if (ch.buff(Vulnerable.class) != null) aoeHit *= 1.33f;
ch.damage(aoeHit, target);
ch.sprite.bloodBurstA(target.sprite.center(), dmg);
ch.sprite.flash();
if (!ch.isAlive()) {
if (hero.hasTalent(Talent.LETHAL_DEFENSE) && hero.buff(BrokenSeal.WarriorShield.class) != null){
BrokenSeal.WarriorShield shield = hero.buff(BrokenSeal.WarriorShield.class);
shield.supercharge(Math.round(shield.maxShield() * hero.pointsInTalent(Talent.LETHAL_DEFENSE)/3f));
}
}
}
}
break;
default:
@ -333,8 +360,6 @@ public class Combo extends Buff implements ActionIndicator.Action {
}
Hero hero = (Hero)target;
//Post-attack behaviour
switch(moveBeingUsed){
case CLOBBER:
@ -343,18 +368,9 @@ public class Combo extends Buff implements ActionIndicator.Action {
hero.spendAndNext(hero.attackDelay());
break;
/*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
if (!enemy.isAlive() || (!wasAlly && enemy.alignment == target.alignment)) {
hit( enemy );
comboTime = 12f;
} else {
detach();
ActionIndicator.clearAction(Combo.this);
}
hero.spendAndNext(hero.attackDelay());
break;*/
case PARRY:
hero.next();
break;
case FURY:
count--;
@ -390,6 +406,27 @@ public class Combo extends Buff implements ActionIndicator.Action {
}
private CellSelector.Listener listener = new CellSelector.Listener() {
@Override
public void onSelect(Integer cell) {
if (cell == null) return;
final Char enemy = Actor.findChar( cell );
if (enemy == null
|| !Dungeon.level.heroFOV[cell]
|| !((Hero)target).canAttack(enemy)
|| target.isCharmedBy( enemy )){
GLog.w( Messages.get(Combo.class, "bad_target") );
} else {
target.sprite.attack(cell, new Callback() {
@Override
public void call() {
doAttack(enemy);
}
});
}
}
@Override
public String prompt() {
return Messages.get(Combo.class, "prompt");

View File

@ -52,6 +52,7 @@ import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Regeneration;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.SnipersMark;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Vertigo;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Monk;
import com.shatteredpixel.shatteredpixeldungeon.effects.CellEmitter;
import com.shatteredpixel.shatteredpixeldungeon.effects.CheckedCell;
import com.shatteredpixel.shatteredpixeldungeon.effects.Flare;
@ -410,6 +411,13 @@ public class Hero extends Char {
@Override
public int defenseSkill( Char enemy ) {
if (buff(Combo.ParryTracker.class) != null){
if (canAttack(enemy)){
Buff.affect(this, Combo.RiposteTracker.class).enemy = enemy;
}
return INFINITE_EVASION;
}
float evasion = defenseSkill;
evasion *= RingOfEvasion.evasionMultiplier( this );
@ -425,6 +433,18 @@ public class Hero extends Char {
return Math.round(evasion);
}
@Override
public String defenseVerb() {
Combo.ParryTracker parry = buff(Combo.ParryTracker.class);
if (parry == null){
return super.defenseVerb();
} else {
parry.parried = true;
parry.detach();
return Messages.get(Monk.class, "parried");
}
}
@Override
public int drRoll() {
int dr = 0;

View File

@ -36,7 +36,7 @@ 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 WIDTH_L = 160;
private static final int MARGIN = 2;