diff --git a/core/src/main/assets/messages/actors/actors.properties b/core/src/main/assets/messages/actors/actors.properties index b784eec6f..a982e9403 100644 --- a/core/src/main/assets/messages/actors/actors.properties +++ b/core/src/main/assets/messages/actors/actors.properties @@ -351,6 +351,11 @@ actors.hero.talent.protective_shadows.desc=_+1:_ The Rogue gains one shielding _ actors.hero.talent.mystical_meal.title=mystical meal actors.hero.talent.mystical_meal.desc=_+1:_ Eating food takes the Rogue 1 turn and grants him _3 turns of artifact recharging_.\n\n_+2:_ Eating food takes the rogue 1 turn and grants him _5 turns of artifact recharging_.\n\nThis talent cannot be used to let the horn of plenty recharge itself. +actors.hero.talent.silent_steps.title=silent steps +actors.hero.talent.silent_steps.desc=_+1:_ The Rogue will not wake sleeping enemies while he is _3 or more tiles away from them_.\n\n_+2:_ The Rogue will not wake sleeping enemies while he is _not adjacent to them_. +actors.hero.talent.rogues_foresight.title=rogue's foresight +actors.hero.talent.rogues_foresight.desc=_+1:_ When he first enters a level with a secret room, the Rogue has a _50% chance to notice_ that the level contains a secret.\n\n_+1:_ When he first enters a level with a secret room, the Rogue has a _75% chance to notice_ that the level contains a secret. + actors.hero.talent.natures_bounty.title=nature's bounty actors.hero.talent.natures_bounty.desc=_+1:_ The Huntress can find _4 berries_ hidden in tall grass as she explores the earlier stages of the dungeon.\n\n_+2:_ The Huntress can find _6 berries_ hidden in tall grass as she explores the earlier stages of the dungeon. actors.hero.talent.survivalists_intuition.title=survivalist's intuition @@ -362,6 +367,11 @@ actors.hero.talent.natures_aid.desc=_+1:_ The Huntress gains 2 armor of barkskin actors.hero.talent.invigorating_meal.title=invigorating meal actors.hero.talent.invigorating_meal.desc=_+1:_ Eating food takes the Huntress 1 turn (berries are eaten instantly) and grants her _2 turns of haste_.\n\n_+1:_ Eating food takes the Huntress 1 turn (berries are eaten instantly) and grants her _3 turns of haste_. +actors.hero.talent.durable_projectiles.title=durable projectiles +actors.hero.talent.durable_projectiles.desc=_+1:_ Thrown weapons have _+50% durability_ when used by the huntress.\n\n_+2:_ Thrown weapons have _+75% durability_ when used by the huntress. +actors.hero.talent.heightened_senses.title=heightened senses +actors.hero.talent.heightened_senses.desc=_+1:_ The Huntress gains mind vision on any enemy within _2 tiles of her position_.\n\n_+2:_ The Huntress gains mind vision on any enemy within _3 tiles of her position_. + actors.hero.hero.name=you actors.hero.hero.leave=You can't leave yet, the rest of the dungeon awaits below! actors.hero.hero.level_up=Level up! diff --git a/core/src/main/assets/messages/scenes/scenes.properties b/core/src/main/assets/messages/scenes/scenes.properties index 7bc6f74a5..7380f39e3 100644 --- a/core/src/main/assets/messages/scenes/scenes.properties +++ b/core/src/main/assets/messages/scenes/scenes.properties @@ -26,6 +26,7 @@ scenes.gamescene.spawner_warn=You feel that there's a source of demonic energy a scenes.gamescene.spawner_warn_final=You can feel demonic energy radiating here from the previous floors! scenes.gamescene.warp=The walls warp and shift around you! scenes.gamescene.return=You return to floor %d of the dungeon. +scenes.gamescene.secret_hint=You're certain that there's a secret room somewhere on this floor. scenes.gamescene.chasm=Your steps echo across the dungeon. scenes.gamescene.water=You hear water splashing around you. scenes.gamescene.grass=The smell of vegetation is thick in the air. diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/Talent.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/Talent.java index 4c7a23002..866a580f3 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/Talent.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/Talent.java @@ -80,8 +80,8 @@ public enum Talent { PROTECTIVE_SHADOWS(35), MYSTICAL_MEAL(36), TEST_ROGUE_T2_2(37), - TEST_ROGUE_T2_3(38), - TEST_ROGUE_T2_4(39), + SILENT_STEPS(38), + ROGUES_FORESIGHT(39), TEST_ROGUE_T2_5(40), NATURES_BOUNTY(48), @@ -90,8 +90,8 @@ public enum Talent { NATURES_AID(51), INVIGORATING_MEAL(52), TEST_HUNTRESS_T2_2(53), - TEST_HUNTRESS_T2_3(54), - TEST_HUNTRESS_T2_4(55), + DURABLE_PROJECTILES(54), + HEIGHTENED_SENSES(55), TEST_HUNTRESS_T2_5(56); int icon; @@ -306,10 +306,10 @@ public enum Talent { Collections.addAll(tierTalents, ENERGIZING_MEAL, ENERGIZING_UPGRADE, TEST_MAGE_T2_3, TEST_MAGE_T2_4, TEST_MAGE_T2_5); break; case ROGUE: - Collections.addAll(tierTalents, MYSTICAL_MEAL, TEST_ROGUE_T2_2, TEST_ROGUE_T2_3, TEST_ROGUE_T2_4, TEST_ROGUE_T2_5); + Collections.addAll(tierTalents, MYSTICAL_MEAL, TEST_ROGUE_T2_2, SILENT_STEPS, ROGUES_FORESIGHT, TEST_ROGUE_T2_5); break; case HUNTRESS: - Collections.addAll(tierTalents, INVIGORATING_MEAL, TEST_HUNTRESS_T2_2, TEST_HUNTRESS_T2_3, TEST_HUNTRESS_T2_4, TEST_HUNTRESS_T2_5); + Collections.addAll(tierTalents, INVIGORATING_MEAL, TEST_HUNTRESS_T2_2, DURABLE_PROJECTILES, HEIGHTENED_SENSES, TEST_HUNTRESS_T2_5); break; } for (Talent talent : tierTalents){ diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/Mob.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/Mob.java index c52da9548..3ea208033 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/Mob.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/Mob.java @@ -40,6 +40,7 @@ import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Sleep; import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.SoulMark; import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Terror; import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero; +import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Talent; import com.shatteredpixel.shatteredpixeldungeon.effects.Speck; import com.shatteredpixel.shatteredpixeldungeon.effects.Surprise; import com.shatteredpixel.shatteredpixeldungeon.effects.Wound; @@ -789,33 +790,43 @@ public abstract class Mob extends Char { @Override public boolean act( boolean enemyInFOV, boolean justAlerted ) { - if (enemyInFOV && Random.Float( distance( enemy ) + enemy.stealth() ) < 1) { - enemySeen = true; + if (enemyInFOV) { - notice(); - state = HUNTING; - target = enemy.pos; + float enemyStealth = enemy.stealth(); - if (alignment == Alignment.ENEMY && Dungeon.isChallenged( Challenges.SWARM_INTELLIGENCE )) { - for (Mob mob : Dungeon.level.mobs) { - if (mob.paralysed <= 0 - && Dungeon.level.distance(pos, mob.pos) <= 8 //TODO base on pathfinder distance instead? - && mob.state != mob.HUNTING) { - mob.beckon( target ); - } + if (enemy instanceof Hero && ((Hero) enemy).hasTalent(Talent.SILENT_STEPS)){ + if (Dungeon.level.distance(pos, enemy.pos) >= 4 - ((Hero) enemy).pointsInTalent(Talent.SILENT_STEPS)) { + enemyStealth = Float.POSITIVE_INFINITY; } } - spend( TIME_TO_WAKE_UP ); + if (Random.Float( distance( enemy ) + enemyStealth ) < 1) { + enemySeen = true; - } else { + notice(); + state = HUNTING; + target = enemy.pos; - enemySeen = false; + if (alignment == Alignment.ENEMY && Dungeon.isChallenged(Challenges.SWARM_INTELLIGENCE)) { + for (Mob mob : Dungeon.level.mobs) { + if (mob.paralysed <= 0 + && Dungeon.level.distance(pos, mob.pos) <= 8 //TODO base on pathfinder distance instead? + && mob.state != mob.HUNTING) { + mob.beckon(target); + } + } + } - spend( TICK ); + spend(TIME_TO_WAKE_UP); + return true; + } } + + enemySeen = false; + spend( TICK ); + return true; } } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/weapon/missiles/MissileWeapon.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/weapon/missiles/MissileWeapon.java index 4c0b34ec3..70904481d 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/weapon/missiles/MissileWeapon.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/weapon/missiles/MissileWeapon.java @@ -28,7 +28,7 @@ import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff; import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Corruption; import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.PinCushion; import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero; -import com.shatteredpixel.shatteredpixeldungeon.actors.hero.HeroClass; +import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Talent; import com.shatteredpixel.shatteredpixeldungeon.items.Item; import com.shatteredpixel.shatteredpixeldungeon.items.bags.Bag; import com.shatteredpixel.shatteredpixeldungeon.items.bags.MagicalHolster; @@ -220,9 +220,13 @@ abstract public class MissileWeapon extends Weapon { protected float durabilityPerUse(){ float usages = baseUses * (float)(Math.pow(3, level())); - //TODO this is becoming a talent - if (Dungeon.hero.heroClass == HeroClass.HUNTRESS) usages *= 1.5f; - if (holster) usages *= MagicalHolster.HOLSTER_DURABILITY_FACTOR; + //+50%/75% durability + if (Dungeon.hero.hasTalent(Talent.DURABLE_PROJECTILES)){ + usages *= 1.25f + (0.25f*Dungeon.hero.pointsInTalent(Talent.DURABLE_PROJECTILES)); + } + if (holster) { + usages *= MagicalHolster.HOLSTER_DURABILITY_FACTOR; + } usages *= RingOfSharpshooting.durabilityMultiplier( Dungeon.hero ); diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/weapon/missiles/darts/TippedDart.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/weapon/missiles/darts/TippedDart.java index ae156c69b..f3dfe9a96 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/weapon/missiles/darts/TippedDart.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/weapon/missiles/darts/TippedDart.java @@ -56,8 +56,8 @@ public abstract class TippedDart extends Dart { { tier = 2; - //so that slightly more than 1.5x durability is needed for 2 uses - baseUses = 0.65f; + //so that 1.5x durability is needed for 2 uses + baseUses = 0.67f; } private static final String AC_CLEAN = "CLEAN"; diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/Level.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/Level.java index fba0f2123..314fda1bc 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/Level.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/Level.java @@ -41,8 +41,8 @@ import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.MagicalSight; import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.MindVision; import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Shadows; 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.actors.hero.Talent; import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Bestiary; import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mimic; import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob; @@ -1118,15 +1118,12 @@ public abstract class Level implements Bundlable { } } - //TODO this is becoming a talent - } else if (((Hero)c).heroClass == HeroClass.HUNTRESS) { + } else if (((Hero) c).hasTalent(Talent.HEIGHTENED_SENSES)) { for (Mob mob : mobs) { int p = mob.pos; - if (distance( c.pos, p) == 2) { - - if (!fieldOfView[p]){ - Dungeon.hero.mindVisionEnemies.add(mob); - } + if (!fieldOfView[p] + && distance(c.pos, p) <= 1+((Hero) c).pointsInTalent(Talent.HEIGHTENED_SENSES)) { + Dungeon.hero.mindVisionEnemies.add(mob); } } } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/scenes/GameScene.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/scenes/GameScene.java index 1968c4841..5b09fafd1 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/scenes/GameScene.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/scenes/GameScene.java @@ -31,6 +31,7 @@ import com.shatteredpixel.shatteredpixeldungeon.actors.Actor; import com.shatteredpixel.shatteredpixeldungeon.actors.Char; import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.Blob; import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.ChampionEnemy; +import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Talent; import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.DemonSpawner; import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob; import com.shatteredpixel.shatteredpixeldungeon.effects.BannerSprites; @@ -52,6 +53,10 @@ import com.shatteredpixel.shatteredpixeldungeon.items.bags.VelvetPouch; import com.shatteredpixel.shatteredpixeldungeon.items.potions.Potion; import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfTeleportation; import com.shatteredpixel.shatteredpixeldungeon.journal.Journal; +import com.shatteredpixel.shatteredpixeldungeon.levels.Level; +import com.shatteredpixel.shatteredpixeldungeon.levels.RegularLevel; +import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.Room; +import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.secret.SecretRoom; import com.shatteredpixel.shatteredpixeldungeon.levels.traps.Trap; import com.shatteredpixel.shatteredpixeldungeon.messages.Messages; import com.shatteredpixel.shatteredpixeldungeon.plants.Plant; @@ -109,6 +114,7 @@ import com.watabou.noosa.audio.Music; import com.watabou.noosa.audio.Sample; import com.watabou.noosa.particles.Emitter; import com.watabou.utils.GameMath; +import com.watabou.utils.Random; import java.io.IOException; import java.util.ArrayList; @@ -462,6 +468,18 @@ public class GameScene extends PixelScene { } } } + + if (Dungeon.hero.hasTalent(Talent.ROGUES_FORESIGHT) + && Dungeon.level instanceof RegularLevel){ + int reqSecrets = Dungeon.level.feeling == Level.Feeling.SECRETS ? 2 : 1; + for (Room r : ((RegularLevel) Dungeon.level).rooms()){ + if (r instanceof SecretRoom) reqSecrets--; + } + //50%/75% chance + if (reqSecrets <= 0 && Random.Int(4) <= Dungeon.hero.pointsInTalent(Talent.ROGUES_FORESIGHT)){ + GLog.p(Messages.get(this, "secret_hint")); + } + } } else if (InterlevelScene.mode == InterlevelScene.Mode.RESET) { GLog.h(Messages.get(this, "warp"));