v2.3.2: improved item placement logic in shops.
This improves layouts and also fixes seed problems with varying item count
This commit is contained in:
@@ -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());
|
||||
|
||||
@@ -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){
|
||||
|
||||
Reference in New Issue
Block a user