diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/rooms/special/ShopRoom.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/rooms/special/ShopRoom.java index 2b25337cb..0bcd51d46 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/rooms/special/ShopRoom.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/rooms/special/ShopRoom.java @@ -22,6 +22,7 @@ package com.shatteredpixel.shatteredpixeldungeon.levels.rooms.special; import com.shatteredpixel.shatteredpixeldungeon.Dungeon; +import com.shatteredpixel.shatteredpixeldungeon.ShatteredPixelDungeon; import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Belongings; import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob; import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.npcs.Shopkeeper; @@ -111,38 +112,88 @@ public class ShopRoom extends SpecialRoom { itemsToSpawn = generateItems(); } - Point itemPlacement = new Point(entrance()); - if (itemPlacement.y == top){ - itemPlacement.y++; - } else if (itemPlacement.y == bottom) { - itemPlacement.y--; - } else if (itemPlacement.x == left){ - itemPlacement.x++; + Point entryInset = new Point(entrance()); + if (entryInset.y == top){ + entryInset.y++; + } else if (entryInset.y == bottom) { + entryInset.y--; + } else if (entryInset.x == left){ + entryInset.x++; } else { - itemPlacement.x--; + entryInset.x--; } - for (Item item : itemsToSpawn) { + Point curItemPlace = entryInset.clone(); - if (itemPlacement.x == left+1 && itemPlacement.y != top+1){ - itemPlacement.y--; - } else if (itemPlacement.y == top+1 && itemPlacement.x != right-1){ - itemPlacement.x++; - } else if (itemPlacement.x == right-1 && itemPlacement.y != bottom-1){ - itemPlacement.y++; + int inset = 1; + + for (Item item : itemsToSpawn.toArray(new Item[0])) { + + //place items in a clockwise pattern + if (curItemPlace.x == left+inset && curItemPlace.y != top+inset){ + curItemPlace.y--; + } else if (curItemPlace.y == top+inset && curItemPlace.x != right-inset){ + curItemPlace.x++; + } else if (curItemPlace.x == right-inset && curItemPlace.y != bottom-inset){ + curItemPlace.y++; } else { - itemPlacement.x--; + curItemPlace.x--; } - int cell = level.pointToCell(itemPlacement); + //once we get to the inset from the entrance again, move another cell inward and loop + if (curItemPlace.equals(entryInset)){ - if (level.heaps.get( cell ) != null) { - do { - cell = level.pointToCell(random()); - } while (level.heaps.get( cell ) != null || level.findMob( cell ) != null); + if (entryInset.y == top+inset){ + entryInset.y++; + } else if (entryInset.y == bottom-inset){ + entryInset.y--; + } + if (entryInset.x == left+inset){ + entryInset.x++; + } else if (entryInset.x == right-inset){ + entryInset.x--; + } + inset++; + + if (inset > (Math.min(width(), height())-3)/2){ + break; //out of space! + } + + curItemPlace = entryInset.clone(); + + //make sure to step forward again + if (curItemPlace.x == left+inset && curItemPlace.y != top+inset){ + curItemPlace.y--; + } else if (curItemPlace.y == top+inset && curItemPlace.x != right-inset){ + curItemPlace.x++; + } else if (curItemPlace.x == right-inset && curItemPlace.y != bottom-inset){ + curItemPlace.y++; + } else { + curItemPlace.x--; + } } + int cell = level.pointToCell(curItemPlace); level.drop( item, cell ).type = Heap.Type.FOR_SALE; + itemsToSpawn.remove(item); + } + + //we didn't have enough space to place everything neatly, so now just fill in anything left + if (!itemsToSpawn.isEmpty()){ + for (Point p : getPoints()){ + int cell = level.pointToCell(p); + if ((level.map[cell] == Terrain.EMPTY_SP || level.map[cell] == Terrain.EMPTY) + && level.heaps.get(cell) == null && level.findMob(cell) == null){ + level.drop( itemsToSpawn.remove(0), level.pointToCell(p) ).type = Heap.Type.FOR_SALE; + } + if (itemsToSpawn.isEmpty()){ + break; + } + } + } + + if (!itemsToSpawn.isEmpty()){ + ShatteredPixelDungeon.reportException(new RuntimeException("failed to place all items in a shop!")); } } @@ -270,11 +321,6 @@ public class ShopRoom extends SpecialRoom { rare.cursedKnown = true; itemsToSpawn.add( rare ); - //hard limit is 63 items + 1 shopkeeper, as shops can't be bigger than 8x8=64 internally - if (itemsToSpawn.size() > 63) { - throw new RuntimeException("Shop attempted to carry more than 63 items!"); - } - //use a new generator here to prevent items in shop stock affecting levelgen RNG (e.g. sandbags) //we can use a random long for the seed as it will be the same long every time Random.pushGenerator(Random.Long()); diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/rooms/standard/ImpShopRoom.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/rooms/standard/ImpShopRoom.java index e72b90881..b03085136 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/rooms/standard/ImpShopRoom.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/rooms/standard/ImpShopRoom.java @@ -91,7 +91,7 @@ public class ImpShopRoom extends ShopRoom { //fix for connections not being bundled normally @Override public Door entrance() { - return connected.isEmpty() ? new Door(left, top+2) : super.entrance(); + return connected.isEmpty() ? new Door((left+right)/2 + 1, bottom-1) : super.entrance(); } public void spawnShop(Level level){