更新饥荒
This commit is contained in:
@@ -1384,7 +1384,8 @@ const gCtx = {
|
||||
return f
|
||||
},
|
||||
// 否决型钩子调用器(供 mod 使用):任一 mod 返回 false 即返回 false
|
||||
allows: (name, ...args) => callAllows(modRt, name, ...args),
|
||||
// 与核心其它钩子一致,gCtx 作为钩子首参自动前置,mod 侧签名统一为 (g, ...)
|
||||
allows: (name, ...args) => callAllows(modRt, name, gCtx, ...args),
|
||||
me: () => player,
|
||||
isHost: () => isHostRole(),
|
||||
invalidate: () => { invDirty = true },
|
||||
|
||||
@@ -338,18 +338,22 @@ export default {
|
||||
name: '水井',
|
||||
conf: { size: 30, struct: true },
|
||||
init(e) {
|
||||
if (e.cd == null) e.cd = 0
|
||||
// 冷却必须放在 e.mx 里:核心只序列化 e.mx(+ e.state),放 e.cd 会存档/联机丢失
|
||||
if (!e.mx) e.mx = { cd: 0 }
|
||||
if (e.mx.cd == null) e.mx.cd = 0
|
||||
},
|
||||
update(e, dt, g) {
|
||||
if (e.cd > 0) e.cd = Math.max(0, e.cd - dt)
|
||||
const cd = e.mx?.cd || 0
|
||||
if (cd > 0) e.mx.cd = Math.max(0, cd - dt)
|
||||
},
|
||||
interact(p, e, g) {
|
||||
if (e.cd > 0) {
|
||||
g.ptip(p, `井水还没续满……(${Math.ceil(e.cd)} 秒)`)
|
||||
const cd = e.mx?.cd || 0
|
||||
if (cd > 0) {
|
||||
g.ptip(p, `井水还没续满……(${Math.ceil(cd)} 秒)`)
|
||||
return
|
||||
}
|
||||
p.san += 5
|
||||
e.cd = 60
|
||||
e.mx = { ...(e.mx || {}), cd: 60 }
|
||||
g.markDirty(e)
|
||||
g.swing(p, 'eat')
|
||||
g.ptip(p, '打了一瓢清水,理智 +5')
|
||||
|
||||
@@ -94,6 +94,15 @@ function campCenter(g) {
|
||||
if (house) return { x: house.x, y: house.y }
|
||||
return { x: g.worldW / 2, y: g.worldH / 2 }
|
||||
}
|
||||
// 全部营地房屋(用于绘制每一座的安全区边界)
|
||||
function campHouseList(g) {
|
||||
return g.entities.filter((e) => e.type === 'camphouse')
|
||||
}
|
||||
// 玩家在「任意一座」营地房屋的 CAMP_R 内都算进入营地 —— 自建的分基地同样生效。
|
||||
// ⚠️ 这里不能用 find 只取第一座,否则玩家再造房屋不会扩展安全区。
|
||||
function inCamp(g, x, y) {
|
||||
return g.entities.some((e) => e.type === 'camphouse' && Math.hypot(x - e.x, y - e.y) < CAMP_R)
|
||||
}
|
||||
export default {
|
||||
id: 'camp',
|
||||
name: '营地',
|
||||
@@ -435,21 +444,21 @@ export default {
|
||||
// 只对敌对生物生效(保留「怪可以去打守卫/猪人」的能力)。
|
||||
if (!g.mon[m.kind]?.hostile) return
|
||||
// 判断依据是「受害者在不在营地内」,怪本身不做任何位移(无跳变)。
|
||||
const center = g.entities.find((e) => e.type === 'camphouse') || { x: g.worldW / 2, y: g.worldH / 2 }
|
||||
if (Math.hypot(victim.x - center.x, victim.y - center.y) < CAMP_R) return false
|
||||
if (inCamp(g, victim.x, victim.y)) return false
|
||||
},
|
||||
onDraw(g, ctx, env) {
|
||||
// 虚线画出营地领地边界(世界坐标位置,画布为屏幕坐标系,故减去相机)
|
||||
const c = campCenter(g)
|
||||
const sx = c.x - env.camX
|
||||
const sy = c.y - env.camY
|
||||
// 虚线画出**每一座**营地房屋的领地边界(世界坐标 → 画布屏幕坐标,故减去相机)
|
||||
const houses = campHouseList(g)
|
||||
const list = houses.length ? houses : [campCenter(g)]
|
||||
ctx.save()
|
||||
ctx.strokeStyle = 'rgba(255,220,140,0.35)'
|
||||
ctx.lineWidth = 2
|
||||
ctx.setLineDash([10, 8])
|
||||
ctx.beginPath()
|
||||
ctx.ellipse(sx, sy, CAMP_R, CAMP_R * 0.62, 0, 0, TAU)
|
||||
ctx.stroke()
|
||||
for (const h of list) {
|
||||
ctx.beginPath()
|
||||
ctx.ellipse(h.x - env.camX, h.y - env.camY, CAMP_R, CAMP_R * 0.62, 0, 0, TAU)
|
||||
ctx.stroke()
|
||||
}
|
||||
ctx.restore()
|
||||
},
|
||||
onDrawUI(g, ctx, env) {
|
||||
|
||||
@@ -341,12 +341,15 @@ export default {
|
||||
g.ptip(p, '需要剪刀才能剪羊毛')
|
||||
return
|
||||
}
|
||||
if (m.shearDay === g.day) {
|
||||
// 剪毛冷却记在 m.state 上:mob 只持久化 state / loyalT 等少数字段,
|
||||
// 自定义字段(如 m.shearDay)存档与联机都会丢,会导致读档后可重复剪毛
|
||||
const sheared = Number(String(m.state || '').replace('sheared:', '')) || -1
|
||||
if (sheared === g.day) {
|
||||
g.ptip(p, '羊毛还没长回来(需等到明天)')
|
||||
return
|
||||
}
|
||||
g.addItem(p, 'wool', 2)
|
||||
m.shearDay = g.day
|
||||
m.state = `sheared:${g.day}`
|
||||
g.ptip(p, '给绵羊剪下一团羊毛')
|
||||
g.swing(p, 'chop')
|
||||
},
|
||||
|
||||
@@ -277,18 +277,20 @@ export default {
|
||||
name: '蒸汽机',
|
||||
conf: { size: 38, struct: true },
|
||||
init(e) {
|
||||
if (e.fuel == null) e.fuel = 0
|
||||
if (e.on == null) e.on = false
|
||||
// 燃料必须放在 e.mx 里:核心只序列化 e.mx(+ e.state),放 e.fuel 会存档/联机丢失
|
||||
if (!e.mx) e.mx = { fuel: 0 }
|
||||
if (e.mx.fuel == null) e.mx.fuel = 0
|
||||
e.on = e.mx.fuel > 0
|
||||
},
|
||||
update(e, dt, g) {
|
||||
e.on = (e.fuel || 0) > 0
|
||||
e.on = (e.mx?.fuel || 0) > 0
|
||||
},
|
||||
interact(p, e, g) {
|
||||
if (g.hasCost(p, { log: 1 })) {
|
||||
g.payCost(p, { log: 1 })
|
||||
e.fuel = (e.fuel || 0) + 3
|
||||
e.mx = { ...(e.mx || {}), fuel: (e.mx?.fuel || 0) + 3 }
|
||||
g.markDirty(e)
|
||||
g.ptip(p, `投入木头,蒸汽机燃料剩余 ${e.fuel}`)
|
||||
g.ptip(p, `投入木头,蒸汽机燃料剩余 ${e.mx.fuel}`)
|
||||
} else {
|
||||
g.ptip(p, '蒸汽机需要木头作燃料')
|
||||
}
|
||||
@@ -341,7 +343,7 @@ export default {
|
||||
name: '工厂',
|
||||
conf: { size: 40, struct: true },
|
||||
interact(p, e, g) {
|
||||
const powered = g.entities.some((s) => s.type === 'steamengine' && s.on && Math.hypot(s.x - e.x, s.y - e.y) < STEAM_RANGE)
|
||||
const powered = g.entities.some((s) => s.type === 'steamengine' && (s.mx?.fuel || 0) > 0 && Math.hypot(s.x - e.x, s.y - e.y) < STEAM_RANGE)
|
||||
if (!powered) {
|
||||
g.ptip(p, '需要通蒸汽动力(在附近建蒸汽机并加燃料)')
|
||||
return
|
||||
@@ -402,7 +404,7 @@ export default {
|
||||
name: '自动矿机',
|
||||
conf: { size: 34, struct: true },
|
||||
interact(p, e, g) {
|
||||
const powered = g.entities.some((s) => s.type === 'steamengine' && s.on && Math.hypot(s.x - e.x, s.y - e.y) < STEAM_RANGE)
|
||||
const powered = g.entities.some((s) => s.type === 'steamengine' && (s.mx?.fuel || 0) > 0 && Math.hypot(s.x - e.x, s.y - e.y) < STEAM_RANGE)
|
||||
g.ptip(p, powered ? '矿机正在满速运转(每台每天自动开采)' : '缺少蒸汽动力,效率减半')
|
||||
},
|
||||
draw(ctx, e, env) {
|
||||
@@ -450,14 +452,14 @@ export default {
|
||||
onNewDay(g) {
|
||||
// 自动矿机开采:附近有供能的蒸汽机则翻倍
|
||||
g.entities.filter((e) => e.type === 'miner').forEach((m) => {
|
||||
const powered = g.entities.some((s) => s.type === 'steamengine' && s.on && Math.hypot(s.x - m.x, s.y - m.y) < STEAM_RANGE)
|
||||
const powered = g.entities.some((s) => s.type === 'steamengine' && (s.mx?.fuel || 0) > 0 && Math.hypot(s.x - m.x, s.y - m.y) < STEAM_RANGE)
|
||||
g.dropLoot(m.x + g.rand(-24, 24), m.y + g.rand(-24, 24), 'rock', powered ? 4 : 2)
|
||||
g.dropLoot(m.x + g.rand(-24, 24), m.y + g.rand(-24, 24), 'flint', powered ? 2 : 1)
|
||||
})
|
||||
// 蒸汽机每日消耗 1 份燃料
|
||||
// 蒸汽机每日消耗 1 份燃料(燃料存在 e.mx.fuel,随存档与联机同步)
|
||||
g.entities.filter((e) => e.type === 'steamengine').forEach((s) => {
|
||||
s.fuel = Math.max(0, (s.fuel || 0) - 1)
|
||||
s.on = s.fuel > 0
|
||||
s.mx = { ...(s.mx || {}), fuel: Math.max(0, (s.mx?.fuel || 0) - 1) }
|
||||
s.on = s.mx.fuel > 0
|
||||
g.markDirty(s)
|
||||
})
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user