v2.0.0: lots of initial duelist weapon ability structure

This commit is contained in:
Evan Debenham
2022-11-15 13:38:04 -05:00
parent ac77531603
commit 607cdb7d4e
8 changed files with 147 additions and 8 deletions

View File

@@ -504,7 +504,7 @@ actors.hero.heroclass.huntress_unlock=To unlock the Huntress _hit enemies with t
actors.hero.heroclass.duelist=Duelist
actors.hero.heroclass.duelist_desc_short=The Duelist is a weapons master who can use her weapon to trigger a _special weapon ability._ This special ability is _different for every weapon._
actors.hero.heroclass.duelist_desc=The Duelist starts with a _unique Rapier_ with a special ability.\n\nThe Duelist gets a _different special ability_ for every weapon in the game.\n\nThe duelist also starts with _three throwing knives_, cloth armor, a waterskin, and a velvet pouch.\n\nThe Duelist automatically identifies:\n_-_ Scrolls of Identify\n_-_ Potions of Strength\n_-_ Scrolls of Mirror Image
actors.hero.heroclass.duelist_desc=The Duelist starts with a _unique rapier_ with a special ability that recharges over time.\n\nEvery weapon in the game has a _different special ability_ that the Duelist can use.\n\nThe duelist also starts with _three throwing knives_, cloth armor, a waterskin, and a velvet pouch.\n\nThe Duelist automatically identifies:\n_-_ Scrolls of Identify\n_-_ Potions of Strength\n_-_ Scrolls of Mirror Image
actors.hero.heroclass.duelist_unlock=To unlock the Duelist _equip a tier 2 or higher weapon with no strength penalty._
actors.hero.herosubclass.berserker=berserker

View File

@@ -1566,6 +1566,10 @@ items.weapon.melee.meleeweapon.stats_known=This _tier-%1$d_ melee weapon deals _
items.weapon.melee.meleeweapon.stats_unknown=Typically this _tier-%1$d_ melee weapon deals _%2$d-%3$d damage_ and requires _%4$d strength_ to use properly.
items.weapon.melee.meleeweapon.probably_too_heavy=Probably this weapon is too heavy for you.
items.weapon.melee.meleeweapon.stats_desc=
items.weapon.melee.meleeweapon.charge_use=This will consume _%s_ charge.
items.weapon.melee.meleeweapon.ability_equip=You must equip that weapon to use its ability.
items.weapon.melee.meleeweapon.ability_charge=You don't have enough energy to use that ability.
items.weapon.melee.meleeweapon.prompt=Select a Target
items.weapon.melee.shortsword.name=shortsword
items.weapon.melee.shortsword.desc=A quite short sword, only a few inches longer than a dagger.
@@ -1576,7 +1580,9 @@ items.weapon.melee.quarterstaff.desc=A staff of hardwood, its ends are shod with
items.weapon.melee.rapier.name=rapier
items.weapon.melee.rapier.stats_desc=This weapon blocks 0-1 damage.
items.weapon.melee.rapier.desc=TODO
items.weapon.melee.rapier.ability_name=lunge
items.weapon.melee.rapier.ability_desc=The duelist can _lunge_ with a rapier at an enemy 1 tile away. This moves into the enemy, deals +33% damage, and is guaranteed to hit.
items.weapon.melee.rapier.desc=A slim straight sword that offers some protection in exchange for less slashing power.
items.weapon.melee.roundshield.name=round shield
items.weapon.melee.roundshield.typical_stats_desc=Typically this weapon blocks 0-%d damage. This blocking scales with upgrades.

View File

@@ -27,6 +27,7 @@ import com.shatteredpixel.shatteredpixeldungeon.Challenges;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.QuickSlot;
import com.shatteredpixel.shatteredpixeldungeon.SPDSettings;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.abilities.ArmorAbility;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.abilities.huntress.NaturesPower;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.abilities.huntress.SpiritHawk;
@@ -63,6 +64,7 @@ import com.shatteredpixel.shatteredpixeldungeon.items.weapon.SpiritBow;
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.Dagger;
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.Gloves;
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.MagesStaff;
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.MeleeWeapon;
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.Rapier;
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.WornShortsword;
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.missiles.ThrowingKnife;
@@ -212,6 +214,9 @@ public enum HeroClass {
private static void initDuelist( Hero hero ) {
(hero.belongings.weapon = new Rapier()).identify();
hero.belongings.weapon.activate(hero);
Buff.affect(hero, MeleeWeapon.Charger.class).charge = 100f;
ThrowingKnife knives = new ThrowingKnife();
knives.quantity(3).collect();

View File

@@ -164,7 +164,7 @@ abstract public class ClassArmor extends Armor {
@Override
public String actionName(String action, Hero hero) {
if (hero.armorAbility != null && action.equals(AC_ABILITY)){
return hero.armorAbility.name().toUpperCase();
return Messages.upperCase(hero.armorAbility.name());
} else {
return super.actionName(action, hero);
}

View File

@@ -115,6 +115,7 @@ public class MagesStaff extends MeleeWeapon {
@Override
public void activate( Char ch ) {
super.activate(ch);
applyWandChargeBuff(ch);
}

View File

@@ -23,25 +23,39 @@ package com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.LockedFloor;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.HeroClass;
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.Weapon;
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
import com.shatteredpixel.shatteredpixeldungeon.scenes.CellSelector;
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
import com.watabou.utils.Bundle;
import com.watabou.utils.Random;
import java.text.DecimalFormat;
import java.util.ArrayList;
public class MeleeWeapon extends Weapon {
public static String AC_ABILITY = "ABILITY";
@Override
public void activate(Char ch) {
super.activate(ch);
if (ch instanceof Hero && ((Hero) ch).heroClass == HeroClass.DUELIST){
Buff.affect(ch, Charger.class);
}
}
@Override
public String defaultAction() {
if (Dungeon.hero != null && Dungeon.hero.heroClass == HeroClass.DUELIST){
return AC_ABILITY;
} else {
return null;
return super.defaultAction();
}
}
@@ -54,19 +68,68 @@ public class MeleeWeapon extends Weapon {
return actions;
}
@Override
public String actionName(String action, Hero hero) {
if (action.equals(AC_ABILITY)){
return Messages.upperCase(Messages.get(this, "ability_name"));
} else {
return super.actionName(action, hero);
}
}
@Override
public void execute(Hero hero, String action) {
super.execute(hero, action);
if (action.equals(AC_ABILITY)){
if (!isEquipped(hero)){
GLog.w("Need to Equip!");
if (!isEquipped(hero)) {
GLog.w(Messages.get(this, "ability_equip"));
} else if (Buff.affect(hero, Charger.class).charge < abilityChargeUse()) {
GLog.w(Messages.get(this, "ability_charge"));
} else {
GLog.i("Weapon Ability TODO");
if (targetingPrompt() == null){
Buff.affect(hero, Charger.class).charge -= abilityChargeUse();
duelistAbility(hero, hero.pos);
updateQuickslot();
} else {
usesTargeting = useTargeting();
GameScene.selectCell(new CellSelector.Listener() {
@Override
public void onSelect(Integer cell) {
if (cell != null) {
Buff.affect(hero, Charger.class).charge -= abilityChargeUse();
duelistAbility(hero, cell);
updateQuickslot();
}
}
@Override
public String prompt() {
return targetingPrompt();
}
});
}
}
}
}
//leave null for no targeting
public String targetingPrompt(){
return null;
}
public boolean useTargeting(){
return targetingPrompt() != null;
}
//TODO make abstract
protected void duelistAbility( Hero hero, Integer target ){}
public float abilityChargeUse(){
return 33f; //TODO
}
public int tier;
@Override
@@ -147,6 +210,11 @@ public class MeleeWeapon extends Weapon {
info += "\n\n" + Messages.get(Weapon.class, "not_cursed");
}
}
if (Dungeon.hero.heroClass == HeroClass.DUELIST){
info += "\n\n" + Messages.get(this, "ability_desc");
info += " " + Messages.get(MeleeWeapon.class, "charge_use", new DecimalFormat("#.##").format(abilityChargeUse()));
}
return info;
}
@@ -154,7 +222,17 @@ public class MeleeWeapon extends Weapon {
public String statsInfo(){
return Messages.get(this, "stats_desc");
}
@Override
public String status() {
if (isEquipped(Dungeon.hero)
&& Dungeon.hero.buff(Charger.class) != null) {
return Messages.format( "%.0f%%", Math.floor(Dungeon.hero.buff(Charger.class).charge) );
} else {
return super.status();
}
}
@Override
public int value() {
int price = 20 * tier;
@@ -173,4 +251,40 @@ public class MeleeWeapon extends Weapon {
return price;
}
public static class Charger extends Buff {
public float charge;
//offhand charge as well?
@Override
public boolean act() {
LockedFloor lock = target.buff(LockedFloor.class);
if (lock == null || lock.regenOn()) {
charge += 100 / 300f; //300 turns to full charge
updateQuickslot();
if (charge > 100) {
charge = 100;
}
}
spend(TICK);
return true;
}
public static final String CHARGE = "charge";
@Override
public void storeInBundle(Bundle bundle) {
super.storeInBundle(bundle);
bundle.put(CHARGE, charge);
}
@Override
public void restoreFromBundle(Bundle bundle) {
super.restoreFromBundle(bundle);
charge = bundle.getFloat(CHARGE);
}
}
}

View File

@@ -23,6 +23,7 @@ package com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee;
import com.shatteredpixel.shatteredpixeldungeon.Assets;
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet;
public class Rapier extends MeleeWeapon {
@@ -50,4 +51,8 @@ public class Rapier extends MeleeWeapon {
return 1; //1 extra defence
}
@Override
public String targetingPrompt() {
return Messages.get(this, "prompt");
}
}

View File

@@ -191,4 +191,12 @@ public class Messages {
//Otherwise, use sentence case
return capitalize(str);
}
public static String upperCase( String str ){
return str.toUpperCase(locale);
}
public static String lowerCase( String str ){
return str.toLowerCase(locale);
}
}