ludic/packages/ludic.npc/spots.ludic

80 lines
3.1 KiB
Text

# 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(npc_st: NpcState, p: NpcPerson, s: NpcStep, x: float, z: float) -> void {
npc_go(npc_st, p, x, z, s.act, npc_secs(npc_st, s.lo, s.hi))
}
function np_spot_here(npc_st: mut NpcState, p: NpcPerson, s: NpcStep) -> bool {
npc_face_ahead(p)
npc_do(npc_st, p, s.act, npc_secs(npc_st, s.lo, s.hi))
return true
}
function np_spot_home(npc_st: mut NpcState, 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(npc_st, p, s.act, npc_secs(npc_st, s.lo, s.hi)) } else { npc_step_go(npc_st, p, s, p.hx, p.hz) }
npc_face(p, fx, fz)
return true
}
function np_spot_near_home(npc_st: mut NpcState, p: NpcPerson, s: NpcStep) -> bool {
if not npc_spot_near(npc_st, p.hx, p.hz, s.near, s.far) { return false }
npc_step_go(npc_st, p, s, npc_st.np_px, npc_st.np_pz)
return true
}
function np_spot_near_here(npc_st: mut NpcState, p: NpcPerson, s: NpcStep) -> bool {
if not npc_spot_near(npc_st, p.x, p.z, s.near, s.far) { return false }
npc_step_go(npc_st, p, s, npc_st.np_px, npc_st.np_pz)
return true
}
# at the water's edge, facing out over it
function np_spot_shore(npc_st: mut NpcState, p: NpcPerson, s: NpcStep, x: float, z: float) -> bool {
if not npc_shore(npc_st, x, z, s.far) { return false }
let wx = npc_st.np_wx
let wz = npc_st.np_wz
npc_step_go(npc_st, p, s, npc_st.np_px, npc_st.np_pz)
npc_face(p, wx, wz)
return true
}
function np_spot_shore_home(npc_st: mut NpcState, p: NpcPerson, s: NpcStep) -> bool { return np_spot_shore(npc_st, p, s, p.hx, p.hz) }
function np_spot_shore_here(npc_st: mut NpcState, p: NpcPerson, s: NpcStep) -> bool { return np_spot_shore(npc_st, p, s, p.x, p.z) }
function np_spot_wander(npc_st: mut NpcState, p: NpcPerson, s: NpcStep) -> bool {
npc_wander(npc_st, p)
return true
}
# a few steps somewhere that can actually be walked to, after being stuck
export function npc_wander(npc_st: mut NpcState, p: NpcPerson) -> void {
for t in 0 .. 16 {
let ang = npc_rnd(npc_st) * NP_TAU
let d = 8.0 + npc_rnd(npc_st) * 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(npc_st, p, x, z, NPCA_IDLE, npc_secs(npc_st, 5, 12))
return
}
}
npc_face_ahead(p)
npc_do(npc_st, p, NPCA_IDLE, 8.0)
}