diff --git a/core/src/main/assets/messages/items/items.properties b/core/src/main/assets/messages/items/items.properties index 19840574f..cc6611029 100644 --- a/core/src/main/assets/messages/items/items.properties +++ b/core/src/main/assets/messages/items/items.properties @@ -1693,12 +1693,12 @@ items.weapon.melee.battleaxe.desc=The enormous steel head of this battle axe put items.weapon.melee.crossbow.name=crossbow items.weapon.melee.crossbow.stats_desc=This weapon enhances the damage of thrown darts when equipped, and will even grant its enchantment to them. items.weapon.melee.crossbow.ability_name=charged shot -items.weapon.melee.crossbow.typical_ability_desc=The Duelist can ready a _charged shot_ with a crossbow. This ability activates instantly and causes the next fired dart to always hit, apply on-hit effects to enemies in a 7x7 tile area, and typically last for _%d more uses_ if it is tipped. -items.weapon.melee.crossbow.ability_desc=The Duelist can ready a _charged shot_ with a crossbow. This ability activates instantly and causes the next fired dart to always hit, apply on-hit effects to enemies in a 7x7 tile area, and last for _%d more uses_ if it is tipped. +items.weapon.melee.crossbow.typical_ability_desc=The Duelist can _charge_ her crossbow, causing her next attack with it to always hit and apply one of three effects: melee attacks will knock enemies away, untipped darts will typically deal _+%1$d damage_, and tipped darts will apply their effect in a 7x7 area and typically last for _%2$d more uses_. +items.weapon.melee.crossbow.ability_desc=The Duelist can _charge_ her crossbow, causing her next attack with it to always hit and apply one of three effects: melee attacks will knock enemies away, untipped darts will deal _+%1$d damage_, and tipped darts will apply their effect in a 7x7 area and last for _%2$d more uses_. items.weapon.melee.crossbow.desc=A fairly intricate weapon which shoots bolts at exceptional speeds. While it isn't designed for it, this crossbow's heft and sturdy construction make it a decent melee weapon as well. -items.weapon.melee.crossbow.upgrade_ability_stat_name=Ability Extra Uses -items.weapon.melee.crossbow$chargedshot.name=charged shot -items.weapon.melee.crossbow$chargedshot.desc=The Duelist is focusing power into her crossbow. The next dart she fires with it will always hit and apply tipped dart effects and the crossbow's enchantment in a 7x7 area. Positive dart effects will only affect allies, and harmful effects will only apply to enemies.\n\nTipped darts will also have extra uses when fired using a charged shot. The Duelist cannot use this ability to apply positive dart effects to herself. +items.weapon.melee.crossbow.upgrade_ability_stat_name=Ability Boost +items.weapon.melee.crossbow$chargedshot.name=charged +items.weapon.melee.crossbow$chargedshot.desc=The Duelist is focusing power into her crossbow. The next attack she makes with it will always hit and apply one of three effects:\n- Melee attacks with knock enemies a few tiles away.\n- Untipped darts will deal bonus damage.\n- Tipped darts will gain extra uses and apply their effect in a 7x7 area. Positive dart effects will only affect allies, and harmful effects will only apply to enemies. The Duelist cannot use this ability to apply positive dart effects to herself. items.weapon.melee.dagger.name=dagger items.weapon.melee.dagger.stats_desc=This weapon is stronger against unaware enemies. diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/weapon/melee/Crossbow.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/weapon/melee/Crossbow.java index de99bb3f1..e98ff0ec4 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/weapon/melee/Crossbow.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/weapon/melee/Crossbow.java @@ -22,8 +22,13 @@ package com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee; import com.shatteredpixel.shatteredpixeldungeon.Assets; +import com.shatteredpixel.shatteredpixeldungeon.actors.Actor; +import com.shatteredpixel.shatteredpixeldungeon.actors.Char; import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff; import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero; +import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfBlastWave; +import com.shatteredpixel.shatteredpixeldungeon.items.weapon.missiles.darts.Dart; +import com.shatteredpixel.shatteredpixeldungeon.mechanics.Ballistica; import com.shatteredpixel.shatteredpixeldungeon.messages.Messages; import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet; import com.shatteredpixel.shatteredpixeldungeon.ui.BuffIndicator; @@ -55,7 +60,49 @@ public class Crossbow extends MeleeWeapon { return false; } } - + + @Override + public float accuracyFactor(Char owner, Char target) { + if (owner.buff(Crossbow.ChargedShot.class) != null){ + Actor.add(new Actor() { + { actPriority = VFX_PRIO; } + @Override + protected boolean act() { + if (owner instanceof Hero && !target.isAlive()){ + onAbilityKill((Hero)owner, target); + } + Actor.remove(this); + return true; + } + }); + return Float.POSITIVE_INFINITY; + } else { + return super.accuracyFactor(owner, target); + } + } + + @Override + public int proc(Char attacker, Char defender, int damage) { + int dmg = super.proc(attacker, defender, damage); + + //stronger elastic effect + if (attacker.buff(ChargedShot.class) != null && !(curItem instanceof Dart)){ + //trace a ballistica to our target (which will also extend past them + Ballistica trajectory = new Ballistica(attacker.pos, defender.pos, Ballistica.STOP_TARGET); + //trim it to just be the part that goes past them + trajectory = new Ballistica(trajectory.collisionPos, trajectory.path.get(trajectory.path.size()-1), Ballistica.PROJECTILE); + //knock them back along that ballistica + WandOfBlastWave.throwChar(defender, + trajectory, + 3, + true, + true, + this); + attacker.buff(Crossbow.ChargedShot.class).detach(); + } + return dmg; + } + @Override public int max(int lvl) { return 4*(tier+1) + //20 base, down from 25 @@ -79,9 +126,9 @@ public class Crossbow extends MeleeWeapon { @Override public String abilityInfo() { if (levelKnown){ - return Messages.get(this, "ability_desc", 3+buffedLvl()); + return Messages.get(this, "ability_desc", 3+buffedLvl(), 3+buffedLvl()); } else { - return Messages.get(this, "typical_ability_desc", 3); + return Messages.get(this, "typical_ability_desc", 3, 3); } } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/weapon/melee/MeleeWeapon.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/weapon/melee/MeleeWeapon.java index 9ad881236..98924b41b 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/weapon/melee/MeleeWeapon.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/weapon/melee/MeleeWeapon.java @@ -307,6 +307,8 @@ public class MeleeWeapon extends Weapon { ACC *= 1f + 0.1f * ((Hero) owner).pointsInTalent(Talent.PRECISE_ASSAULT); } else if (this instanceof Flail && owner.buff(Flail.SpinAbilityTracker.class) != null){ //do nothing, this is not a regular attack so don't consume talent fx + } else if (this instanceof Crossbow && owner.buff(Crossbow.ChargedShot.class) != null){ + //do nothing, this is not a regular attack so don't consume talent fx } else if (owner.buff(Talent.PreciseAssaultTracker.class) != null) { // 2x/5x/inf. ACC for duelist if she just used a weapon ability switch (((Hero) owner).pointsInTalent(Talent.PRECISE_ASSAULT)){ diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/weapon/missiles/darts/Dart.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/weapon/missiles/darts/Dart.java index 6fdb01953..5f17a7084 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/weapon/missiles/darts/Dart.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/weapon/missiles/darts/Dart.java @@ -78,8 +78,14 @@ public class Dart extends MissileWeapon { @Override public int min(int lvl) { if (bow != null){ - return 4 + //4 base - bow.buffedLvl() + lvl; //+1 per level or bow level + if (!(this instanceof TippedDart) && Dungeon.hero.buff(Crossbow.ChargedShot.class) != null){ + //ability increases base dmg by 37.5%, scaling by 50% + return 7 + //7 base + 2*bow.buffedLvl() + lvl;//+2 per bow level, +1 per level + } else { + return 4 + //4 base + bow.buffedLvl() + lvl; //+1 per level or bow level + } } else { return 1 + //1 base, down from 2 lvl; //scaling unchanged @@ -89,8 +95,14 @@ public class Dart extends MissileWeapon { @Override public int max(int lvl) { if (bow != null){ - return 12 + //12 base - 3*bow.buffedLvl() + 2*lvl; //+3 per bow level, +2 per level (default scaling +2) + if (!(this instanceof TippedDart) && Dungeon.hero.buff(Crossbow.ChargedShot.class) != null){ + //ability increases base dmg by 37.5%, scaling by 50% + return 15 + //15 base + 4*bow.buffedLvl() + 2*lvl; //+4 per bow level, +2 per level + } else { + return 12 + //12 base + 3*bow.buffedLvl() + 2*lvl; //+3 per bow level, +2 per level + } } else { return 2 + //2 base, down from 5 2*lvl; //scaling unchanged @@ -136,9 +148,7 @@ public class Dart extends MissileWeapon { @Override public int proc(Char attacker, Char defender, int damage) { - if (bow != null - //only apply enchant effects to enemies when processing charged shot - && (!processingChargedShot || attacker.alignment != defender.alignment)){ + if (bow != null && !processingChargedShot){ damage = bow.proc(attacker, defender, damage); }