feat(packages): ludic.npc - the other people in a place: kinds, spots, acts, names and lines as open registries (a kind's routine is steps by the hour - a spot, an act, how long - with its own start and plan as function values, readable from .lres), a census on the half hour by weight (after dark only who stays out) with an extra the place asks for, walking round what is in the way and never into the water or up a scramble, no act where the place says nobody stops, facing a player within notice and back to the errand, leaving only out of every player's sight, unique names, posts that never walk (a vendor), lines by prio and chance with the story's words through a port and choices, a guest's copy of a host's people; greeted, talked and arrived as facts
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
73a376ac6c
commit
029a1ebba2
23 changed files with 1664 additions and 0 deletions
80
packages/ludic.npc/spots.ludic
Normal file
80
packages/ludic.npc/spots.ludic
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
# spots.ludic - the spots every place has: here, home, somewhere near home or near here, the shore
|
||||
# near either, and a few steps anywhere that can be walked to. A game adds its own (a sign, an
|
||||
# animal) as `def NpcSpots`; each sends the person with npc_go / npc_do and says whether it could.
|
||||
def NpcSpots here { find: fn np_spot_here }
|
||||
def NpcSpots home { find: fn np_spot_home }
|
||||
def NpcSpots near_home { find: fn np_spot_near_home }
|
||||
def NpcSpots near_here { find: fn np_spot_near_here }
|
||||
def NpcSpots shore_home { find: fn np_spot_shore_home }
|
||||
def NpcSpots shore_here { find: fn np_spot_shore_here }
|
||||
def NpcSpots wander { find: fn np_spot_wander }
|
||||
|
||||
# the step's act for the step's time, at (x, z)
|
||||
export function npc_step_go(p: NpcPerson, s: NpcStep, x: float, z: float) -> void {
|
||||
npc_go(p, x, z, s.act, npc_secs(s.lo, s.hi))
|
||||
}
|
||||
|
||||
function np_spot_here(p: NpcPerson, s: NpcStep) -> bool {
|
||||
npc_face_ahead(p)
|
||||
npc_do(p, s.act, npc_secs(s.lo, s.hi))
|
||||
return true
|
||||
}
|
||||
|
||||
function np_spot_home(p: NpcPerson, s: NpcStep) -> bool {
|
||||
var fx = p.hx - Math.sin(p.yaw) * 5.0
|
||||
var fz = p.hz - Math.cos(p.yaw) * 5.0
|
||||
if p.home_face {
|
||||
fx = p.hfx
|
||||
fz = p.hfz
|
||||
}
|
||||
if npc_d(p.x, p.z, p.hx, p.hz) < 2.0 { npc_do(p, s.act, npc_secs(s.lo, s.hi)) } else { npc_step_go(p, s, p.hx, p.hz) }
|
||||
npc_face(p, fx, fz)
|
||||
return true
|
||||
}
|
||||
|
||||
function np_spot_near_home(p: NpcPerson, s: NpcStep) -> bool {
|
||||
if not npc_spot_near(p.hx, p.hz, s.near, s.far) { return false }
|
||||
npc_step_go(p, s, np_px, np_pz)
|
||||
return true
|
||||
}
|
||||
|
||||
function np_spot_near_here(p: NpcPerson, s: NpcStep) -> bool {
|
||||
if not npc_spot_near(p.x, p.z, s.near, s.far) { return false }
|
||||
npc_step_go(p, s, np_px, np_pz)
|
||||
return true
|
||||
}
|
||||
|
||||
# at the water's edge, facing out over it
|
||||
function np_spot_shore(p: NpcPerson, s: NpcStep, x: float, z: float) -> bool {
|
||||
if not npc_shore(x, z, s.far) { return false }
|
||||
let wx = np_wx
|
||||
let wz = np_wz
|
||||
npc_step_go(p, s, np_px, np_pz)
|
||||
npc_face(p, wx, wz)
|
||||
return true
|
||||
}
|
||||
|
||||
function np_spot_shore_home(p: NpcPerson, s: NpcStep) -> bool { return np_spot_shore(p, s, p.hx, p.hz) }
|
||||
|
||||
function np_spot_shore_here(p: NpcPerson, s: NpcStep) -> bool { return np_spot_shore(p, s, p.x, p.z) }
|
||||
|
||||
function np_spot_wander(p: NpcPerson, s: NpcStep) -> bool {
|
||||
npc_wander(p)
|
||||
return true
|
||||
}
|
||||
|
||||
# a few steps somewhere that can actually be walked to, after being stuck
|
||||
export function npc_wander(p: NpcPerson) -> void {
|
||||
for t in 0 .. 16 {
|
||||
let ang = npc_rnd() * NP_TAU
|
||||
let d = 8.0 + npc_rnd() * 18.0
|
||||
let x = p.x + Math.cos(ang) * d
|
||||
let z = p.z + Math.sin(ang) * d
|
||||
if npc_walkable(x, z) and npc_line_ok(p.x, p.z, x, z) {
|
||||
npc_go(p, x, z, NPCA_IDLE, npc_secs(5, 12))
|
||||
return
|
||||
}
|
||||
}
|
||||
npc_face_ahead(p)
|
||||
npc_do(p, NPCA_IDLE, 8.0)
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue