From 649c41bcb4be42b70dc9e0beccac547a81639e7c Mon Sep 17 00:00:00 2001 From: Evan Debenham Date: Wed, 11 Dec 2019 21:48:04 -0500 Subject: [PATCH] v0.8.0: Implement a new character property: 'Large' Large characters cannot move into small spaces. They are equivalent to a 2x2 enemy in most cases, but without nearly as much dev work. --- .../shatteredpixeldungeon/Dungeon.java | 12 +++++++ .../shatteredpixeldungeon/actors/Char.java | 10 ++++++ .../actors/buffs/Combo.java | 3 +- .../actors/mobs/Mob.java | 10 ++++-- .../actors/mobs/NewTengu.java | 2 +- .../actors/mobs/Thief.java | 2 +- .../actors/mobs/npcs/Ghost.java | 6 ++-- .../actors/mobs/npcs/Imp.java | 2 +- .../items/armor/curses/Multiplicity.java | 15 ++++++-- .../items/artifacts/EtherealChains.java | 4 ++- .../items/artifacts/LloydsBeacon.java | 2 +- .../items/potions/PotionOfMindVision.java | 2 +- .../items/scrolls/ScrollOfTeleportation.java | 2 +- .../items/spells/PhaseShift.java | 2 +- .../items/wands/WandOfBlastWave.java | 22 ++++++++++-- .../items/weapon/curses/Displacing.java | 2 +- .../weapon/missiles/darts/DisplacingDart.java | 1 + .../levels/CavesBossLevel.java | 6 ++-- .../levels/CityBossLevel.java | 6 ++-- .../levels/DeadEndLevel.java | 3 +- .../levels/HallsBossLevel.java | 6 ++-- .../levels/LastLevel.java | 7 ++-- .../levels/LastShopLevel.java | 7 ++-- .../shatteredpixeldungeon/levels/Level.java | 36 ++++++++++++++----- .../levels/NewPrisonBossLevel.java | 8 +++-- .../levels/OldPrisonBossLevel.java | 8 +++-- .../levels/RegularLevel.java | 4 ++- .../levels/SewerBossLevel.java | 8 +++-- .../levels/traps/DisarmingTrap.java | 4 +-- .../levels/traps/DistortionTrap.java | 4 +++ .../levels/traps/GuardianTrap.java | 2 +- .../levels/traps/SummoningTrap.java | 4 +++ .../levels/traps/TeleportationTrap.java | 4 +-- .../levels/traps/WarpingTrap.java | 4 +-- .../plants/Fadeleaf.java | 2 +- .../scenes/GameScene.java | 4 +-- 36 files changed, 166 insertions(+), 60 deletions(-) diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/Dungeon.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/Dungeon.java index 396d69d0a..a35e0290d 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/Dungeon.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/Dungeon.java @@ -805,6 +805,10 @@ public class Dungeon { System.arraycopy( pass, 0, passable, 0, Dungeon.level.length() ); } + if (Char.hasProp(ch, Char.Property.LARGE)){ + BArray.and( pass, Dungeon.level.openSpace, passable ); + } + for (Char c : Actor.chars()) { if (visible[c.pos]) { passable[c.pos] = false; @@ -827,6 +831,10 @@ public class Dungeon { } else { System.arraycopy( pass, 0, passable, 0, Dungeon.level.length() ); } + + if (Char.hasProp(ch, Char.Property.LARGE)){ + BArray.and( pass, Dungeon.level.openSpace, passable ); + } for (Char c : Actor.chars()) { if (visible[c.pos]) { @@ -846,6 +854,10 @@ public class Dungeon { } else { System.arraycopy( pass, 0, passable, 0, Dungeon.level.length() ); } + + if (Char.hasProp(ch, Char.Property.LARGE)){ + BArray.and( pass, Dungeon.level.openSpace, passable ); + } for (Char c : Actor.chars()) { if (visible[c.pos]) { 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 1cf8fc8e2..11dbffebd 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/Char.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/Char.java @@ -149,6 +149,10 @@ public abstract class Char extends Actor { if (!Dungeon.level.passable[pos] && !Dungeon.hero.flying){ return true; } + + if (properties.contains(Property.LARGE) && !Dungeon.level.openSpace[Dungeon.hero.pos]){ + return true; + } int curPos = pos; @@ -697,6 +701,7 @@ public abstract class Char extends Actor { new HashSet( Arrays.asList(Ooze.class))), ELECTRIC ( new HashSet( Arrays.asList(WandOfLightning.class, Shocking.class, Potential.class, Electricity.class, ShockingDart.class, Elemental.Shock.class )), new HashSet()), + LARGE, IMMOVABLE; private HashSet resistances; @@ -718,5 +723,10 @@ public abstract class Char extends Actor { public HashSet immunities(){ return new HashSet<>(immunities); } + + } + + public static boolean hasProp( Char ch, Property p){ + return (ch != null && ch.properties.contains(p)); } } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/buffs/Combo.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/buffs/Combo.java index 51e4e2d39..9060a664b 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/buffs/Combo.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/buffs/Combo.java @@ -263,7 +263,8 @@ public class Combo extends Buff implements ActionIndicator.Action { if (enemy.pos - target.pos == ofs) { int newPos = enemy.pos + ofs; if ((Dungeon.level.passable[newPos] || Dungeon.level.avoid[newPos]) - && Actor.findChar( newPos ) == null) { + && Actor.findChar( newPos ) == null + && (!Char.hasProp(enemy, Char.Property.LARGE) || Dungeon.level.openSpace[newPos])) { Actor.addDelayed( new Pushing( enemy, enemy.pos, newPos ), -1 ); 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 0c15ed638..2dc08a897 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 @@ -339,8 +339,9 @@ public abstract class Mob extends Char { path = null; - if (Actor.findChar( target ) == null && - (Dungeon.level.passable[target] || (flying && Dungeon.level.avoid[target]))) { + if (Actor.findChar( target ) == null + && (Dungeon.level.passable[target] || (flying && Dungeon.level.avoid[target])) + && (!Char.hasProp(this, Char.Property.LARGE) || Dungeon.level.openSpace[target])) { step = target; } @@ -397,7 +398,10 @@ public abstract class Mob extends Char { int lookAhead = (int)GameMath.gate(1, path.size()-1, 4); for (int i = 0; i < lookAhead; i++) { int cell = path.get(i); - if (!Dungeon.level.passable[cell] || ( fieldOfView[cell] && Actor.findChar(cell) != null)) { + if (!Dungeon.level.passable[cell] + || (!flying && Dungeon.level.avoid[target]) + || (Char.hasProp(this, Char.Property.LARGE) && !Dungeon.level.openSpace[cell]) + || (fieldOfView[cell] && Actor.findChar(cell) != null)) { newPath = true; break; } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/NewTengu.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/NewTengu.java index bc668cfe3..9202caaf3 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/NewTengu.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/NewTengu.java @@ -269,7 +269,7 @@ public class NewTengu extends Mob { } else { Level level = Dungeon.level; - newPos = level.randomRespawnCell(); + newPos = level.randomRespawnCell( this ); if (level.heroFOV[pos]) CellEmitter.get( pos ).burst( Speck.factory( Speck.WOOL ), 6 ); diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/Thief.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/Thief.java index 85714103c..e94cf2a4e 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/Thief.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/Thief.java @@ -209,7 +209,7 @@ public class Thief extends Mob { int count = 32; int newPos; do { - newPos = Dungeon.level.randomRespawnCell(); + newPos = Dungeon.level.randomRespawnCell( Thief.this ); if (count-- <= 0) { break; } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/npcs/Ghost.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/npcs/Ghost.java index 1f709313c..ba0eef336 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/npcs/Ghost.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/npcs/Ghost.java @@ -143,7 +143,7 @@ public class Ghost extends NPC { int newPos = -1; for (int i = 0; i < 10; i++) { - newPos = Dungeon.level.randomRespawnCell(); + newPos = Dungeon.level.randomRespawnCell( this ); if (newPos != -1) { break; } @@ -173,7 +173,7 @@ public class Ghost extends NPC { txt_quest = Messages.get(this, "crab_1", Dungeon.hero.name()); break; } - questBoss.pos = Dungeon.level.randomRespawnCell(); + questBoss.pos = Dungeon.level.randomRespawnCell( this ); if (questBoss.pos != -1) { GameScene.add(questBoss); @@ -273,7 +273,7 @@ public class Ghost extends NPC { Ghost ghost = new Ghost(); do { - ghost.pos = level.randomRespawnCell(); + ghost.pos = level.randomRespawnCell( ghost ); } while (ghost.pos == -1); level.mobs.add( ghost ); diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/npcs/Imp.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/npcs/Imp.java index e46666b29..4cca01cb1 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/npcs/Imp.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/npcs/Imp.java @@ -195,7 +195,7 @@ public class Imp extends NPC { Imp npc = new Imp(); do { - npc.pos = level.randomRespawnCell(); + npc.pos = level.randomRespawnCell( npc ); } while ( npc.pos == -1 || level.heaps.get( npc.pos ) != null || diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/armor/curses/Multiplicity.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/armor/curses/Multiplicity.java index cb9f70333..d190ed900 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/armor/curses/Multiplicity.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/armor/curses/Multiplicity.java @@ -96,8 +96,19 @@ public class Multiplicity extends Armor.Glyph { } if (m != null) { - GameScene.add(m); - ScrollOfTeleportation.appear(m, Random.element(spawnPoints)); + + if (Char.hasProp(m, Char.Property.LARGE)){ + for ( int i : spawnPoints){ + if (!Dungeon.level.openSpace[i]){ + spawnPoints.remove(i); + } + } + } + + if (!spawnPoints.isEmpty()) { + GameScene.add(m); + ScrollOfTeleportation.appear(m, Random.element(spawnPoints)); + } } } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/artifacts/EtherealChains.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/artifacts/EtherealChains.java index 15bc7e8d9..ed6fb8f98 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/artifacts/EtherealChains.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/artifacts/EtherealChains.java @@ -139,7 +139,9 @@ public class EtherealChains extends Artifact { int bestPos = -1; for (int i : chain.subPath(1, chain.dist)){ //prefer to the earliest point on the path - if (!Dungeon.level.solid[i] && Actor.findChar(i) == null){ + if (!Dungeon.level.solid[i] + && Actor.findChar(i) == null + && (!Char.hasProp(enemy, Char.Property.LARGE) || Dungeon.level.openSpace[i])){ bestPos = i; break; } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/artifacts/LloydsBeacon.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/artifacts/LloydsBeacon.java index 71e59be5e..957043fe2 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/artifacts/LloydsBeacon.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/artifacts/LloydsBeacon.java @@ -230,7 +230,7 @@ public class LloydsBeacon extends Artifact { int count = 10; int pos; do { - pos = Dungeon.level.randomRespawnCell(); + pos = Dungeon.level.randomRespawnCell( ch ); if (count-- <= 0) { break; } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/potions/PotionOfMindVision.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/potions/PotionOfMindVision.java index 7b6e68174..b88771102 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/potions/PotionOfMindVision.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/potions/PotionOfMindVision.java @@ -37,7 +37,7 @@ public class PotionOfMindVision extends Potion { @Override public void apply( Hero hero ) { setKnown(); - Buff.affect( hero, MindVision.class, MindVision.DURATION ); + Buff.affect( hero, MindVision.class, MindVision.DURATION*100 ); Dungeon.observe(); if (Dungeon.level.mobs.size() > 0) { diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/scrolls/ScrollOfTeleportation.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/scrolls/ScrollOfTeleportation.java index f83a3b191..96c257e25 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/scrolls/ScrollOfTeleportation.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/scrolls/ScrollOfTeleportation.java @@ -121,7 +121,7 @@ public class ScrollOfTeleportation extends Scroll { int count = 10; int pos; do { - pos = Dungeon.level.randomRespawnCell(); + pos = Dungeon.level.randomRespawnCell( ch ); if (count-- <= 0) { break; } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/spells/PhaseShift.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/spells/PhaseShift.java index ef056b307..2b3adfc84 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/spells/PhaseShift.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/spells/PhaseShift.java @@ -48,7 +48,7 @@ public class PhaseShift extends TargetedSpell { int count = 10; int pos; do { - pos = Dungeon.level.randomRespawnCell(); + pos = Dungeon.level.randomRespawnCell( hero ); if (count-- <= 0) { break; } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/wands/WandOfBlastWave.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/wands/WandOfBlastWave.java index dfbaaca77..c234789dd 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/wands/WandOfBlastWave.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/wands/WandOfBlastWave.java @@ -106,15 +106,30 @@ public class WandOfBlastWave extends DamageWand { } public static void throwChar(final Char ch, final Ballistica trajectory, int power){ + if (ch.properties().contains(Char.Property.BOSS)) { + power /= 2; + } + int dist = Math.min(trajectory.dist, power); - if (ch.properties().contains(Char.Property.BOSS)) - dist /= 2; + boolean collided = dist == trajectory.dist; if (dist == 0 || ch.properties().contains(Char.Property.IMMOVABLE)) return; + //large characters cannot be moved into non-open space + if (Char.hasProp(ch, Char.Property.LARGE)) { + for (int i = 1; i <= dist; i++) { + if (!Dungeon.level.openSpace[trajectory.path.get(i)]){ + dist = i-1; + collided = true; + break; + } + } + } + if (Actor.findChar(trajectory.path.get(dist)) != null){ dist--; + collided = true; } final int newPos = trajectory.path.get(dist); @@ -122,6 +137,7 @@ public class WandOfBlastWave extends DamageWand { if (newPos == ch.pos) return; final int finalDist = dist; + final boolean finalCollided = collided; final int initialpos = ch.pos; Actor.addDelayed(new Pushing(ch, ch.pos, newPos, new Callback() { @@ -132,7 +148,7 @@ public class WandOfBlastWave extends DamageWand { return; } ch.pos = newPos; - if (ch.pos == trajectory.collisionPos && ch.isAlive()) { + if (finalCollided && ch.isAlive()) { ch.damage(Random.NormalIntRange((finalDist + 1) / 2, finalDist), this); Paralysis.prolong(ch, Paralysis.class, Random.NormalIntRange((finalDist + 1) / 2, finalDist)); } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/weapon/curses/Displacing.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/weapon/curses/Displacing.java index 7d8213cdf..d8e330800 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/weapon/curses/Displacing.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/weapon/curses/Displacing.java @@ -41,7 +41,7 @@ public class Displacing extends Weapon.Enchantment { int count = 10; int newPos; do { - newPos = Dungeon.level.randomRespawnCell(); + newPos = Dungeon.level.randomRespawnCell( defender ); if (count-- <= 0) { break; } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/weapon/missiles/darts/DisplacingDart.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/weapon/missiles/darts/DisplacingDart.java index bdc2a50df..ba0047458 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/weapon/missiles/darts/DisplacingDart.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/weapon/missiles/darts/DisplacingDart.java @@ -51,6 +51,7 @@ public class DisplacingDart extends TippedDart { for (int pos = 0; pos < Dungeon.level.length(); pos++){ if (Dungeon.level.heroFOV[pos] && Dungeon.level.passable[pos] + && (!Char.hasProp(defender, Char.Property.LARGE) || Dungeon.level.openSpace[pos]) && Actor.findChar(pos) == null){ int dist = Dungeon.level.distance(attacker.pos, pos); diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/CavesBossLevel.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/CavesBossLevel.java index f375a8b48..87a0d8a93 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/CavesBossLevel.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/CavesBossLevel.java @@ -202,11 +202,13 @@ public class CavesBossLevel extends Level { } @Override - public int randomRespawnCell() { + public int randomRespawnCell( Char ch ) { int cell; do { cell = entrance + PathFinder.NEIGHBOURS8[Random.Int(8)]; - } while (!passable[cell] || Actor.findChar(cell) != null); + } while (!passable[cell] + || (Char.hasProp(ch, Char.Property.LARGE) && !openSpace[cell]) + || Actor.findChar(cell) != null); return cell; } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/CityBossLevel.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/CityBossLevel.java index 1fd6df11e..3b29e77b3 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/CityBossLevel.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/CityBossLevel.java @@ -173,11 +173,13 @@ public class CityBossLevel extends Level { } @Override - public int randomRespawnCell() { + public int randomRespawnCell( Char ch ) { int cell; do { cell = entrance + PathFinder.NEIGHBOURS8[Random.Int(8)]; - } while (!passable[cell] || Actor.findChar(cell) != null); + } while (!passable[cell] + || (Char.hasProp(ch, Char.Property.LARGE) && !openSpace[cell]) + || Actor.findChar(cell) != null); return cell; } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/DeadEndLevel.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/DeadEndLevel.java index 1b7e2899c..8329cc0dc 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/DeadEndLevel.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/DeadEndLevel.java @@ -23,6 +23,7 @@ package com.shatteredpixel.shatteredpixeldungeon.levels; import com.shatteredpixel.shatteredpixeldungeon.Assets; import com.shatteredpixel.shatteredpixeldungeon.actors.Actor; +import com.shatteredpixel.shatteredpixeldungeon.actors.Char; import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob; public class DeadEndLevel extends Level { @@ -89,7 +90,7 @@ public class DeadEndLevel extends Level { } @Override - public int randomRespawnCell() { + public int randomRespawnCell( Char ch ) { return entrance-width(); } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/HallsBossLevel.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/HallsBossLevel.java index 129cd9591..b6c1f6808 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/HallsBossLevel.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/HallsBossLevel.java @@ -162,12 +162,14 @@ public class HallsBossLevel extends Level { } @Override - public int randomRespawnCell() { + public int randomRespawnCell( Char ch ) { int pos = entrance == -1 ? stairs : entrance; int cell; do { cell = pos + PathFinder.NEIGHBOURS8[Random.Int(8)]; - } while (!passable[cell] || Actor.findChar(cell) != null); + } while (!passable[cell] + || (Char.hasProp(ch, Char.Property.LARGE) && !openSpace[cell]) + || Actor.findChar(cell) != null); return cell; } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/LastLevel.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/LastLevel.java index fda9c246e..32bc36096 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/LastLevel.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/LastLevel.java @@ -23,6 +23,7 @@ package com.shatteredpixel.shatteredpixeldungeon.levels; import com.shatteredpixel.shatteredpixeldungeon.Assets; import com.shatteredpixel.shatteredpixeldungeon.actors.Actor; +import com.shatteredpixel.shatteredpixeldungeon.actors.Char; import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob; import com.shatteredpixel.shatteredpixeldungeon.items.Amulet; import com.shatteredpixel.shatteredpixeldungeon.levels.painters.Painter; @@ -130,11 +131,13 @@ public class LastLevel extends Level { } @Override - public int randomRespawnCell() { + public int randomRespawnCell( Char ch ) { int cell; do { cell = entrance + PathFinder.NEIGHBOURS8[Random.Int(8)]; - } while (!passable[cell] || Actor.findChar(cell) != null); + } while (!passable[cell] + || (Char.hasProp(ch, Char.Property.LARGE) && !openSpace[cell]) + || Actor.findChar(cell) != null); return cell; } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/LastShopLevel.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/LastShopLevel.java index 4fad9ff8c..e64ee64e7 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/LastShopLevel.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/LastShopLevel.java @@ -24,6 +24,7 @@ package com.shatteredpixel.shatteredpixeldungeon.levels; import com.shatteredpixel.shatteredpixeldungeon.Assets; import com.shatteredpixel.shatteredpixeldungeon.Bones; import com.shatteredpixel.shatteredpixeldungeon.actors.Actor; +import com.shatteredpixel.shatteredpixeldungeon.actors.Char; import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob; import com.shatteredpixel.shatteredpixeldungeon.items.Heap; import com.shatteredpixel.shatteredpixeldungeon.items.Item; @@ -126,11 +127,13 @@ public class LastShopLevel extends RegularLevel { } @Override - public int randomRespawnCell() { + public int randomRespawnCell( Char ch ) { int cell; do { cell = pointToCell( roomEntrance.random() ); - } while (!passable[cell] || Actor.findChar(cell) != null); + } while (!passable[cell] + || (Char.hasProp(ch, Char.Property.LARGE) && !openSpace[cell]) + || Actor.findChar(cell) != null); return cell; } 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 89316b91b..514ac90fe 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/Level.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/Level.java @@ -38,7 +38,6 @@ import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff; import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.LockedFloor; import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.MagicalSight; import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.MindVision; -import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Roots; import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Shadows; import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero; import com.shatteredpixel.shatteredpixeldungeon.actors.hero.HeroClass; @@ -54,7 +53,6 @@ import com.shatteredpixel.shatteredpixeldungeon.items.Heap; import com.shatteredpixel.shatteredpixeldungeon.items.Item; import com.shatteredpixel.shatteredpixeldungeon.items.Stylus; import com.shatteredpixel.shatteredpixeldungeon.items.Torch; -import com.shatteredpixel.shatteredpixeldungeon.items.artifacts.DriedRose; import com.shatteredpixel.shatteredpixeldungeon.items.artifacts.TimekeepersHourglass; import com.shatteredpixel.shatteredpixeldungeon.items.food.SmallRation; import com.shatteredpixel.shatteredpixeldungeon.items.potions.PotionOfStrength; @@ -128,6 +126,8 @@ public abstract class Level implements Bundlable { public boolean[] avoid; public boolean[] water; public boolean[] pit; + + public boolean[] openSpace; public Feeling feeling = Feeling.NONE; @@ -275,6 +275,8 @@ public abstract class Level implements Bundlable { avoid = new boolean[length]; water = new boolean[length]; pit = new boolean[length]; + + openSpace = new boolean[length]; PathFinder.setMapSize(w, h); } @@ -513,7 +515,7 @@ public abstract class Level implements Bundlable { Mob mob = createMob(); mob.state = mob.WANDERING; - mob.pos = randomRespawnCell(); + mob.pos = randomRespawnCell( mob ); if (Dungeon.hero.isAlive() && mob.pos != -1 && distance(Dungeon.hero.pos, mob.pos) >= 4) { GameScene.add( mob ); if (Statistics.amuletObtained) { @@ -537,12 +539,13 @@ public abstract class Level implements Bundlable { } } - public int randomRespawnCell() { + public int randomRespawnCell( Char ch ) { int cell; do { cell = Random.Int( length() ); } while ((Dungeon.level == this && heroFOV[cell]) || !passable[cell] + || (Char.hasProp(ch, Char.Property.LARGE) && !openSpace[cell]) || Actor.findChar( cell ) != null); return cell; } @@ -614,16 +617,25 @@ public abstract class Level implements Bundlable { int lastRow = length() - width(); for (int i=0; i < width(); i++) { passable[i] = avoid[i] = false; - losBlocking[i] = true; + losBlocking[i] = solid[i] = true; passable[lastRow + i] = avoid[lastRow + i] = false; - losBlocking[lastRow + i] = true; + losBlocking[lastRow + i] = solid[lastRow + i] = true; } for (int i=width(); i < lastRow; i += width()) { passable[i] = avoid[i] = false; - losBlocking[i] = true; + losBlocking[i] = solid[i] = true; passable[i + width()-1] = avoid[i + width()-1] = false; - losBlocking[i + width()-1] = true; + losBlocking[i + width()-1] = solid[i + width()-1] = true; } + + //an open space is large enough to fit large mobs. A space is open when it is not solid + // and there also aren't solid spaces above&below, or left&right + for (int i=0; i < length(); i++) { + openSpace[i] = !solid[i] && + (!solid[i-1] || !solid[i+1]) && + (!solid[i-width()] || !solid[i+width()]); + } + } public void destroy( int pos ) { @@ -669,6 +681,12 @@ public abstract class Level implements Bundlable { level.avoid[cell] = (flags & Terrain.AVOID) != 0; level.pit[cell] = (flags & Terrain.PIT) != 0; level.water[cell] = terrain == Terrain.WATER; + + for (int i : PathFinder.NEIGHBOURS9){ + level.openSpace[cell+i] = !level.solid[cell+i] && + (!level.solid[cell+i-1] || !level.solid[cell+i+1]) && + (!level.solid[cell+i-level.width()] || !level.solid[cell+i+level.width()]); + } SmokeScreen s = (SmokeScreen)level.blobs.get(SmokeScreen.class); if (s != null && s.volume > 0){ @@ -783,7 +801,7 @@ public abstract class Level implements Bundlable { public int fallCell( boolean fallIntoPit ) { int result; do { - result = randomRespawnCell(); + result = randomRespawnCell( null ); } while (traps.get(result) != null || findMob(result) != null || heaps.get(result) != null); diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/NewPrisonBossLevel.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/NewPrisonBossLevel.java index e67878061..713a1fda5 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/NewPrisonBossLevel.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/NewPrisonBossLevel.java @@ -619,7 +619,7 @@ public class NewPrisonBossLevel extends Level { protected void createItems() { Item item = Bones.get(); if (item != null) { - drop( item, randomRespawnCell() ).setHauntedIfCursed().type = Heap.Type.REMAINS; + drop( item, randomRespawnCell( null ) ).setHauntedIfCursed().type = Heap.Type.REMAINS; } } @@ -687,12 +687,14 @@ public class NewPrisonBossLevel extends Level { } @Override - public int randomRespawnCell() { + public int randomRespawnCell( Char ch ) { int pos = ENTRANCE_POS; //random cell adjacent to the entrance. int cell; do { cell = pos + PathFinder.NEIGHBOURS8[Random.Int(8)]; - } while (!passable[cell] || Actor.findChar(cell) != null); + } while (!passable[cell] + || (Char.hasProp(ch, Char.Property.LARGE) && !openSpace[cell]) + || Actor.findChar(cell) != null); return cell; } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/OldPrisonBossLevel.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/OldPrisonBossLevel.java index 1a0c25117..3817d5363 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/OldPrisonBossLevel.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/OldPrisonBossLevel.java @@ -160,7 +160,7 @@ public class OldPrisonBossLevel extends Level { protected void createItems() { Item item = Bones.get(); if (item != null) { - drop( item, randomRespawnCell() ).setHauntedIfCursed().type = Heap.Type.REMAINS; + drop( item, randomRespawnCell( null ) ).setHauntedIfCursed().type = Heap.Type.REMAINS; } drop(new IronKey(10), randomPrisonCell()); } @@ -210,12 +210,14 @@ public class OldPrisonBossLevel extends Level { } @Override - public int randomRespawnCell() { + public int randomRespawnCell( Char ch ) { int pos = 5+2*32; //random cell adjacent to the entrance. int cell; do { cell = pos + PathFinder.NEIGHBOURS8[Random.Int(8)]; - } while (!passable[cell] || Actor.findChar(cell) != null); + } while (!passable[cell] + || (Char.hasProp(ch, Char.Property.LARGE) && !openSpace[cell]) + || Actor.findChar(cell) != null); return cell; } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/RegularLevel.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/RegularLevel.java index 6271b178d..85f4b37cf 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/RegularLevel.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/RegularLevel.java @@ -24,6 +24,7 @@ package com.shatteredpixel.shatteredpixeldungeon.levels; import com.shatteredpixel.shatteredpixeldungeon.Bones; import com.shatteredpixel.shatteredpixeldungeon.Dungeon; import com.shatteredpixel.shatteredpixeldungeon.actors.Actor; +import com.shatteredpixel.shatteredpixeldungeon.actors.Char; import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.GoldenMimic; import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mimic; import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob; @@ -220,7 +221,7 @@ public abstract class RegularLevel extends Level { } @Override - public int randomRespawnCell() { + public int randomRespawnCell( Char ch ) { int count = 0; int cell = -1; @@ -239,6 +240,7 @@ public abstract class RegularLevel extends Level { if (!heroFOV[cell] && Actor.findChar( cell ) == null && passable[cell] + && (!Char.hasProp(ch, Char.Property.LARGE) || openSpace[cell]) && room.canPlaceCharacter(cellToPoint(cell), this) && cell != exit) { return cell; diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/SewerBossLevel.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/SewerBossLevel.java index 92fd66707..e3300f160 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/SewerBossLevel.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/SewerBossLevel.java @@ -23,6 +23,7 @@ package com.shatteredpixel.shatteredpixeldungeon.levels; import com.shatteredpixel.shatteredpixeldungeon.Bones; import com.shatteredpixel.shatteredpixeldungeon.actors.Actor; +import com.shatteredpixel.shatteredpixeldungeon.actors.Char; import com.shatteredpixel.shatteredpixeldungeon.items.Heap; import com.shatteredpixel.shatteredpixeldungeon.items.Item; import com.shatteredpixel.shatteredpixeldungeon.levels.builders.Builder; @@ -119,11 +120,14 @@ public class SewerBossLevel extends SewerLevel { } @Override - public int randomRespawnCell() { + public int randomRespawnCell( Char ch ) { int pos; do { pos = pointToCell(roomEntrance.random()); - } while (pos == entrance || !passable[pos] || Actor.findChar(pos) != null); + } while (pos == entrance + || !passable[pos] + || (Char.hasProp(ch, Char.Property.LARGE) && !openSpace[pos]) + || Actor.findChar(pos) != null); return pos; } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/traps/DisarmingTrap.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/traps/DisarmingTrap.java index dd8166b45..c26dd6dfe 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/traps/DisarmingTrap.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/traps/DisarmingTrap.java @@ -47,7 +47,7 @@ public class DisarmingTrap extends Trap{ Heap heap = Dungeon.level.heaps.get( pos ); if (heap != null){ - int cell = Dungeon.level.randomRespawnCell(); + int cell = Dungeon.level.randomRespawnCell( null ); if (cell != -1) { Item item = heap.pickUp(); @@ -70,7 +70,7 @@ public class DisarmingTrap extends Trap{ int cell; int tries = 20; do { - cell = Dungeon.level.randomRespawnCell(); + cell = Dungeon.level.randomRespawnCell( null ); if (tries-- < 0 && cell != -1) break; PathFinder.buildDistanceMap(pos, Dungeon.level.passable); diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/traps/DistortionTrap.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/traps/DistortionTrap.java index 4094488a7..be2eb6ab0 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/traps/DistortionTrap.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/traps/DistortionTrap.java @@ -136,6 +136,10 @@ public class DistortionTrap extends Trap{ break; } + if (Char.hasProp(mob, Char.Property.LARGE) && !Dungeon.level.openSpace[point]){ + continue; + } + mob.maxLvl = Hero.MAX_LEVEL; mob.state = mob.WANDERING; mob.pos = point; diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/traps/GuardianTrap.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/traps/GuardianTrap.java index d315ecff7..2fd7fa113 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/traps/GuardianTrap.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/traps/GuardianTrap.java @@ -57,7 +57,7 @@ public class GuardianTrap extends Trap { for (int i = 0; i < (Dungeon.depth - 5)/5; i++){ Guardian guardian = new Guardian(); guardian.state = guardian.WANDERING; - guardian.pos = Dungeon.level.randomRespawnCell(); + guardian.pos = Dungeon.level.randomRespawnCell( guardian ); GameScene.add(guardian); guardian.beckon(Dungeon.hero.pos ); } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/traps/SummoningTrap.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/traps/SummoningTrap.java index ab532c131..655103c11 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/traps/SummoningTrap.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/traps/SummoningTrap.java @@ -23,6 +23,7 @@ package com.shatteredpixel.shatteredpixeldungeon.levels.traps; import com.shatteredpixel.shatteredpixeldungeon.Dungeon; import com.shatteredpixel.shatteredpixeldungeon.actors.Actor; +import com.shatteredpixel.shatteredpixeldungeon.actors.Char; import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob; import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfTeleportation; import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene; @@ -73,6 +74,9 @@ public class SummoningTrap extends Trap { for (Integer point : respawnPoints) { Mob mob = Dungeon.level.createMob(); + if (Char.hasProp(mob, Char.Property.LARGE) && !Dungeon.level.openSpace[point]){ + continue; + } if (mob != null) { mob.state = mob.WANDERING; mob.pos = point; diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/traps/TeleportationTrap.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/traps/TeleportationTrap.java index 6de6be30c..331cb7b3f 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/traps/TeleportationTrap.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/traps/TeleportationTrap.java @@ -57,7 +57,7 @@ public class TeleportationTrap extends Trap { int count = 10; int pos; do { - pos = Dungeon.level.randomRespawnCell(); + pos = Dungeon.level.randomRespawnCell( ch ); if (count-- <= 0) { break; } @@ -83,7 +83,7 @@ public class TeleportationTrap extends Trap { Heap heap = Dungeon.level.heaps.get(pos); if (heap != null){ - int cell = Dungeon.level.randomRespawnCell(); + int cell = Dungeon.level.randomRespawnCell( null ); Item item = heap.pickUp(); diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/traps/WarpingTrap.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/traps/WarpingTrap.java index d3fa6b97e..7197c1935 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/traps/WarpingTrap.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/traps/WarpingTrap.java @@ -63,7 +63,7 @@ public class WarpingTrap extends Trap { int count = 10; int pos; do { - pos = Dungeon.level.randomRespawnCell(); + pos = Dungeon.level.randomRespawnCell( ch ); if (count-- <= 0) { break; } @@ -89,7 +89,7 @@ public class WarpingTrap extends Trap { Heap heap = Dungeon.level.heaps.get(pos); if (heap != null){ - int cell = Dungeon.level.randomRespawnCell(); + int cell = Dungeon.level.randomRespawnCell( null ); Item item = heap.pickUp(); diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/plants/Fadeleaf.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/plants/Fadeleaf.java index 313026856..f54c2337e 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/plants/Fadeleaf.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/plants/Fadeleaf.java @@ -77,7 +77,7 @@ public class Fadeleaf extends Plant { int count = 10; int newPos; do { - newPos = Dungeon.level.randomRespawnCell(); + newPos = Dungeon.level.randomRespawnCell( ch ); if (count-- <= 0) { break; } 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 c3dd7aa58..535fa2fd1 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/scenes/GameScene.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/scenes/GameScene.java @@ -379,7 +379,7 @@ public class GameScene extends PixelScene { ArrayList dropped = Dungeon.droppedItems.get( Dungeon.depth ); if (dropped != null) { for (Item item : dropped) { - int pos = Dungeon.level.randomRespawnCell(); + int pos = Dungeon.level.randomRespawnCell( null ); if (item instanceof Potion) { ((Potion)item).shatter( pos ); } else if (item instanceof Plant.Seed) { @@ -401,7 +401,7 @@ public class GameScene extends PixelScene { //try to find a tile with no heap, otherwise just stick items onto a heap. int tries = 100; do { - pos = Dungeon.level.randomRespawnCell(); + pos = Dungeon.level.randomRespawnCell( null ); tries--; } while (tries > 0 && Dungeon.level.heaps.get(pos) != null); for (Item item : ported) {