78 lines
3.0 KiB
JavaScript
78 lines
3.0 KiB
JavaScript
// 临时:验证 onMobVictim 否决钩子语义(跑完删除)
|
||
import camp from './src/games/starve/mods/camp.js'
|
||
|
||
let fails = 0
|
||
const ok = (c, m) => { if (c) console.log(' PASS', m); else { fails++; console.error(' FAIL', m) } }
|
||
|
||
const HOOK = camp.hooks.onMobVictim
|
||
function makeG() {
|
||
const g = {
|
||
mon: { hound: { hostile: true }, icehound: { hostile: true }, pig: { friendly: true } },
|
||
players: [],
|
||
monsters: [],
|
||
entities: [{ type: 'camphouse', x: 0, y: 0 }],
|
||
worldW: 0,
|
||
worldH: 0,
|
||
}
|
||
// 模拟核心 g.allows:任一 mod 返回 false 即 false
|
||
g.allows = (name, mm, vv) => HOOK(g, mm, vv) !== false
|
||
return g
|
||
}
|
||
|
||
console.log('== onMobVictim 否决语义 ==')
|
||
const g = makeG()
|
||
const hound = { kind: 'hound', x: 800, y: 800 }
|
||
const pig = { kind: 'pig', x: 800, y: 800 }
|
||
|
||
const inCamp = { x: 100, y: 100 } // 距房(0,0) ~141 < 420
|
||
const outside = { x: 800, y: 800 } // 距房 ~1131 > 420
|
||
|
||
ok(HOOK(g, hound, inCamp) === false, '营地内玩家 → 返回 false(怪不选他)')
|
||
ok(HOOK(g, hound, outside) !== false, '营地外玩家 → 不返回 false')
|
||
ok(HOOK(g, pig, inCamp) !== false, '非敌对生物 → 不返回 false(保留打守卫/猪人)')
|
||
ok(g.allows('onMobVictim', hound, inCamp) === false, 'g.allows 透传 false 正确')
|
||
ok(g.allows('onMobVictim', hound, outside) === true, 'g.allows 透传 true 正确')
|
||
|
||
console.log('== 端点边界 ==')
|
||
ok(HOOK(g, hound, { x: 419, y: 0 }) === false, '半径内 419 → false')
|
||
ok(HOOK(g, hound, { x: 421, y: 0 }) !== false, '半径外 421 → 允许')
|
||
|
||
console.log('== 无房屋时退回世界中心 ==')
|
||
const g2 = makeG()
|
||
g2.entities = []
|
||
g2.worldW = 1000
|
||
g2.worldH = 1000
|
||
ok(HOOK(g2, hound, { x: 600, y: 500 }) === false, '无房屋→以世界中心(500,500)为圆心,100 距离内 → false')
|
||
ok(HOOK(g2, hound, { x: 1200, y: 500 }) !== false, '无房屋→距世界中心 700 → 允许')
|
||
ok(HOOK(g2, hound, { x: 500, y: 500 }) === false, '世界中心本身 → false')
|
||
|
||
console.log('== 模拟核心 nearestVictim:营地内玩家被排除 ==')
|
||
{
|
||
// 复刻 mobs.js nearestVictim 的玩家循环(含 g.allows 否决)
|
||
const pick = (gg, m) => {
|
||
let best = null
|
||
let bd = Infinity
|
||
gg.players.forEach((p) => {
|
||
if (p.dead) return
|
||
if (gg.allows && gg.allows('onMobVictim', m, p) === false) return
|
||
const d = Math.hypot(p.x - m.x, p.y - m.y)
|
||
if (d < bd) { bd = d; best = p }
|
||
})
|
||
return best
|
||
}
|
||
const gg = makeG()
|
||
const m = { kind: 'hound', x: 300, y: 300 }
|
||
const pIn = { dead: false, x: 100, y: 100 } // 营地内,离怪更近 (~283)
|
||
const pOut = { dead: false, x: 900, y: 900 } // 营地外,离怪更远 (~849)
|
||
gg.players = [pIn, pOut]
|
||
ok(pick(gg, m) === pOut, '营地内玩家被否决,目标落到营地外玩家')
|
||
|
||
// 若营地内玩家是唯一玩家 → 无目标(怪待命)
|
||
const gg2 = makeG()
|
||
gg2.players = [pIn]
|
||
ok(pick(gg2, { kind: 'hound', x: 300, y: 300 }) === null, '仅营地内玩家 → 无目标(怪待命,符合 updHound if(!near)return)')
|
||
}
|
||
|
||
console.log(`\n${fails} 项失败`)
|
||
process.exit(fails ? 1 : 0)
|