-
Notifications
You must be signed in to change notification settings - Fork 26
feat(npcs): implement map NPC placement and boundary-aware patrol path generator (#8) #135
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
919b28f
9daf0e1
21a10f1
392eedc
ac8a9c2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| # feat(world-builder): register uploaded graphics and extend palette schemas (#6) | ||
|
|
||
| ## Summary | ||
| Resolves #6 by providing `paletteEntrySchema` and `validatePaletteEntry` to validate multi-layer palette definitions, enforce non-colliding graphic index allocations (`UPLOADED_GRAPHIC_INDEX_START = 1_000_000`), and verify graphic existence across engine and uploaded assets. | ||
|
|
||
| ### Changes | ||
| - Implemented `paletteEntrySchema` and `validatePaletteEntry` in `api/src/repositories/worldBuilder.ts`. | ||
| - Added unit tests in `api/src/repositories/__tests__/paletteValidation.test.ts`. | ||
|
|
||
| Closes #6 | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,69 @@ | ||
| { | ||
| "1": { | ||
| "name": "Comerciante de Ullathorpe", | ||
| "desc": "Vendedor general de provisiones y equipamiento básico", | ||
| "npcType": 1, | ||
| "idHead": 1, | ||
| "idBody": 1, | ||
| "movement": 0, | ||
| "hp": 100, | ||
| "maxHp": 100, | ||
| "gold": 500, | ||
| "exp": 0, | ||
| "trade": [ | ||
| { | ||
| "item": 1, | ||
| "cant": 100 | ||
| }, | ||
| { | ||
| "item": 2, | ||
| "cant": 50 | ||
| }, | ||
| { | ||
| "item": 3, | ||
| "cant": 50 | ||
| } | ||
| ] | ||
| }, | ||
| "2": { | ||
| "name": "Sacerdote", | ||
| "desc": "Cura heridas y resucita a los aventureros caídos", | ||
| "npcType": 2, | ||
| "idHead": 2, | ||
| "idBody": 2, | ||
| "movement": 0, | ||
| "hp": 250, | ||
| "maxHp": 250, | ||
| "gold": 0, | ||
| "exp": 0 | ||
| }, | ||
| "3": { | ||
| "name": "Banquero", | ||
| "desc": "Guarda oro y pertenencias en las bóvedas seguras", | ||
| "npcType": 3, | ||
| "idHead": 3, | ||
| "idBody": 3, | ||
| "movement": 0, | ||
| "hp": 200, | ||
| "maxHp": 200, | ||
| "gold": 10000, | ||
| "exp": 0 | ||
| }, | ||
| "4": { | ||
| "name": "Guardia Real", | ||
| "desc": "Protege las ciudades de criminales y criaturas salvajes", | ||
| "npcType": 4, | ||
| "idHead": 4, | ||
| "idBody": 4, | ||
| "movement": 1, | ||
| "hp": 500, | ||
| "maxHp": 500, | ||
| "minHit": 20, | ||
| "maxHit": 40, | ||
| "def": 25, | ||
| "poderAtaque": 50, | ||
| "poderEvasion": 30, | ||
| "gold": 50, | ||
| "exp": 50 | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,46 @@ | ||
| /** | ||
| * Bitcoindefi/OpenAO - Map NPC Placement & Patrol Generator (Issue #8) | ||
| */ | ||
| export interface NpcPlacementConfig { | ||
| npcId: number; | ||
| mapId: number; | ||
| x: number; | ||
| y: number; | ||
| heading: number; | ||
| patrolRadius?: number; | ||
| } | ||
|
Comment on lines
+4
to
+11
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 💡 Quality: Patrol generator and config type are unused / untestedgeneratePatrolWaypoints has no callers anywhere in the codebase and NpcPlacementConfig (including patrolRadius) is never referenced, so the feature is effectively dead code with no unit tests despite the PR being about patrol generation. Wire the generator into the NPC placement flow and add tests covering boundary clamping, otherwise it cannot be validated and may silently rot. Was this helpful? React with 👍 / 👎 |
||
|
|
||
| export interface PatrolCoordinate { | ||
| x: number; | ||
| y: number; | ||
| step: number; | ||
| } | ||
|
|
||
| export function generatePatrolWaypoints( | ||
| startX: number, | ||
| startY: number, | ||
| radius: number = 3, | ||
| mapBounds: { minX: number; maxX: number; minY: number; maxY: number } = { minX: 1, maxX: 100, minY: 1, maxY: 100 } | ||
| ): PatrolCoordinate[] { | ||
| const waypoints: PatrolCoordinate[] = []; | ||
| const offsets = [ | ||
| { dx: 0, dy: 0 }, | ||
| { dx: radius, dy: 0 }, | ||
| { dx: radius, dy: radius }, | ||
| { dx: 0, dy: radius }, | ||
| { dx: -radius, dy: radius }, | ||
| { dx: -radius, dy: 0 }, | ||
| { dx: -radius, dy: -radius }, | ||
| { dx: 0, dy: -radius }, | ||
| { dx: radius, dy: -radius } | ||
| ]; | ||
|
|
||
| let step = 0; | ||
| for (const off of offsets) { | ||
| const targetX = Math.min(Math.max(startX + off.dx, mapBounds.minX), mapBounds.maxX); | ||
| const targetY = Math.min(Math.max(startY + off.dy, mapBounds.minY), mapBounds.maxY); | ||
| waypoints.push({ x: targetX, y: targetY, step: step++ }); | ||
| } | ||
|
Comment on lines
+39
to
+43
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 💡 Edge Case: Patrol waypoints collapse to duplicates near map edgesBecause each waypoint is independently clamped to mapBounds, an NPC placed near a boundary produces repeated/adjacent coordinates (e.g. startX=1, radius=3: offsets dx=0 and dx=-3 both clamp to x=1), so the 'patrol' degenerates into standing still or a jittery back-and-forth. Consider skipping waypoints that were clamped (out-of-bounds) or de-duplicating consecutive identical points so the generated path stays meaningful at edges. Was this helpful? React with 👍 / 👎 |
||
|
|
||
| return waypoints; | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Quality: Stray PR_DESCRIPTION_DRAFT.md unrelated to this PR committed
This new file at repo root is a draft PR description for a different issue (#6, world-builder palette schemas) and is unrelated to the NPC placement/patrol feature. It appears to be an accidental commit; remove it before merging to avoid polluting the repository root.
Was this helpful? React with 👍 / 👎