v0.7.1: implemented upgradeable missile weapons!

- missile weapons now have damage scaling and can be upgraded (except darts)
- upgraded missile weapons gain 3x durability (stacking multiplicatively)
- missile weapons with more than 100 uses now last indefinitely
- ring of sharpshooting now works with damage scaling, rather than applying a flat +20% dmg per level
- bolas buffed. base damage up to 6-9, from 4-6
- shuriken adjusted. base damage up to 4-8, from 4-6. uses down to 5, from 10
- throwing stones now have 1/2 value, instead of 1 value.
This commit is contained in:
Evan Debenham 2018-11-13 21:12:46 -05:00
parent 24a22626ee
commit 5207ba4e90
17 changed files with 143 additions and 248 deletions

View File

@ -288,7 +288,7 @@ public class Item implements Bundlable {
}
public boolean isSimilar( Item item ) {
return getClass() == item.getClass();
return level == item.level && getClass() == item.getClass();
}
protected void onDetach(){}

View File

@ -30,9 +30,8 @@ public class RingOfSharpshooting extends Ring {
return new Aim();
}
//roughly in line with the boost a weapon gets from an upgrade
public static float damageMultiplier( Char target ){
return 1f + 0.2f * getBonus(target, Aim.class);
public static int levelDamageBonus( Char target ){
return getBonus(target, RingOfSharpshooting.Aim.class);
}
public static float durabilityMultiplier( Char target ){

View File

@ -31,21 +31,14 @@ public class Bolas extends MissileWeapon {
{
image = ItemSpriteSheet.BOLAS;
}
@Override
public int min(int lvl) {
return 4;
tier = 3;
baseUses = 5;
}
@Override
public int max(int lvl) {
return 6;
}
@Override
public int STRReq(int lvl) {
return 13;
return 3 * tier + //9 base, down from 15
(tier == 1 ? 2*lvl : tier*lvl); //scaling unchanged
}
@Override
@ -53,14 +46,4 @@ public class Bolas extends MissileWeapon {
Buff.prolong( defender, Cripple.class, Cripple.DURATION );
return super.proc( attacker, defender, damage );
}
@Override
protected float durabilityPerUse() {
return super.durabilityPerUse()*2f;
}
@Override
public int price() {
return 18 * quantity;
}
}

View File

@ -42,6 +42,7 @@ public class Boomerang extends MissileWeapon {
unique = true;
bones = false;
tier = 1;
}
@Override
@ -63,18 +64,6 @@ public class Boomerang extends MissileWeapon {
2 * lvl;//scales the same as a tier 1 weapon
}
@Override
public int STRReq(int lvl) {
lvl = Math.max(0, lvl);
//strength req decreases at +1,+3,+6,+10,etc.
return 9 - (int)(Math.sqrt(8 * lvl + 1) - 1)/2;
}
@Override
public boolean isUpgradable() {
return true;
}
@Override
public boolean isIdentified() {
return levelKnown && cursedKnown;

View File

@ -29,21 +29,8 @@ public class FishingSpear extends MissileWeapon {
{
image = ItemSpriteSheet.FISHING_SPEAR;
}
@Override
public int min(int lvl) {
return 4;
}
@Override
public int max(int lvl) {
return 10;
}
@Override
public int STRReq(int lvl) {
return 11;
tier = 2;
}
@Override
@ -53,10 +40,4 @@ public class FishingSpear extends MissileWeapon {
}
return super.proc(attacker, defender, damage);
}
@Override
public int price() {
return 12 * quantity;
}
}

View File

@ -27,25 +27,8 @@ public class Javelin extends MissileWeapon {
{
image = ItemSpriteSheet.JAVELIN;
tier = 4;
}
@Override
public int min(int lvl) {
return 8;
}
@Override
public int max(int lvl) {
return 20;
}
@Override
public int STRReq(int lvl) {
return 15;
}
@Override
public int price() {
return 24 * quantity;
}
}

View File

@ -48,6 +48,8 @@ abstract public class MissileWeapon extends Weapon {
stackable = true;
levelKnown = true;
bones = true;
defaultAction = AC_THROW;
usesTargeting = true;
}
@ -56,12 +58,64 @@ abstract public class MissileWeapon extends Weapon {
protected static final float MAX_DURABILITY = 100;
protected float durability = MAX_DURABILITY;
protected int baseUses = 10;
public boolean holster;
//used to reduce durability from the source weapon stack, rather than the one being thrown.
protected MissileWeapon parent;
public int tier;
@Override
public int min() {
return Math.max(0, min( level() + RingOfSharpshooting.levelDamageBonus(Dungeon.hero) ));
}
@Override
public int min(int lvl) {
return 2 * tier + //base
(tier == 1 ? lvl : 2*lvl); //level scaling
}
@Override
public int max() {
return Math.max(0, max( level() + RingOfSharpshooting.levelDamageBonus(Dungeon.hero) ));
}
@Override
public int max(int lvl) {
return 5 * tier + //base
(tier == 1 ? 2*lvl : tier*lvl); //level scaling
}
public int STRReq(int lvl){
lvl = Math.max(0, lvl);
//strength req decreases at +1,+3,+6,+10,etc.
return (7 + tier * 2) - (int)(Math.sqrt(8 * lvl + 1) - 1)/2;
}
@Override
public Item upgrade() {
if (quantity > 1){
MissileWeapon left = (MissileWeapon) split(quantity - 1);
left.parent = null;
super.upgrade();
//deal with full inventory.
if (!left.collect()){
Dungeon.level.drop( left, Dungeon.hero.pos);
}
} else {
super.upgrade();
}
durability = MAX_DURABILITY;
return this;
}
@Override
public ArrayList<String> actions( Hero hero ) {
ArrayList<String> actions = super.actions( hero );
@ -170,20 +224,21 @@ abstract public class MissileWeapon extends Weapon {
}
protected float durabilityPerUse(){
float usage = MAX_DURABILITY/10f;
float usages = baseUses * (float)(Math.pow(3, level()));
if (Dungeon.hero.heroClass == HeroClass.HUNTRESS) usage /= 1.5f;
if (holster) usage /= MagicalHolster.HOLSTER_DURABILITY_FACTOR;
if (Dungeon.hero.heroClass == HeroClass.HUNTRESS) usages *= 1.5f;
if (holster) usages *= MagicalHolster.HOLSTER_DURABILITY_FACTOR;
usage /= RingOfSharpshooting.durabilityMultiplier( Dungeon.hero );
usages *= RingOfSharpshooting.durabilityMultiplier( Dungeon.hero );
return usage;
float usage = MAX_DURABILITY/usages;
//after 100 uses, items just last forever.
return usage >= (MAX_DURABILITY/100f) ? usage : 0;
}
@Override
public int damageRoll(Char owner) {
int damage = augment.damageFactor(super.damageRoll( owner ));
damage = Math.round( damage * RingOfSharpshooting.damageMultiplier( owner ));
if (owner instanceof Hero &&
((Hero)owner).heroClass == HeroClass.HUNTRESS) {
@ -237,11 +292,6 @@ abstract public class MissileWeapon extends Weapon {
return super.doPickUp(hero);
}
@Override
public boolean isUpgradable() {
return false;
}
@Override
public boolean isIdentified() {
return true;
@ -253,8 +303,9 @@ abstract public class MissileWeapon extends Weapon {
String info = desc();
info += "\n\n" + Messages.get( MissileWeapon.class, "stats",
Math.round(augment.damageFactor(min()) * RingOfSharpshooting.damageMultiplier( Dungeon.hero )),
Math.round(augment.damageFactor(max()) * RingOfSharpshooting.damageMultiplier( Dungeon.hero )),
tier,
Math.round(augment.damageFactor(min())),
Math.round(augment.damageFactor(max())),
STRReq());
if (STRReq() > Dungeon.hero.STR()) {
@ -284,12 +335,19 @@ abstract public class MissileWeapon extends Weapon {
info += " " + Messages.get(this, "uses_left",
(int)Math.ceil(durability/durabilityPerUse()),
(int)Math.ceil(MAX_DURABILITY/durabilityPerUse()));
} else {
info += " " + Messages.get(this, "unlimited_uses");
}
return info;
}
@Override
public int price() {
return 6 * tier * quantity * (level() + 1);
}
private static final String DURABILITY = "durability";
@Override

View File

@ -29,21 +29,15 @@ public class Shuriken extends MissileWeapon {
{
image = ItemSpriteSheet.SHURIKEN;
}
@Override
public int min(int lvl) {
return 4;
tier = 2;
baseUses = 5;
}
@Override
public int max(int lvl) {
return 6;
}
@Override
public int STRReq(int lvl) {
return 11;
return 4 * tier + //8 base, down from 10
(tier == 1 ? 2*lvl : tier*lvl); //scaling unchanged
}
@Override
@ -51,9 +45,4 @@ public class Shuriken extends MissileWeapon {
if (owner instanceof Hero && ((Hero) owner).justMoved) return 0;
else return super.speedFactor(owner);
}
@Override
public int price() {
return 12 * quantity;
}
}

View File

@ -28,31 +28,20 @@ public class ThrowingHammer extends MissileWeapon {
{
image = ItemSpriteSheet.THROWING_HAMMER;
tier = 5;
baseUses = 15;
sticky = false;
}
@Override
public int min(int lvl) {
return 8;
return Math.round(1.6f * tier) + //8 base, down from 10
(tier == 1 ? lvl : 2*lvl); //scaling unchanged
}
@Override
public int max(int lvl) {
return 20;
}
@Override
public int STRReq(int lvl) {
return 17;
}
@Override
protected float durabilityPerUse() {
return super.durabilityPerUse()/1.5f;
}
@Override
public int price() {
return 30 * quantity;
return 4 * tier + //20 base, down from 25
(tier-1) * lvl; //+4 per level, down from +5
}
}

View File

@ -26,7 +26,6 @@ import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.HeroClass;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob;
import com.shatteredpixel.shatteredpixeldungeon.items.rings.RingOfSharpshooting;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet;
import com.watabou.utils.Random;
@ -37,21 +36,14 @@ public class ThrowingKnife extends MissileWeapon {
bones = false;
}
@Override
public int min(int lvl) {
return 2;
tier = 1;
baseUses = 5;
}
@Override
public int max(int lvl) {
return 6;
}
@Override
public int STRReq(int lvl) {
return 9;
return 6 * tier + //6 base, up from 5
(tier == 1 ? 2*lvl : tier*lvl); //scaling unchanged
}
private Char enemy;
@ -72,7 +64,6 @@ public class ThrowingKnife extends MissileWeapon {
int damage = augment.damageFactor(Random.NormalIntRange(
min() + Math.round(diff*0.75f),
max()));
damage = Math.round(damage * RingOfSharpshooting.damageMultiplier( hero ));
int exStr = hero.STR() - STRReq();
if (exStr > 0 && hero.heroClass == HeroClass.HUNTRESS) {
damage += Random.IntRange(0, exStr);
@ -82,14 +73,4 @@ public class ThrowingKnife extends MissileWeapon {
}
return super.damageRoll(owner);
}
@Override
protected float durabilityPerUse() {
return super.durabilityPerUse()*2f;
}
@Override
public int price() {
return 6 * quantity;
}
}

View File

@ -27,26 +27,8 @@ public class ThrowingSpear extends MissileWeapon {
{
image = ItemSpriteSheet.THROWING_SPEAR;
}
@Override
public int min(int lvl) {
return 6;
}
@Override
public int max(int lvl) {
return 15;
}
@Override
public int STRReq(int lvl) {
return 13;
}
@Override
public int price() {
return 18 * quantity;
tier = 3;
}
}

View File

@ -28,34 +28,21 @@ public class ThrowingStone extends MissileWeapon {
{
image = ItemSpriteSheet.THROWING_STONE;
sticky = false;
bones = false;
tier = 1;
baseUses = 3;
sticky = false;
}
@Override
public int min(int lvl) {
return 1;
}
@Override
public int max(int lvl) {
return 5;
}
@Override
public int STRReq(int lvl) {
return 9;
}
@Override
protected float durabilityPerUse() {
return super.durabilityPerUse()*3.34f;
return tier + //1 base, down from 2
(tier == 1 ? lvl : 2*lvl); //scaling unchanged
}
@Override
public int price() {
return quantity;
return super.price()/2; //half normal value
}
}

View File

@ -31,21 +31,20 @@ public class Tomahawk extends MissileWeapon {
{
image = ItemSpriteSheet.TOMAHAWK;
tier = 4;
baseUses = 5;
}
@Override
public int min(int lvl) {
return 6;
return Math.round(1.5f * tier) + //6 base, down from 8
2 * lvl; //scaling unchanged
}
@Override
public int max(int lvl) {
return 15;
}
@Override
public int STRReq(int lvl) {
return 15;
return Math.round(3.75f * tier) + //15 base, down from 20
(tier-1)*lvl; //+3 per level, down from +4
}
@Override
@ -53,14 +52,4 @@ public class Tomahawk extends MissileWeapon {
Buff.affect( defender, Bleeding.class ).set( damage );
return super.proc( attacker, defender, damage );
}
@Override
protected float durabilityPerUse() {
return super.durabilityPerUse()*2f;
}
@Override
public int price() {
return 24 * quantity;
}
}

View File

@ -27,26 +27,8 @@ public class Trident extends MissileWeapon {
{
image = ItemSpriteSheet.TRIDENT;
}
@Override
public int min(int lvl) {
return 10;
}
@Override
public int max(int lvl) {
return 25;
}
@Override
public int STRReq(int lvl) {
return 17;
}
@Override
public int price() {
return 30 * quantity;
tier = 5;
}
}

View File

@ -34,21 +34,30 @@ public class Dart extends MissileWeapon {
{
image = ItemSpriteSheet.DART;
tier = 1;
}
@Override
public int min(int lvl) {
return bow != null ? 4 + bow.level() : 1;
if (bow != null){
return 4 + //4 base
bow.level() + lvl; //+1 per level or bow level
} else {
return 1 + //1 base, down from 2
lvl; //scaling unchanged
}
}
@Override
public int max(int lvl) {
return bow != null ? 12 + 3*bow.level() : 2;
}
@Override
public int STRReq(int lvl) {
return 9;
if (bow != null){
return 12 + //12 base
3*(bow.level() + lvl); //+3 per level or bow level
} else {
return 2 + //2 base, down from 5
2*lvl; //scaling unchanged
}
}
@Override
@ -97,7 +106,7 @@ public class Dart extends MissileWeapon {
}
@Override
public int price() {
return 4 * quantity;
public boolean isUpgradable() {
return false;
}
}

View File

@ -49,13 +49,10 @@ import java.util.HashMap;
public abstract class TippedDart extends Dart {
{
bones = true;
tier = 2;
}
@Override
public int STRReq(int lvl) {
return 11;
}
//exact same damage as regular darts, despite being higher tier.
@Override
protected void rangedHit(Char enemy, int cell) {
@ -71,11 +68,6 @@ public abstract class TippedDart extends Dart {
Dungeon.level.drop( d, enemy.pos ).sprite.drop();
}
@Override
public int price() {
return 6 * quantity;
}
private static HashMap<Class<?extends Plant.Seed>, Class<?extends TippedDart>> types = new HashMap<>();
static {
types.put(Blindweed.Seed.class, BlindingDart.class);

View File

@ -1313,7 +1313,7 @@ items.weapon.missiles.darts.chillingdart.desc=These darts are tipped with an ice
items.weapon.missiles.darts.dart.name=dart
items.weapon.missiles.darts.dart.desc=These simple shafts of spike-tipped wood are weighted to fly true and sting their prey with a flick of the wrist.
items.weapon.missiles.darts.dart.durability=Due to their size and simple construction, darts will never break from use. However specially tipped darts will lose their effect after one use.
items.weapon.missiles.darts.dart.unlimited_uses=However, due to their simple construction darts will effectively last forever.
items.weapon.missiles.darts.displacingdart.name=displacing dart
items.weapon.missiles.darts.displacingdart.desc=These darts are tipped with a fadeleaf-based compound which will teleport their target a short distance away.
@ -1324,12 +1324,12 @@ items.weapon.missiles.darts.healingdart.desc=These darts are tipped with a sungr
items.weapon.missiles.darts.holydart.name=holy dart
items.weapon.missiles.darts.holydart.desc=These darts are tipped with a starflower-based compound which grants a boost in power to their target. The dart itself is still harmful though.
items.weapon.missiles.darts.paralyticdart.name=paralytic dart
items.weapon.missiles.darts.paralyticdart.desc=These darts are tipped with an earthroot-based compound which will paralyze their target for a short time.
items.weapon.missiles.darts.incendiarydart.name=incendiary dart
items.weapon.missiles.darts.incendiarydart.desc=These darts are tipped with a firebloom-based compound which will burst into brilliant flames on impact.
items.weapon.missiles.darts.paralyticdart.name=paralytic dart
items.weapon.missiles.darts.paralyticdart.desc=These darts are tipped with an earthroot-based compound which will paralyze their target for a short time.
items.weapon.missiles.darts.poisondart.name=poison dart
items.weapon.missiles.darts.poisondart.desc=These darts are tipped with a sorrowmoss-based compound which will poison their target.
@ -1342,6 +1342,7 @@ items.weapon.missiles.darts.shockingdart.desc=These darts are tipped with a stor
items.weapon.missiles.darts.sleepdart.name=sleep dart
items.weapon.missiles.darts.sleepdart.desc=These darts are tipped with a dreamfoil-based compound which will instantly put their target into a light sleep.
items.weapon.missiles.darts.tippeddart.unlimited_uses=Tipped darts will expend their effect once used and will become regular darts.
items.weapon.missiles.bolas.name=bolas
@ -1360,10 +1361,11 @@ items.weapon.missiles.fishingspear.desc=Tiny throwing spears designed for fishin
items.weapon.missiles.javelin.name=javelin
items.weapon.missiles.javelin.desc=These larger throwing spears are weighted to keep the spike at their tip foremost as they sail through the air.
items.weapon.missiles.missileweapon.stats=This missile weapon deals _%1$d-%2$d damage_ and requires _%3$d strength_ to use properly.
items.weapon.missiles.missileweapon.stats=This _tier-%1$d_ missile weapon deals _%2$d-%3$d damage_ and requires _%4$d strength_ to use properly.
items.weapon.missiles.missileweapon.distance=This weapon is designed to be used at a distance, it is much less accurate at melee range.
items.weapon.missiles.missileweapon.durability=Missile weapons will wear out and break as they are used.
items.weapon.missiles.missileweapon.uses_left=This stack of weapons has _%d/%d_ uses left before one breaks.
items.weapon.missiles.missileweapon.unlimited_uses=_But these are of such high quality that they will effectively last forever._
items.weapon.missiles.shuriken.name=shuriken
items.weapon.missiles.shuriken.desc=Star-shaped pieces of metal with razor-sharp blades. They are lightweight and easy to use on the move. A single shuriken can be thrown instantly after moving.