diff --git a/core/src/main/assets/interfaces/buffs.png b/core/src/main/assets/interfaces/buffs.png index 03e854791..6075db952 100644 Binary files a/core/src/main/assets/interfaces/buffs.png and b/core/src/main/assets/interfaces/buffs.png differ diff --git a/core/src/main/assets/interfaces/large_buffs.png b/core/src/main/assets/interfaces/large_buffs.png index 6a9533b71..c5a4091fc 100644 Binary files a/core/src/main/assets/interfaces/large_buffs.png and b/core/src/main/assets/interfaces/large_buffs.png differ diff --git a/core/src/main/assets/messages/items/items.properties b/core/src/main/assets/messages/items/items.properties index a1753556c..b06c9c178 100644 --- a/core/src/main/assets/messages/items/items.properties +++ b/core/src/main/assets/messages/items/items.properties @@ -1532,6 +1532,8 @@ items.weapon.melee.greatshield.stats_desc=This weapon blocks 0-%d damage. This b items.weapon.melee.greatshield.desc=More like a mobile wall than a shield, this gigantic mass of metal aids defense, but doesn't leave much room for attacking. items.weapon.melee.greatsword.name=greatsword +items.weapon.melee.greatsword.ability_name=cleave +items.weapon.melee.greatsword.ability_desc=The duelist can _cleave_ an enemy with a greatsword. This deals +20% damage and is guaranteed to hit. If cleave kills an enemy it is instantaneous and lets the duelist use cleave again within 5 turns for free. items.weapon.melee.greatsword.desc=This towering blade inflicts heavy damage by investing its heft into every swing. items.weapon.melee.handaxe.name=hand axe @@ -1543,6 +1545,8 @@ items.weapon.melee.knuckles.stats_desc=This is a very fast weapon. items.weapon.melee.knuckles.desc=A piece of iron shaped to fit around the knuckles. Keeps the hands free, yet allows for better attacks than an empty fist. items.weapon.melee.longsword.name=longsword +items.weapon.melee.longsword.ability_name=cleave +items.weapon.melee.longsword.ability_desc=The duelist can _cleave_ an enemy with a longsword. This deals +23% damage and is guaranteed to hit. If cleave kills an enemy it is instantaneous and lets the duelist use cleave again within 5 turns for free. items.weapon.melee.longsword.desc=This sword's long razor-sharp steel blade shines reassuringly, though its size does make it quite heavy. items.weapon.melee.mace.name=mace @@ -1581,6 +1585,8 @@ items.weapon.melee.meleeweapon.ability_bad_position=That target can't be reached items.weapon.melee.meleeweapon.prompt=Select a Target items.weapon.melee.shortsword.name=shortsword +items.weapon.melee.shortsword.ability_name=cleave +items.weapon.melee.shortsword.ability_desc=The duelist can _cleave_ an enemy with a shortsword. This deals +30% damage and is guaranteed to hit. If cleave kills an enemy it is instantaneous and lets the duelist use cleave again within 5 turns for free. items.weapon.melee.shortsword.desc=A quite short sword, only a few inches longer than a dagger. items.weapon.melee.quarterstaff.name=quarterstaff @@ -1619,7 +1625,11 @@ items.weapon.melee.spear.ability_desc=The duelist can use the tip of a spear to items.weapon.melee.spear.desc=A slender wooden rod tipped with sharpened iron. items.weapon.melee.sword.name=sword +items.weapon.melee.sword.ability_name=cleave +items.weapon.melee.sword.ability_desc=The duelist can _cleave_ an enemy with a sword. This deals +27% damage and is guaranteed to hit. If cleave kills an enemy it is instantaneous and lets the duelist use cleave again within 5 turns for free. items.weapon.melee.sword.desc=A nicely balanced sword. Not too large, but still notably longer than a shortsword. +items.weapon.melee.sword$cleavetracker.name=cleave +items.weapon.melee.sword$cleavetracker.desc=The duelist is ready to follow up on her previous cleave. The next use of cleave will not cost any weapon ability charge.\n\nTurns remaining: %s. items.weapon.melee.warhammer.name=war hammer items.weapon.melee.warhammer.stats_desc=This is a rather accurate weapon. @@ -1630,6 +1640,8 @@ items.weapon.melee.whip.stats_desc=This weapon has tremendous reach. items.weapon.melee.whip.desc=While the barbed length of rope at the end of this weapon deals poor damage, its reach cannot be matched. items.weapon.melee.wornshortsword.name=worn shortsword +items.weapon.melee.wornshortsword.ability_name=cleave +items.weapon.melee.wornshortsword.ability_desc=The duelist can _cleave_ an enemy with a worn shortsword. This deals +33% damage and is guaranteed to hit. If cleave kills an enemy it is instantaneous and lets the duelist use cleave again within 5 turns for free. items.weapon.melee.wornshortsword.desc=A quite short sword, worn down through heavy use. It is both weaker and a bit lighter than a shortsword in better condition. diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/weapon/melee/Greatsword.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/weapon/melee/Greatsword.java index dababe1ec..abddf6342 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/weapon/melee/Greatsword.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/weapon/melee/Greatsword.java @@ -22,6 +22,9 @@ package com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee; import com.shatteredpixel.shatteredpixeldungeon.Assets; +import com.shatteredpixel.shatteredpixeldungeon.Dungeon; +import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero; +import com.shatteredpixel.shatteredpixeldungeon.messages.Messages; import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet; public class Greatsword extends MeleeWeapon { @@ -31,7 +34,22 @@ public class Greatsword extends MeleeWeapon { hitSound = Assets.Sounds.HIT_SLASH; hitSoundPitch = 1f; - tier=5; + tier = 5; + } + + @Override + public int abilityChargeUse() { + return Dungeon.hero.buff(Sword.CleaveTracker.class) != null ? 0 : 1; + } + + @Override + public String targetingPrompt() { + return Messages.get(this, "prompt"); + } + + @Override + protected void duelistAbility(Hero hero, Integer target) { + Sword.cleaveAbility(hero, target, 1.20f, this); } } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/weapon/melee/Longsword.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/weapon/melee/Longsword.java index 690b4e7e2..a0f7eb107 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/weapon/melee/Longsword.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/weapon/melee/Longsword.java @@ -22,6 +22,9 @@ package com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee; import com.shatteredpixel.shatteredpixeldungeon.Assets; +import com.shatteredpixel.shatteredpixeldungeon.Dungeon; +import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero; +import com.shatteredpixel.shatteredpixeldungeon.messages.Messages; import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet; public class Longsword extends MeleeWeapon { @@ -34,4 +37,19 @@ public class Longsword extends MeleeWeapon { tier = 4; } + @Override + public int abilityChargeUse() { + return Dungeon.hero.buff(Sword.CleaveTracker.class) != null ? 0 : 1; + } + + @Override + public String targetingPrompt() { + return Messages.get(this, "prompt"); + } + + @Override + protected void duelistAbility(Hero hero, Integer target) { + Sword.cleaveAbility(hero, target, 1.23f, this); + } + } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/weapon/melee/Shortsword.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/weapon/melee/Shortsword.java index 047e61273..b187c9576 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/weapon/melee/Shortsword.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/weapon/melee/Shortsword.java @@ -22,6 +22,9 @@ package com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee; import com.shatteredpixel.shatteredpixeldungeon.Assets; +import com.shatteredpixel.shatteredpixeldungeon.Dungeon; +import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero; +import com.shatteredpixel.shatteredpixeldungeon.messages.Messages; import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet; public class Shortsword extends MeleeWeapon { @@ -34,4 +37,19 @@ public class Shortsword extends MeleeWeapon { tier = 2; } + @Override + public int abilityChargeUse() { + return Dungeon.hero.buff(Sword.CleaveTracker.class) != null ? 0 : 1; + } + + @Override + public String targetingPrompt() { + return Messages.get(this, "prompt"); + } + + @Override + protected void duelistAbility(Hero hero, Integer target) { + Sword.cleaveAbility(hero, target, 1.30f, this); + } + } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/weapon/melee/Sword.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/weapon/melee/Sword.java index 36f2106c2..56df0dd8e 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/weapon/melee/Sword.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/weapon/melee/Sword.java @@ -22,7 +22,18 @@ package com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee; import com.shatteredpixel.shatteredpixeldungeon.Assets; +import com.shatteredpixel.shatteredpixeldungeon.Dungeon; +import com.shatteredpixel.shatteredpixeldungeon.actors.Actor; +import com.shatteredpixel.shatteredpixeldungeon.actors.Char; +import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff; +import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.FlavourBuff; +import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero; +import com.shatteredpixel.shatteredpixeldungeon.messages.Messages; import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet; +import com.shatteredpixel.shatteredpixeldungeon.ui.BuffIndicator; +import com.shatteredpixel.shatteredpixeldungeon.utils.GLog; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Callback; public class Sword extends MeleeWeapon { @@ -34,4 +45,67 @@ public class Sword extends MeleeWeapon { tier = 3; } + @Override + public int abilityChargeUse() { + return Dungeon.hero.buff(CleaveTracker.class) != null ? 0 : 1; + } + + @Override + public String targetingPrompt() { + return Messages.get(this, "prompt"); + } + + @Override + protected void duelistAbility(Hero hero, Integer target) { + Sword.cleaveAbility(hero, target, 1.27f, this); + } + + public static void cleaveAbility(Hero hero, Integer target, float dmgMulti, MeleeWeapon wep){ + if (target == null) { + return; + } + + Char enemy = Actor.findChar(target); + if (enemy == null || enemy == hero || hero.isCharmedBy(enemy) || !Dungeon.level.heroFOV[target]) { + GLog.w(Messages.get(wep, "ability_no_target")); + return; + } + + if (!hero.canAttack(enemy)){ + GLog.w(Messages.get(wep, "ability_bad_position")); + return; + } + + hero.sprite.attack(enemy.pos, new Callback() { + @Override + public void call() { + hero.attack(enemy, dmgMulti, 0, Char.INFINITE_ACCURACY); + wep.onAbilityUsed(hero); + Sample.INSTANCE.play(Assets.Sounds.HIT_STRONG); + + if (!enemy.isAlive()){ + hero.next(); + Buff.prolong(hero, CleaveTracker.class, 4f); //1 less as attack was instant + } else { + hero.spendAndNext(hero.attackDelay()); + if (hero.buff(CleaveTracker.class) != null) { + hero.buff(CleaveTracker.class).detach(); + } + } + } + }); + } + + public static class CleaveTracker extends FlavourBuff { + + { + type = buffType.POSITIVE; + } + + @Override + public int icon() { + return BuffIndicator.DUEL_CLEAVE; + } + } + } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/weapon/melee/WornShortsword.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/weapon/melee/WornShortsword.java index c3bc50ed0..8c77c964d 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/weapon/melee/WornShortsword.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/weapon/melee/WornShortsword.java @@ -22,6 +22,9 @@ package com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee; import com.shatteredpixel.shatteredpixeldungeon.Assets; +import com.shatteredpixel.shatteredpixeldungeon.Dungeon; +import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero; +import com.shatteredpixel.shatteredpixeldungeon.messages.Messages; import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet; public class WornShortsword extends MeleeWeapon { @@ -36,4 +39,19 @@ public class WornShortsword extends MeleeWeapon { bones = false; } + @Override + public int abilityChargeUse() { + return Dungeon.hero.buff(Sword.CleaveTracker.class) != null ? 0 : 1; + } + + @Override + public String targetingPrompt() { + return Messages.get(this, "prompt"); + } + + @Override + protected void duelistAbility(Hero hero, Integer target) { + Sword.cleaveAbility(hero, target, 1.33f, this); + } + } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/BuffIndicator.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/BuffIndicator.java index 31b3f6f2d..61eeae573 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/BuffIndicator.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/BuffIndicator.java @@ -111,6 +111,7 @@ public class BuffIndicator extends Component { public static final int INVERT_MARK = 57; public static final int NATURE_POWER= 58; public static final int AMULET = 59; + public static final int DUEL_CLEAVE = 60; public static final int SIZE_SMALL = 7; public static final int SIZE_LARGE = 16;