feat(slay-the-spire-like): implement encounter system
Add logic for handling different encounter types including combat, shop, curio, camp, and events. Includes shop item generation and grid inventory placement for shop encounters.
This commit is contained in:
parent
52b6cecd64
commit
d5ec099540
|
|
@ -29,6 +29,12 @@ export function buildCombatState(
|
|||
};
|
||||
}
|
||||
|
||||
export function buildCombatEncounterState(
|
||||
data: EncounterData<"minion" | "elite">,
|
||||
): CombatEncounterState {
|
||||
return { data, blocked: false };
|
||||
}
|
||||
|
||||
function createEnemyEntities(encounter: EncounterData): EnemyEntity[] {
|
||||
const enemies: EnemyEntity[] = [];
|
||||
let instanceCounter = 0;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,100 @@
|
|||
import { createGridInventory, placeItem } from "../grid-inventory";
|
||||
import { GameItemMeta } from "../grid-inventory/types";
|
||||
import { IDENTITY_TRANSFORM } from "../utils/shape-collision";
|
||||
import { parseShapeString } from "../utils/parse-shape";
|
||||
import { EncounterData, EncounterType, ItemData } from "../types";
|
||||
import type { RNG } from "@/utils/rng";
|
||||
import type {
|
||||
CampEncounterState,
|
||||
CombatEncounterState,
|
||||
CurioEncounterState,
|
||||
DialogueEncounterState,
|
||||
EncounterState,
|
||||
ShopEncounterState,
|
||||
} from "./types";
|
||||
import { buildCombatEncounterState } from "./combat";
|
||||
import { buildShopEncounterState } from "./shop";
|
||||
|
||||
function createCurioItems(allItems: ItemData[], rng: RNG): GameItemMeta[] {
|
||||
const curioItems: GameItemMeta[] = [];
|
||||
const rolledIndices = new Set<number>();
|
||||
|
||||
for (let i = 0; i < 3 && rolledIndices.size < allItems.length; i++) {
|
||||
let index: number;
|
||||
do {
|
||||
index = rng.nextInt(allItems.length);
|
||||
} while (rolledIndices.has(index));
|
||||
rolledIndices.add(index);
|
||||
|
||||
const itemData = allItems[index];
|
||||
const shape = parseShapeString(itemData.shape);
|
||||
curioItems.push({ itemData, shape });
|
||||
}
|
||||
|
||||
return curioItems;
|
||||
}
|
||||
|
||||
export function buildCurioEncounterState(
|
||||
data: EncounterData<"curio">,
|
||||
allItems: ItemData[],
|
||||
rng: RNG,
|
||||
): CurioEncounterState {
|
||||
const items = createCurioItems(allItems, rng);
|
||||
const inventory = createGridInventory<GameItemMeta>(6, 4);
|
||||
|
||||
for (let i = 0; i < items.length; i++) {
|
||||
const meta = items[i];
|
||||
placeItem(inventory, {
|
||||
id: `curio-item-${i}`,
|
||||
shape: meta.shape,
|
||||
transform: { ...IDENTITY_TRANSFORM, offset: { x: i, y: 0 } },
|
||||
meta,
|
||||
});
|
||||
}
|
||||
|
||||
return { data, items: inventory };
|
||||
}
|
||||
|
||||
export function buildCampEncounterState(
|
||||
data: EncounterData<"camp">,
|
||||
): CampEncounterState {
|
||||
return { data };
|
||||
}
|
||||
|
||||
export function buildDialogueEncounterState(
|
||||
data: EncounterData<"event">,
|
||||
): DialogueEncounterState {
|
||||
return { data, blocked: false };
|
||||
}
|
||||
|
||||
export function buildEncounterState(
|
||||
data: EncounterData<EncounterType>,
|
||||
allItems: ItemData[],
|
||||
rng: RNG,
|
||||
idCounter: { value: number },
|
||||
): EncounterState {
|
||||
switch (data.type) {
|
||||
case "minion":
|
||||
case "elite":
|
||||
return buildCombatEncounterState(
|
||||
data as EncounterData<"minion" | "elite">,
|
||||
);
|
||||
case "shop":
|
||||
return buildShopEncounterState(
|
||||
data as EncounterData<"shop">,
|
||||
allItems,
|
||||
rng,
|
||||
idCounter,
|
||||
);
|
||||
case "curio":
|
||||
return buildCurioEncounterState(
|
||||
data as EncounterData<"curio">,
|
||||
allItems,
|
||||
rng,
|
||||
);
|
||||
case "camp":
|
||||
return buildCampEncounterState(data as EncounterData<"camp">);
|
||||
case "event":
|
||||
return buildDialogueEncounterState(data as EncounterData<"event">);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
export { buildCombatState, buildCombatEncounterState } from "./combat";
|
||||
export { buildShopEncounterState, generateInstanceId } from "./shop";
|
||||
export { buildEncounterState } from "./encounter";
|
||||
export { RunState, EncounterState } from "./types";
|
||||
export { buildCombatState } from "./combat";
|
||||
export { generateInstanceId } from "./shop";
|
||||
|
|
|
|||
|
|
@ -1,4 +1,63 @@
|
|||
import { createGridInventory, placeItem } from "../grid-inventory";
|
||||
import { GameItemMeta } from "../grid-inventory/types";
|
||||
import { IDENTITY_TRANSFORM } from "../utils/shape-collision";
|
||||
import { parseShapeString } from "../utils/parse-shape";
|
||||
import { EncounterData, ItemData } from "../types";
|
||||
import type { RNG } from "@/utils/rng";
|
||||
import type { ShopEncounterState } from "./types";
|
||||
|
||||
export function generateInstanceId(counter: { value: number }): string {
|
||||
counter.value++;
|
||||
return `item-${counter.value}`;
|
||||
}
|
||||
|
||||
function createShopItems(
|
||||
allItems: ItemData[],
|
||||
rng: RNG,
|
||||
): (GameItemMeta & { sellPrice: number })[] {
|
||||
const shopItems: (GameItemMeta & { sellPrice: number })[] = [];
|
||||
const rolledIndices = new Set<number>();
|
||||
|
||||
for (let i = 0; i < 5 && rolledIndices.size < allItems.length; i++) {
|
||||
let index: number;
|
||||
do {
|
||||
index = rng.nextInt(allItems.length);
|
||||
} while (rolledIndices.has(index));
|
||||
rolledIndices.add(index);
|
||||
|
||||
const itemData = allItems[index];
|
||||
const shape = parseShapeString(itemData.shape);
|
||||
const sellPrice = Math.floor(
|
||||
(rng.nextInt(5) + rng.nextInt(5) + 1) * 0.2 * itemData.price,
|
||||
);
|
||||
|
||||
shopItems.push({ itemData, shape, sellPrice });
|
||||
}
|
||||
|
||||
return shopItems;
|
||||
}
|
||||
|
||||
export function buildShopEncounterState(
|
||||
data: EncounterData<"shop">,
|
||||
allItems: ItemData[],
|
||||
rng: RNG,
|
||||
idCounter: { value: number },
|
||||
): ShopEncounterState {
|
||||
const items = createShopItems(allItems, rng);
|
||||
const inventory = createGridInventory<GameItemMeta & { sellPrice: number }>(
|
||||
6,
|
||||
4,
|
||||
);
|
||||
|
||||
for (let i = 0; i < items.length; i++) {
|
||||
const meta = items[i];
|
||||
placeItem(inventory, {
|
||||
id: generateInstanceId(idCounter),
|
||||
shape: meta.shape,
|
||||
transform: { ...IDENTITY_TRANSFORM, offset: { x: i, y: 0 } },
|
||||
meta,
|
||||
});
|
||||
}
|
||||
|
||||
return { data, items: inventory };
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue