openvibers/openvibe.games Commits

Salvage Rush runs no NPCs: a world definition can name its own (npcSpawns, [] for none), and the arena did get the procedural world's townsfolk, warden and Rustjaw thugs (#126)

OP OpenVibers committed 24 days ago · 4d517076bf · 5 files, +28 −0

Changes

ddiff --git a/CHANGELOG.md b/CHANGELOG.md
iindex 2458fe1..212c671 100644
---- a/CHANGELOG.md
++++ b/CHANGELOG.md
@@@ -8,6 +8,10 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
### Fixed
++- **Townsfolk in the Salvage Rush arena.** The 90-second scrap round ran the content's seven NPC spawns, laid out for
++ the procedural world: townsfolk and a warden wandered inside the arena and Rustjaw thugs stood just past its edge.
++ A world definition can now name its own NPCs (`npcSpawns`; `[]` is none), and the arena has none. A map's own NPCs
++ still win.
- **Touch play's HUD was buried under the controls.** On a phone, the stick (bottom left) and the button grid (bottom
right) covered the first-steps panel, and the HP, food, water and stamina bars sat on the hotbar. While the touch
controls show:
ddiff --git a/packages/content/src/defs/npcs.ts b/packages/content/src/defs/npcs.ts
iindex 618bc37..f6c120e 100644
---- a/packages/content/src/defs/npcs.ts
++++ b/packages/content/src/defs/npcs.ts
@@@ -124,6 +124,7 @@ export interface NpcSpawn {
export function npcSpawnsFor(world?: WorldDef): NpcSpawn[] {
const mapped = getMapOverride(world)?.npcs ?? []
if (mapped.length) return mapped.map((n) => ({ archetype: n.npc, pos: n.pos }))
++ if (world?.npcSpawns) return world.npcSpawns
return NPC_SPAWNS
}
ddiff --git a/packages/content/src/mapFileV2.test.ts b/packages/content/src/mapFileV2.test.ts
iindex 4c7f72d..3c2d4a4 100644
---- a/packages/content/src/mapFileV2.test.ts
++++ b/packages/content/src/mapFileV2.test.ts
@@@ -12,6 +12,8 @@ import {
} from './mapFileV2.js'
import { NPC_SPAWNS, npcSpawnsFor } from './defs/npcs.js'
import { setMapOverride } from './terrain.js'
++import { SALVAGE_RUSH_PACK } from './packs/salvageRush.js'
++import type { WorldDef } from './schema/world.js'
const SUB = 8
@@@ -473,6 +475,19 @@ describe('map-authored NPCs', () => {
expect(npcSpawnsFor()).toBe(NPC_SPAWNS)
})
++ it("a world with its own spawns (none, in Salvage Rush's arena) is not given the content's", () => {
++ const arena = SALVAGE_RUSH_PACK.map as WorldDef
++ expect(arena.npcSpawns).toEqual([])
++ expect(npcSpawnsFor(arena)).toEqual([])
++ // A map that places NPCs still wins.
++ setMapOverride({ terrains: [], npcs: [{ id: 'n', npc: 'dust_hare', pos: [1, 0, 1] }] })
++ try {
++ expect(npcSpawnsFor(arena)).toEqual([{ archetype: 'dust_hare', pos: [1, 0, 1] }])
++ } finally {
++ setMapOverride(null)
++ }
++ })
++
it('an NPC id may not repeat another object id', () => {
const map: MapFileV2 = {
...emptyMapV2(),
ddiff --git a/packages/content/src/packs/salvageRush.ts b/packages/content/src/packs/salvageRush.ts
iindex b83712e..8bba32d 100644
---- a/packages/content/src/packs/salvageRush.ts
++++ b/packages/content/src/packs/salvageRush.ts
@@@ -17,6 +17,9 @@ export const SALVAGE_RUSH_PACK: ContentPackV2 = {
],
resourceNodes: [],
initialProps: [],
++ // A 90-second scrap round: no NPCs. The content's spawns put townsfolk and a warden inside the arena and Rustjaw
++ // thugs just past its edge.
++ npcSpawns: [],
zones: [
{
id: 'arena',
ddiff --git a/packages/content/src/schema/world.ts b/packages/content/src/schema/world.ts
iindex 954fffe..c8446aa 100644
---- a/packages/content/src/schema/world.ts
++++ b/packages/content/src/schema/world.ts
@@@ -155,6 +155,11 @@ export const WorldDefSchema = z.object({
resourceNodes: z.array(ResourceNodeSpawnSchema),
initialProps: z.array(PropSpawnSchema),
zones: z.array(ZoneDefSchema),
++ /**
++ * The world's own NPCs, when it has an opinion: `[]` for none (a timed arena), else archetypes and ground
++ * positions. Absent, it gets the content's NPC_SPAWNS. A map's own NPCs win over either (npcSpawnsFor).
++ */
++ npcSpawns: z.array(z.object({ archetype: z.string(), pos: vec3 })).optional(),
})
export type WorldDef = z.infer<typeof WorldDefSchema>