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 7854e9cc8..6d616cafc 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/Char.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/Char.java @@ -281,14 +281,6 @@ public abstract class Char extends Actor { return true; } - //TODO: consider revisiting this and shaking in more cases. - float shake = 0f; - if (enemy == Dungeon.hero) - shake = effectiveDamage / (enemy.HT / 4); - - if (shake > 1f) - Camera.main.shake( GameMath.gate( 1, shake, 5), 0.3f ); - enemy.damage( effectiveDamage, this ); if (buff(FireImbue.class) != null) 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 20f8f1c88..ed28e1f10 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 @@ -1045,7 +1045,18 @@ public class Hero extends Char { dmg -= AntiMagic.drRoll(belongings.armor.buffedLvl()); } + int preHP = HP + shielding(); super.damage( dmg, src ); + int effectiveDamage = preHP - (HP + shielding()); + + //flash red when hit for 1/4 of your remaining HP or higher. + // Intensity increases the more injured the player is. + if (preHP > 0 && effectiveDamage >= preHP/4f){ + //08%/11%/16%/33% intensity at + //75%/50%/25%/00% health + float divisor = 3 + 12*((HP + shielding()) / (float)(HT + shielding())); + GameScene.flash( (int)(0xFF/divisor) << 16 ); + } } public void checkVisibleMobs() { diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/NewDM300.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/NewDM300.java index c7aa70498..b4328663a 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/NewDM300.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/NewDM300.java @@ -63,6 +63,7 @@ import com.shatteredpixel.shatteredpixeldungeon.utils.GLog; import com.watabou.noosa.Camera; import com.watabou.noosa.audio.Sample; import com.watabou.utils.Bundle; +import com.watabou.utils.GameMath; import com.watabou.utils.PathFinder; import com.watabou.utils.Random; import com.watabou.utils.RectF; @@ -393,10 +394,11 @@ public class NewDM300 extends Mob { pos++; continue; } - if (!Dungeon.level.solid[pos] && pos != safeCell && Random.Int(Dungeon.level.distance(rockCenter, pos)) == 0) { - GameScene.add(Blob.seed(pos, 1, FallingRocks.class)); - } //add rock cell to pos, if it is not solid, and isn't the safecell + if (!Dungeon.level.solid[pos] && pos != safeCell && Random.Int(Dungeon.level.distance(rockCenter, pos)) == 0) { + //don't want to overly punish players with slow move or attack speed + GameScene.add(Blob.seed(pos, (int)GameMath.gate(TICK, (float)Math.ceil(target.cooldown()), 3*TICK), FallingRocks.class)); + } pos++; } } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/RipperDemon.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/RipperDemon.java index f26642d89..f38388a19 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/RipperDemon.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/RipperDemon.java @@ -37,6 +37,7 @@ import com.shatteredpixel.shatteredpixeldungeon.utils.GLog; import com.watabou.noosa.audio.Sample; import com.watabou.utils.Bundle; import com.watabou.utils.Callback; +import com.watabou.utils.GameMath; import com.watabou.utils.PathFinder; import com.watabou.utils.Random; @@ -209,7 +210,8 @@ public class RipperDemon extends Mob { if (b.collisionPos == targetPos){ //get ready to leap leapPos = targetPos; - spend(TICK); + //don't want to overly punish players with slow move or attack speed + spend(GameMath.gate(TICK, enemy.cooldown(), 3*TICK)); if (Dungeon.level.heroFOV[pos]){ GLog.w(Messages.get(RipperDemon.this, "leap")); sprite.parent.addToBack(new TargetedCell(leapPos, 0xFF0000)); diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/YogDzewa.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/YogDzewa.java index d0f44bfb9..e17acfbca 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/YogDzewa.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/YogDzewa.java @@ -51,6 +51,7 @@ import com.shatteredpixel.shatteredpixeldungeon.tiles.DungeonTilemap; import com.shatteredpixel.shatteredpixeldungeon.ui.BossHealthBar; import com.shatteredpixel.shatteredpixeldungeon.utils.GLog; import com.watabou.utils.Bundle; +import com.watabou.utils.GameMath; import com.watabou.utils.PathFinder; import com.watabou.utils.Random; import com.watabou.utils.Reflection; @@ -87,10 +88,12 @@ public class YogDzewa extends Mob { private ArrayList fistSummons = new ArrayList<>(); { - fistSummons.add(Random.Int(2) == 0 ? YogFist.Burning.class : YogFist.Soiled.class); - fistSummons.add(Random.Int(2) == 0 ? YogFist.Rotting.class : YogFist.Rusted.class); - fistSummons.add(Random.Int(2) == 0 ? YogFist.Bright.class : YogFist.Dark.class); - Random.shuffle(fistSummons); + Random.pushGenerator(Dungeon.seedCurDepth()); + fistSummons.add(Random.Int(2) == 0 ? YogFist.Burning.class : YogFist.Soiled.class); + fistSummons.add(Random.Int(2) == 0 ? YogFist.Rotting.class : YogFist.Rusted.class); + fistSummons.add(Random.Int(2) == 0 ? YogFist.Bright.class : YogFist.Dark.class); + Random.shuffle(fistSummons); + Random.popGenerator(); } private static final int SUMMON_DECK_SIZE = 4; @@ -130,38 +133,41 @@ public class YogDzewa extends Mob { boolean terrainAffected = false; HashSet affected = new HashSet<>(); - for (int i : targetedCells){ - Ballistica b = new Ballistica(pos, i, Ballistica.WONT_STOP); - //shoot beams - sprite.parent.add(new Beam.DeathRay(sprite.center(), DungeonTilemap.raisedTileCenterToWorld(b.collisionPos))); - for (int p : b.path){ - Char ch = Actor.findChar(p); - if (ch != null && ch.alignment != alignment){ - affected.add(ch); - } - if (Dungeon.level.flamable[p]){ - Dungeon.level.destroy( p ); - GameScene.updateMap( p ); - terrainAffected = true; + //delay fire on a rooted hero + if (!Dungeon.hero.rooted) { + for (int i : targetedCells) { + Ballistica b = new Ballistica(pos, i, Ballistica.WONT_STOP); + //shoot beams + sprite.parent.add(new Beam.DeathRay(sprite.center(), DungeonTilemap.raisedTileCenterToWorld(b.collisionPos))); + for (int p : b.path) { + Char ch = Actor.findChar(p); + if (ch != null && ch.alignment != alignment) { + affected.add(ch); + } + if (Dungeon.level.flamable[p]) { + Dungeon.level.destroy(p); + GameScene.updateMap(p); + terrainAffected = true; + } } } - } - if (terrainAffected){ - Dungeon.observe(); - } - for (Char ch : affected){ - ch.damage(Random.NormalIntRange(20, 40), new Eye.DeathGaze()); + if (terrainAffected) { + Dungeon.observe(); + } + for (Char ch : affected) { + ch.damage(Random.NormalIntRange(20, 40), new Eye.DeathGaze()); - if (Dungeon.level.heroFOV[pos]) { - ch.sprite.flash(); - CellEmitter.center( pos ).burst( PurpleParticle.BURST, Random.IntRange( 1, 2 ) ); - } - if (!ch.isAlive() && ch == Dungeon.hero) { - Dungeon.fail( getClass() ); - GLog.n( Messages.get(Char.class, "kill", name()) ); + if (Dungeon.level.heroFOV[pos]) { + ch.sprite.flash(); + CellEmitter.center(pos).burst(PurpleParticle.BURST, Random.IntRange(1, 2)); + } + if (!ch.isAlive() && ch == Dungeon.hero) { + Dungeon.fail(getClass()); + GLog.n(Messages.get(Char.class, "kill", name())); + } } + targetedCells.clear(); } - targetedCells.clear(); if (abilityCooldown <= 0){ @@ -200,18 +206,15 @@ public class YogDzewa extends Mob { } } - //wait extra time to let a crippled/rooted hero evade - if (Dungeon.hero.buff(Cripple.class) != null){ - spend(TICK); - } else if (Dungeon.hero.buff(Roots.class) != null){ - spend(Dungeon.hero.buff(Roots.class).cooldown()); - } - + //don't want to overly punish players with slow move or attack speed + spend(GameMath.gate(TICK, Dungeon.hero.cooldown(), 3*TICK)); Dungeon.hero.interrupt(); abilityCooldown += Random.NormalFloat(MIN_ABILITY_CD, MAX_ABILITY_CD); abilityCooldown -= phase; + } else { + spend(TICK); } while (summonCooldown <= 0){ @@ -257,7 +260,6 @@ public class YogDzewa extends Mob { summonCooldown = 3; } - spend(TICK); return true; } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/bags/VelvetPouch.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/bags/VelvetPouch.java index ca45af8c6..c955e8c66 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/bags/VelvetPouch.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/bags/VelvetPouch.java @@ -22,6 +22,8 @@ package com.shatteredpixel.shatteredpixeldungeon.items.bags; import com.shatteredpixel.shatteredpixeldungeon.items.Item; +import com.shatteredpixel.shatteredpixeldungeon.items.quest.GooBlob; +import com.shatteredpixel.shatteredpixeldungeon.items.quest.MetalShard; import com.shatteredpixel.shatteredpixeldungeon.items.stones.Runestone; import com.shatteredpixel.shatteredpixeldungeon.plants.Plant; import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet; @@ -36,7 +38,8 @@ public class VelvetPouch extends Bag { @Override public boolean grab( Item item ) { - return item instanceof Plant.Seed || item instanceof Runestone; + return item instanceof Plant.Seed || item instanceof Runestone + || item instanceof GooBlob || item instanceof MetalShard; } @Override diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/wands/WandOfDisintegration.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/wands/WandOfDisintegration.java index c488c1e7e..b4b954391 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/wands/WandOfDisintegration.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/wands/WandOfDisintegration.java @@ -24,6 +24,8 @@ package com.shatteredpixel.shatteredpixeldungeon.items.wands; import com.shatteredpixel.shatteredpixeldungeon.Dungeon; import com.shatteredpixel.shatteredpixeldungeon.actors.Actor; import com.shatteredpixel.shatteredpixeldungeon.actors.Char; +import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.Blob; +import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.Web; import com.shatteredpixel.shatteredpixeldungeon.effects.Beam; import com.shatteredpixel.shatteredpixeldungeon.effects.CellEmitter; import com.shatteredpixel.shatteredpixeldungeon.effects.particles.PurpleParticle; @@ -65,6 +67,8 @@ public class WandOfDisintegration extends DamageWand { ArrayList chars = new ArrayList<>(); + Blob web = Dungeon.level.blobs.get(Web.class); + int terrainPassed = 2, terrainBonus = 0; for (int c : beam.subPath(1, maxDistance)) { @@ -79,6 +83,11 @@ public class WandOfDisintegration extends DamageWand { chars.add( ch ); } + if (Dungeon.level.solid[c]) { + terrainPassed++; + if (web != null) web.clear(c); + } + if (Dungeon.level.flamable[c]) { Dungeon.level.destroy( c ); @@ -86,9 +95,6 @@ public class WandOfDisintegration extends DamageWand { terrainAffected = true; } - - if (Dungeon.level.solid[c]) - terrainPassed++; CellEmitter.center( c ).burst( PurpleParticle.BURST, Random.IntRange( 1, 2 ) ); }