ludic/packages/ludic.npc/mirror.ludic

75 lines
2.6 KiB
Text

# mirror.ludic - a guest draws the host's people: no routine and no census here, a slot filled or
# emptied as the host says, and each one eased toward where it was last heard to be
# on: this machine's own walkers leave, and only the host's are drawn until it is turned off
export function npc_mirror(npc_st: mut NpcState, on: bool) -> void {
if npc_st.np_mirror == on { return }
npc_st.np_mirror = on
for i in 0 .. len(npc_st.np_walkers) { npc_retire(npc_st, npc_st.np_walkers[i]) }
if not on { npc_census_now(npc_st) }
}
export function npc_mirroring(npc_st: NpcState) -> bool { return npc_st.np_mirror }
# the host's slot: somebody new in it (born), or nobody (gone)
export function npc_put(npc_st: mut NpcState, slot: int, id: int, kind: int, look: int, seed: float, name: string, hx: float, hz: float) -> NpcPerson {
if slot < 0 or slot >= npc_st.np_max or kind < 0 or kind >= NPCK_COUNT { return null }
@alloc_ok("a guest's copy of the host's slots, no more than np_max")
while len(npc_st.np_walkers) <= slot {
let q = new NpcPerson
q.slot = len(npc_st.np_walkers)
push(npc_st.np_walkers, q)
}
let p = npc_st.np_walkers[slot]
if p.active and p.id == id { return p }
if p.active { npc_retire(npc_st, p) }
np_fresh(p, kind, look)
p.id = id
p.seed = seed
p.name = name
npc_set_at(p, hx, hz)
p.active = true
npc_st.np_n += 1
NpcWorld.born(p)
return p
}
# where the host says it is now, and what it is doing
export function npc_heard(npc_st: NpcState, slot: int, x: float, y: float, z: float, yaw: float, speed: float, act: int, stalk: bool) -> void {
let p = npc_at(npc_st, slot)
if p == null or not p.active { return }
if not p.heard {
p.x = x
p.y = y
p.z = z
p.yaw = yaw
}
p.heard = true
p.heard_t = npc_st.np_clock
p.nx = x
p.ny = y
p.nz = z
p.nyaw = yaw
p.speed = speed
p.act = act
p.stalk = stalk
}
# heard from in the last six seconds: drawn; not, and it is not drawn until it is again
export function npc_heard_lately(npc_st: NpcState, p: NpcPerson) -> bool { return p.heard and npc_st.np_clock - p.heard_t <= 6.0 }
export function npc_mirror_tick(npc_st: mut NpcState, dt: float) -> void {
npc_st.np_clock = npc_st.np_clock + dt
let k = Math.min(1.0, dt * 8.0)
for i in 0 .. len(npc_st.np_walkers) {
let p = npc_st.np_walkers[i]
if not p.active or not npc_heard_lately(npc_st, p) { continue }
let ox = p.x
let oz = p.z
p.x = p.x + (p.nx - p.x) * k
p.y = p.y + (p.ny - p.y) * k
p.z = p.z + (p.nz - p.z) * k
p.yaw = p.yaw + npc_wrap(p.nyaw - p.yaw) * k
if p.act == NPCA_WALK { p.phase = p.phase + npc_d(ox, oz, p.x, p.z) * 2.6 }
}
}