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:
Evan Debenham
2024-01-30 16:03:04 -05:00
parent 14f4b0a38e
commit 6a05169b51
2 changed files with 73 additions and 27 deletions

View File

@@ -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());

View File

@@ -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){