diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/Char.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/Char.java index 77dc0d0c8..cf7d0a4bb 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/Char.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/Char.java @@ -186,7 +186,8 @@ public abstract class Char extends Actor { if (this instanceof Hero){ Hero h = (Hero)this; if (h.belongings.weapon instanceof MissileWeapon - && h.subClass == HeroSubClass.SNIPER){ + && h.subClass == HeroSubClass.SNIPER + && !Dungeon.level.adjacent(h.pos, enemy.pos)){ dr = 0; } } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/buffs/Barkskin.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/buffs/Barkskin.java index 82cdc735a..e01f56d6e 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/buffs/Barkskin.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/buffs/Barkskin.java @@ -61,7 +61,7 @@ public class Barkskin extends Buff { if (Math.sqrt(interval)*level < Math.sqrt(time)*value) { level = value; interval = time; - spend(time - cooldown()); + spend(time - cooldown() - 1); } } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/Hero.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/Hero.java index 8233418a5..6c1493c5f 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/Hero.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/Hero.java @@ -295,11 +295,9 @@ public class Hero extends Char { //temporarily set the hero's weapon to the missile weapon being used KindOfWeapon equipped = belongings.weapon; belongings.weapon = wep; - rangedAttack = true; boolean result = attack( enemy ); Invisibility.dispel(); belongings.weapon = equipped; - rangedAttack = false; return result; } @@ -311,9 +309,13 @@ public class Hero extends Char { float accuracy = 1; accuracy *= RingOfAccuracy.accuracyMultiplier( this ); - if (wep instanceof MissileWeapon && rangedAttack - && Dungeon.level.distance( pos, target.pos ) == 1) { - accuracy *= 0.5f; + if (wep instanceof MissileWeapon){ + if (Dungeon.level.adjacent( pos, target.pos )) { + accuracy *= 0.5f; + } else if (subClass == HeroSubClass.SNIPER){ + //+10% accuracy per tile of distance + accuracy *= .9f + (.1f * Dungeon.level.distance( pos, target.pos)); + } } if (wep != null) { @@ -474,7 +476,6 @@ public class Hero extends Char { //calls to dungeon.observe will also update hero's local FOV. fieldOfView = Dungeon.level.heroFOV; - if (!ready) { //do a full observe (including fog update) if not resting. if (!resting || buff(MindVision.class) != null || buff(Awareness.class) != null) { @@ -498,15 +499,17 @@ public class Hero extends Char { return false; } + boolean actResult; if (curAction == null) { if (resting) { - spend( TIME_TO_REST ); next(); - return false; + spend( TIME_TO_REST ); + next(); + } else { + ready(); } - ready(); - return false; + actResult = false; } else { @@ -515,58 +518,45 @@ public class Hero extends Char { ready = false; if (curAction instanceof HeroAction.Move) { + actResult = actMove( (HeroAction.Move)curAction ); - return actMove( (HeroAction.Move)curAction ); + } else if (curAction instanceof HeroAction.Interact) { + actResult = actInteract( (HeroAction.Interact)curAction ); - } else - if (curAction instanceof HeroAction.Interact) { - - return actInteract( (HeroAction.Interact)curAction ); + } else if (curAction instanceof HeroAction.Buy) { + actResult = actBuy( (HeroAction.Buy)curAction ); - } else - if (curAction instanceof HeroAction.Buy) { - - return actBuy( (HeroAction.Buy)curAction ); + }else if (curAction instanceof HeroAction.PickUp) { + actResult = actPickUp( (HeroAction.PickUp)curAction ); - }else - if (curAction instanceof HeroAction.PickUp) { - - return actPickUp( (HeroAction.PickUp)curAction ); + } else if (curAction instanceof HeroAction.OpenChest) { + actResult = actOpenChest( (HeroAction.OpenChest)curAction ); - } else - if (curAction instanceof HeroAction.OpenChest) { - - return actOpenChest( (HeroAction.OpenChest)curAction ); + } else if (curAction instanceof HeroAction.Unlock) { + actResult = actUnlock((HeroAction.Unlock) curAction); - } else - if (curAction instanceof HeroAction.Unlock) { - - return actUnlock((HeroAction.Unlock) curAction); + } else if (curAction instanceof HeroAction.Descend) { + actResult = actDescend( (HeroAction.Descend)curAction ); - } else - if (curAction instanceof HeroAction.Descend) { - - return actDescend( (HeroAction.Descend)curAction ); + } else if (curAction instanceof HeroAction.Ascend) { + actResult = actAscend( (HeroAction.Ascend)curAction ); - } else - if (curAction instanceof HeroAction.Ascend) { - - return actAscend( (HeroAction.Ascend)curAction ); + } else if (curAction instanceof HeroAction.Attack) { + actResult = actAttack( (HeroAction.Attack)curAction ); - } else - if (curAction instanceof HeroAction.Attack) { - - return actAttack( (HeroAction.Attack)curAction ); - - } else - if (curAction instanceof HeroAction.Alchemy) { - - return actAlchemy( (HeroAction.Alchemy)curAction ); + } else if (curAction instanceof HeroAction.Alchemy) { + actResult = actAlchemy( (HeroAction.Alchemy)curAction ); + } else { + actResult = false; } } - return false; + if( subClass == HeroSubClass.WARDEN && Dungeon.level.map[pos] == Terrain.FURROWED_GRASS){ + Buff.affect(this, Barkskin.class).set( lvl, 1 ); + } + + return actResult; } public void busy() { @@ -937,7 +927,7 @@ public class Hero extends Char { switch (subClass) { case SNIPER: - if (wep instanceof MissileWeapon && rangedAttack) { + if (wep instanceof MissileWeapon) { Buff.prolong( this, SnipersMark.class, attackDelay() ).object = enemy.id(); } break; diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/HeroClass.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/HeroClass.java index 2e7d2abc4..8fbb1f7e0 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/HeroClass.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/HeroClass.java @@ -59,7 +59,7 @@ public enum HeroClass { WARRIOR( "warrior", HeroSubClass.BERSERKER, HeroSubClass.GLADIATOR ), MAGE( "mage", HeroSubClass.BATTLEMAGE, HeroSubClass.WARLOCK ), ROGUE( "rogue", HeroSubClass.ASSASSIN, HeroSubClass.FREERUNNER ), - HUNTRESS( "huntress", HeroSubClass.WARDEN, HeroSubClass.SNIPER ); + HUNTRESS( "huntress", HeroSubClass.SNIPER, HeroSubClass.WARDEN ); private String title; private HeroSubClass[] subClasses; diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/HeroSubClass.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/HeroSubClass.java index 33036a4b4..c3bad6445 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/HeroSubClass.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/HeroSubClass.java @@ -36,7 +36,7 @@ public enum HeroSubClass { ASSASSIN( "assassin" ), FREERUNNER( "freerunner" ), - + SNIPER( "sniper" ), WARDEN( "warden" ); diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/DewVial.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/DewVial.java index 7e1a71538..49a82adb0 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/DewVial.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/DewVial.java @@ -23,7 +23,6 @@ package com.shatteredpixel.shatteredpixeldungeon.items; import com.shatteredpixel.shatteredpixeldungeon.Assets; import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero; -import com.shatteredpixel.shatteredpixeldungeon.actors.hero.HeroSubClass; import com.shatteredpixel.shatteredpixeldungeon.effects.Speck; import com.shatteredpixel.shatteredpixeldungeon.messages.Messages; import com.shatteredpixel.shatteredpixeldungeon.sprites.CharSprite; @@ -87,15 +86,14 @@ public class DewVial extends Item { if (volume > 0) { - //20 drops for a full heal normally, 15 for the warden - float dropHealPercent = hero.subClass == HeroSubClass.WARDEN ? 0.0667f : 0.05f; float missingHealthPercent = 1f - (hero.HP / (float)hero.HT); //trimming off 0.01 drops helps with floating point errors - int dropsNeeded = (int)Math.ceil((missingHealthPercent / dropHealPercent) - 0.01f); + int dropsNeeded = (int)Math.ceil((missingHealthPercent / 0.05f) - 0.01f); dropsNeeded = (int)GameMath.gate(1, dropsNeeded, volume); - int heal = Math.round( hero.HT * dropHealPercent * dropsNeeded ); + //20 drops for a full heal normally + int heal = Math.round( hero.HT * 0.05f * dropsNeeded ); int effect = Math.min( hero.HT - hero.HP, heal ); if (effect > 0) { diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/Dewdrop.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/Dewdrop.java index 8aed10b7a..0ddc6352f 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/Dewdrop.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/Dewdrop.java @@ -23,7 +23,6 @@ package com.shatteredpixel.shatteredpixeldungeon.items; import com.shatteredpixel.shatteredpixeldungeon.Assets; import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero; -import com.shatteredpixel.shatteredpixeldungeon.actors.hero.HeroSubClass; import com.shatteredpixel.shatteredpixeldungeon.effects.Speck; import com.shatteredpixel.shatteredpixeldungeon.messages.Messages; import com.shatteredpixel.shatteredpixeldungeon.sprites.CharSprite; @@ -50,9 +49,8 @@ public class Dewdrop extends Item { } else { - //20 drops for a full heal normally, 15 for the warden - float healthPercent = hero.subClass == HeroSubClass.WARDEN ? 0.0667f : 0.05f; - int heal = Math.round( hero.HT * healthPercent * quantity ); + //20 drops for a full heal + int heal = Math.round( hero.HT * 0.05f * quantity ); int effect = Math.min( hero.HT - hero.HP, heal ); if (effect > 0) { diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/features/HighGrass.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/features/HighGrass.java index 26a0a84fd..4d9281240 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/features/HighGrass.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/features/HighGrass.java @@ -23,11 +23,9 @@ package com.shatteredpixel.shatteredpixeldungeon.levels.features; import com.shatteredpixel.shatteredpixeldungeon.Dungeon; import com.shatteredpixel.shatteredpixeldungeon.actors.Char; -import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Barkskin; import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff; import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero; import com.shatteredpixel.shatteredpixeldungeon.actors.hero.HeroClass; -import com.shatteredpixel.shatteredpixeldungeon.actors.hero.HeroSubClass; import com.shatteredpixel.shatteredpixeldungeon.effects.CellEmitter; import com.shatteredpixel.shatteredpixeldungeon.effects.particles.LeafParticle; import com.shatteredpixel.shatteredpixeldungeon.items.Dewdrop; @@ -91,32 +89,23 @@ public class HighGrass { } } + if (ch instanceof Hero) { + Hero hero = (Hero) ch; + + //Camouflage + //FIXME doesn't work with sad ghost + if (hero.belongings.armor != null && hero.belongings.armor.hasGlyph(Camouflage.class, hero)) { + Buff.affect(hero, Camouflage.Camo.class).set(3 + hero.belongings.armor.level()); + } + } + } freezeTrample = false; GameScene.updateMap( pos ); - - int leaves = 4; - - if (ch instanceof Hero) { - Hero hero = (Hero)ch; - - // Barkskin - if (hero.subClass == HeroSubClass.WARDEN) { - Buff.affect(ch, Barkskin.class).set(ch.HT / 3, 1); - leaves += 4; - } - - //Camouflage - //FIXME doesn't work with sad ghost - if (hero.belongings.armor != null && hero.belongings.armor.hasGlyph(Camouflage.class, hero)){ - Buff.affect(hero, Camouflage.Camo.class).set(3 + hero.belongings.armor.level()); - leaves += 4; - } - } - CellEmitter.get( pos ).burst( LeafParticle.LEVEL_SPECIFIC, leaves ); + CellEmitter.get( pos ).burst( LeafParticle.LEVEL_SPECIFIC, 4 ); if (Dungeon.level.heroFOV[pos]) Dungeon.observe(); } } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/plants/Plant.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/plants/Plant.java index 34dfd38d0..17162968d 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/plants/Plant.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/plants/Plant.java @@ -27,24 +27,20 @@ import com.shatteredpixel.shatteredpixeldungeon.Dungeon; import com.shatteredpixel.shatteredpixeldungeon.ShatteredPixelDungeon; import com.shatteredpixel.shatteredpixeldungeon.actors.Actor; import com.shatteredpixel.shatteredpixeldungeon.actors.Char; -import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Barkskin; -import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff; import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero; import com.shatteredpixel.shatteredpixeldungeon.actors.hero.HeroSubClass; import com.shatteredpixel.shatteredpixeldungeon.effects.CellEmitter; import com.shatteredpixel.shatteredpixeldungeon.effects.particles.LeafParticle; -import com.shatteredpixel.shatteredpixeldungeon.items.Dewdrop; -import com.shatteredpixel.shatteredpixeldungeon.items.Generator; import com.shatteredpixel.shatteredpixeldungeon.items.Item; -import com.shatteredpixel.shatteredpixeldungeon.items.artifacts.SandalsOfNature; import com.shatteredpixel.shatteredpixeldungeon.levels.Level; import com.shatteredpixel.shatteredpixeldungeon.levels.Terrain; import com.shatteredpixel.shatteredpixeldungeon.messages.Messages; +import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene; import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet; import com.watabou.noosa.audio.Sample; import com.watabou.utils.Bundlable; import com.watabou.utils.Bundle; -import com.watabou.utils.Random; +import com.watabou.utils.PathFinder; import java.util.ArrayList; @@ -61,9 +57,6 @@ public abstract class Plant implements Bundlable { if (ch instanceof Hero){ ((Hero) ch).interrupt(); - if (((Hero)ch).subClass == HeroSubClass.WARDEN) { - Buff.affect(ch, Barkskin.class).set(ch.HT / 3, 1); - } } wither(); @@ -79,21 +72,6 @@ public abstract class Plant implements Bundlable { CellEmitter.get( pos ).burst( LeafParticle.GENERAL, 6 ); } - if (Dungeon.hero.subClass == HeroSubClass.WARDEN) { - - int naturalismLevel = 0; - SandalsOfNature.Naturalism naturalism = Dungeon.hero.buff( SandalsOfNature.Naturalism.class ); - if (naturalism != null) { - naturalismLevel = naturalism.itemLevel()+1; - } - - if (Random.Int( 5 - (naturalismLevel/2) ) == 0) { - Dungeon.level.drop(Generator.random(Generator.Category.SEED), pos).sprite.drop(); - } - if (Random.Int( 5 - naturalismLevel ) == 0) { - Dungeon.level.drop( new Dewdrop(), pos ).sprite.drop(); - } - } } private static final String POS = "pos"; @@ -141,6 +119,17 @@ public abstract class Plant implements Bundlable { super.onThrow( cell ); } else { Dungeon.level.plant( this, cell ); + if (Dungeon.hero.subClass == HeroSubClass.WARDEN) { + for (int i : PathFinder.NEIGHBOURS8) { + int c = Dungeon.level.map[cell + i]; + if ( c == Terrain.EMPTY || c == Terrain.EMPTY_DECO + || c == Terrain.EMBERS || c == Terrain.GRASS){ + Level.set(cell + i, Terrain.FURROWED_GRASS); + GameScene.updateMap(cell + i); + CellEmitter.get( cell + i ).burst( LeafParticle.LEVEL_SPECIFIC, 4 ); + } + } + } } } diff --git a/core/src/main/resources/com/shatteredpixel/shatteredpixeldungeon/messages/actors/actors.properties b/core/src/main/resources/com/shatteredpixel/shatteredpixeldungeon/messages/actors/actors.properties index afa69e104..875aded59 100644 --- a/core/src/main/resources/com/shatteredpixel/shatteredpixeldungeon/messages/actors/actors.properties +++ b/core/src/main/resources/com/shatteredpixel/shatteredpixeldungeon/messages/actors/actors.properties @@ -333,9 +333,9 @@ actors.hero.herosubclass.assassin_desc=While invisible the _Assassin_ prepares a actors.hero.herosubclass.freerunner=freerunner actors.hero.herosubclass.freerunner_desc=The _Freerunner_ builds momentum as he runs. Momentum increases his movement speed and evasion, but it quickly fades when he isn't moving. actors.hero.herosubclass.sniper=sniper -actors.hero.herosubclass.sniper_desc=The _Sniper_ is able to detect weak points in an enemy's armor, effectively ignoring it when using a thrown weapon. +actors.hero.herosubclass.sniper_desc=The _Sniper_ is a master of ranged combat, with increased vision and bonus accuracy and armor piercing based on attack distance. After striking with a thrown weapon, she can follow up with a special attack from her bow. actors.hero.herosubclass.warden=warden -actors.hero.herosubclass.warden_desc=Having a strong connection with forces of nature allows the _Warden_ to gain additional health from dew, armor from trampling grass, and seeds and dew from plants. +actors.hero.herosubclass.warden_desc=The _Warden_ has a strong connection to nature which allows her to see through tall grass and command furrowed grass to sprout around plants she grows. Plants she tramples will also give bonus effects, tipped darts will last longer, and grass will give her an armor boost when she stands in it.