world.say('开始运行'); console.log('开始运行'); //table2(now) //newTable(old) //oldTable(dropped) const Adds = [ '广告招商中……', ]; const SmartPlayWays = [ '文具残血时可以使单击鼠标右键/触屏B键快速维修', '结算大量分数有几率获得小橡皮和文具盲盒', '部分隐藏功能平常不会出现,等您发现它们您就知道它们什么时候出现了', '文具盲盒需要一些时间准备,但开启后可以获得大量文具和小橡皮', '俯视视角下与文具交互即可弹', '如果不会玩可以问问周围的人哦', '本游戏公测中,欢迎在评论区反馈bug', ]; const Pens = { //名称,重量,摩擦力,大小,耐久,稀有度(越高越稀有) '铅笔': [0.5, 0.4, 0.3, 30, 0], '蜡笔': [0.4, 0.4, 0.2, 20, 1], '钢笔': [0.6, 0.4, 0.2, 20, 0], '尺子': [0.5, 0.5, 0.3, 30, 0], '圆规': [0.6, 0.4, 0.4, 30, 2], '剪刀': [0.6, 0.4, 0.7, 30, 3], '橡皮': [0.5, 0.5, 0.2, 40, 2], '马克笔': [0.3, 0.4, 0.2, 40, 1], '修正带': [0.3, 0.3, 0.3, 25, 1], '口香糖': [0.5, 0.7, 0.7, 30, 2] } const GameRunTime = 120; const PYP = 10; const Bosses = { //名称,大小 '水壶': [0.2], '笔盒': [0.4], '字典': [0.4], '笔记本': [0.4], '瓶子': [0.4] } const BoxesPenNum = { '普通文具盲盒': 1, '幸运文具盲盒': 2, '巨型文具盲盒': 3, } let BoxNames = []; for (const l in BoxesPenNum) { BoxNames.push(l); } function randomPos() { return new Box3Vector3(10 + Math.round(Math.random() * 107), 5, 10 + Math.round(Math.random() * 107)); } function sPW() { return '[小技巧]' + SmartPlayWays[Math.floor(Math.random() * SmartPlayWays.length)]; } function add() { return `[广告]${Adds[Math.floor(Math.random() * Adds.length)]}`; } let penNames = [], bossNames = []; for (const l in Pens) { penNames.push(l); } for (const l in Bosses) { bossNames.push(l); } function howRare(pen) { if (!penNames.includes(pen)) throw `pen "${pen}" is not defined`; const r = Pens[pen][4]; if (r == 0) { return '普通'; } else if (r == 1) { return '罕见'; } else if (r == 2) { return '史诗'; } else { return '传奇'; } } function getaPen() { const s = penNames[Math.floor(Math.random() * penNames.length)]; let index = Pens[s][4]; if (index > 1 && Math.random() > 0.6) { return getaPen(); } else if (index > 2 && Math.random() > 0.6) { return getaPen(); } else if (index > 3 && Math.random() > 0.6) { return getaPen(); } else { return s; } } var getStore = () => { let list = []; world.querySelectorAll('.p').forEach(p => { if (p.sale.length > 0) { list = list.concat(p.sale); } }); return list; }; let Help = `※如何弹我的笔? 我们提供了两种操作方式。无论使用哪种方式,笔都将在您弹被从您的昵称显示处弹出。 1.交互式 触屏时,点击您自己的笔上的圆圈。使用键盘时,请按照代码岛提供的方式与您的笔交互。 2.鼠标式 该方式在俯视视角下不可用 请使用触屏A建/鼠标左键点击您的笔。 ※我无法找到我的笔 当您正在参与游戏且与您的笔距离较远时,触屏B键/鼠标右键唤出的菜单中会出现“传送到笔所在位置”选项。 ※我无法滑动查看下面的内容 这是Box3的问题导致,请尝试重进。 ※上面的内容我都看了,对我没有帮助 很抱歉我们没能帮到您。我们希望你能将您的问题写在地图评论区,因为您的疑惑可能代表了许多人的疑惑。 `; world.gameRanTime = 0; (async function setUp() { await db.sql`CREATE TABLE IF NOT EXISTS table2 ( "name" TINYTEXT NOT NULL PRIMARY KEY UNIQUE, "joinTime" TINYINT NOT NULL, "items" TEXT NOT NULL, "score" TINYINT NOT NULL, "money" TINYINT NOT NULL, "dialogColor" TINYTEXT NOT NULL, "boxes" TINYTEXT NOT NULL, "cameraMode" BOOL NOT NULL, "sale" TINYTEXT NOT NULL )`; await db.sql`DROP TABLE IF EXISTS oldTable`; world.say('数据库启动成功'); })().catch((e) => { world.say(e); }); var update = async function (user) { if (!user || !user.isPlayer) throw `update fail because of wrong value`; if (!user.player.userKey) return; try { await db.sql`INSERT INTO table2 ( name, items, score, joinTime, money, dialogColor, boxes, cameraMode, sale )VALUES( ${user.player.name}, ${JSON.stringify(user.items)}, ${user.score}, ${user.joinTime}, ${user.smallErasers}, ${JSON.stringify(user.dC)}, ${JSON.stringify(user.boxes)}, ${['follow', 'relative'].indexOf(user.player.cameraMode)}, ${JSON.stringify(user.sale)} )ON CONFLICT(name) DO UPDATE SET items = excluded.items, score = excluded.score, joinTime = excluded.joinTime, money = excluded.money, dialogColor = excluded.dialogColor, boxes = excluded.boxes, cameraMode = excluded.cameraMode, sale = excluded.sale `; } catch (e) { world.say(`sql Insert Error:${e}`); } } var load = async function (user) { if (!user || !user.isPlayer) throw `load fail because of wrong value`; if (!user.player.userKey) return; let data; let nDT = `SELECT * FROM table2 WHERE name = "${user.player.name}" LIMIT 1`; const newData = (await db.sql([nDT]))[0]; const oldData = (await db.sql`SELECT * FROM newTable WHERE name=${user.player.name} LIMIT 1`)[0]; if (newData) { data = newData; if (oldData) await db.sql`DELETE FROM newTable WHERE name = ${user.player.name}`; } else if (oldData) { data = oldData; } if (typeof data == "object") { user.boxes = JSON.parse(data.boxes); user.items = JSON.parse(data.items); user.score = data.score; user.joinTime = data.joinTime + 1; user.smallErasers = data.money; user.dC = JSON.parse(data.dialogColor); if (data.cameraMode == 1) { user.setUpCameraRelativeMode(); } if(data.sale){ user.sale = JSON.parse(data.sale); } return true; } else { user.joinTime += 1; await update(user); return false; } } function p(name = '') { return world.querySelectorAll('player').find(e => e.player.name.startsWith(name)) ? world.querySelectorAll('player').find(e => e.player.name.startsWith(name)) : world.say(`cannot find player whos name startsWith"${name}"`); } Object.assign(Box3Entity.prototype, { items: [], playing: false, score: 0, sale: [], killed: 0, smallErasers: 2, kick: function () { this.player.link(this.player.url, { isConfirm: false, isNewTab: false }); }, joinTime: 0, boxes: [ ['普通文具盲盒', null] ], dC: [new Box3RGBAColor(0.9, 0.7, 0.3, 1), new Box3RGBAColor(1, 1, 1, 1), new Box3RGBAColor(1, 1, 1, 1), new Box3RGBAColor(0, 0, 0, 1)], async textDialog(title, content) { try { this.dialog = await this.player.dialog({ type: "text", title: title, content: content, hasArrow: true, titleBackgroundColor: this.dC[0], titleTextColor: this.dC[1], contentBackgroundColor: this.dC[2], contentTextColor: this.dC[3] }); return this.dialog; } catch (e) { } }, async selectDialog(title, content, options) { try { this.dialog = await this.player.dialog({ type: "select", title: title, content: content, options: options, titleBackgroundColor: this.dC[0], titleTextColor: this.dC[1], contentBackgroundColor: this.dC[2], contentTextColor: this.dC[3] }); return this.dialog; } catch (e) { } }, async inputDialog(title, content, placeholder, confirmText) { this.dialog = await this.player.dialog({ type: "input", title: title, content: content, placeholder: placeholder, console: confirmText, titleBackgroundColor: this.dC[0], titleTextColor: this.dC[1], contentBackgroundColor: this.dC[2], contentTextColor: this.dC[3] }); return this.dialog; }, attacker: { id: '未获取到攻击者' }, getBox: async function (BoxLv = 0) { this.boxes.unshift([['普通文具盲盒', '幸运文具盲盒', '巨型文具盲盒'][BoxLv], null]); }, joinGame: async function () { this.player.cancelDialogs(); this.position = randomPos(); sleep(10000).then(() => { if (this.playing == false) { this.player.cancelDialogs(); } }); await this.selectDialog('加入游戏', `请选择您的参战文具(限时10秒)\n${sPW()}`, this.items); if (!this.dialog || this.dialog == null) { this.playing = false; return; } if (!penNames.includes(this.dialog.value)) { world.say(`⚠pen "${this.dialog.value}" is not defined⚠`); this.playing = false; return; } this.pen = world.createEntity({ id: `${this.player.name} 的 ${this.dialog.value}`, mesh: `mesh/${this.dialog.value}.vb`, meshScale: new Box3Vector3(0.2, 0.2, 0.2), position: this.position, mass: Pens[this.dialog.value][0] * 2, friction: Pens[this.dialog.value][1], collides: true, restitution: 0.7, meshScale: new Box3Vector3(Pens[this.dialog.value][2], Pens[this.dialog.value][2], Pens[this.dialog.value][2]), interactColor: new Box3RGBColor(0, 1, 1), interactRadius: 50 }); this.pen.addTag('pen'); this.pen.enableInteract = true; this.pen.interactHint = this.pen.id; this.pen.hp = this.pen.maxHp = Pens[this.dialog.value][3]; this.pen.enableDamage = true; this.pen.showHealthBar = false; this.pen.owner = this; this.pen.onDestroy(onDestroy); this.playing = true; this.player.cancelDialogs(); }, setUpCameraRelativeMode: async function () { this.player.cameraMode = "relative"; this.player.cameraPosition = new Box3Vector3(-0.01, 40, 0); this.player.swapInputDirection = true; this.player.freezedForwardDirection = new Box3Vector3(0, 0, 1); this.player.reverseInputDirection = Box3InputDirection.HORIZONTAL; this.player.cameraFreezedAxis = Box3CameraFreezedAxis.Y; this.player.freezedForwardDirection = new Box3Vector3(0, 0, 1); this.player.canFly = false; this.player.invisible = true; }, exitGame: async function (killed = 0) { let t = `结算了${killed}分数`; this.score += killed; if (killed > 0) { let w = ''; if (killed > 3) { w = 2; } else if (killed > 1) { w = 1; } else { w = 0; } t += `,您获得了${BoxNames[w]}\n${add()}`; this.getBox(w); } this.pen.killed = 0; this.pen.destroy(); return t; } }); world.onPlayerJoin(async ({ entity }) => { entity.id = entity.player.name; entity.player.spectator = true; entity.player.cameraPosition = new Box3Vector3(-0.01, 50, 0); await load(entity); if (!entity.player.userKey) { await entity.textDialog('登录失败', '您仍可以正常游戏,但您的数据不会被保存。' ); } if (entity.joinTime < 2) { await entity.textDialog( world.projectName, `欢迎您, ${entity.id}` ); do { await entity.selectDialog('新手引导', '请选择您的初始文具。稍后您可以通过文具盲盒活动更多文具', [penNames[0], penNames[1], penNames[2]] ); } while (!entity.dialog || entity.dialog == null); entity.items = [entity.dialog.value]; do { await entity.selectDialog('新手引导', '请选择您的视角。鼠标建议选择跟随视角,触屏建议选择俯视视角。', ['俯视视角', '跟随视角'] ); } while (!entity.dialog || entity.dialog == null); switch (entity.dialog.value) { case '俯视视角': entity.setUpCameraRelativeMode(); break; } await entity.textDialog('帮助', Help); await entity.textDialog('新手引导', '请关闭此对话框,然后点击触屏B键/鼠标右键报名参加游戏/查看帮助。'); } entity.addTag('p'); if (entity.items.includes('粉笔')) { entity.items.splice(entity.items.indexOf('粉笔'), 1, '蜡笔'); } if (entity.player.cameraMode == "follow") { entity.player.canFly = true; } entity.player.forceRespawn(); }); world.onPlayerLeave(async ({ entity }) => { if (entity.pen) { entity.pen.attacker = entity; entity.pen.destroy(); } }); world.onChat(async ({ entity: { player: { name } }, entity, message }) => { if (message.startsWith('$') && (world.Admins.includes(name))) { let code = message.slice(1); world.say(`~> ${code}`); try { if (code.includes('await')) { code = eval((async function () { code })()); } else { code = eval(code); } } catch (error) { code = error; } finally { world.say(`<~ ${code}`); } } }); world.onEntityContact(async ({ entity, other }) => { if (!(entity.hasTag('pen') && other.hasTag('pen'))) return; entity.hurt(1); entity.attacker = other; }); world.onInteract(async ({ entity, targetEntity }) => { if (!entity.playing || !entity.isPlayer || !targetEntity.hasTag('pen') || entity.position.distance(targetEntity.position) > 20) return; if (!targetEntity.owner || !((targetEntity.id).slice(0, targetEntity.id.indexOf(' ')) == entity.player.name)) { entity.player.directMessage(`这是 ${targetEntity.id} 不是您的 ${entity.pen.id}`); return; } entity.player.enableAction0 = false; targetEntity.enableInteract = false; targetEntity.attacker = entity; if (targetEntity.hp == 0) { entity.player.directMessage(`${entity.pen.id} 已损坏,请单击鼠标右键/触屏B键维修`); } else { let d = targetEntity.position.sub(entity.position); let speed = 3; let x = d.x * speed / d.mag(); let z = d.z * speed / d.mag(); targetEntity.velocity.set(x, 0, z); targetEntity.hurt(1); } await sleep(2000); targetEntity.enableInteract = true; entity.player.enableAction0 = true; }); world.onClick(async ({ entity, clicker, raycast: { direction }, button }) => { if (!clicker.playing || button != "action0" || !entity.hasTag('pen') || clicker.player.cameraMode != "follow") return; if (!entity.owner || !(entity.id.slice(0, entity.id.indexOf(' ')) == clicker.player.name)) { clicker.player.directMessage(`这是 ${entity.id} 不是您的 ${clicker.pen.id}`); return; } entity.attacker = clicker; clicker.player.enableAction0 = false; clicker.pen.enableInteract = false; if (entity.hp == 0) { clicker.player.directMessage(`${entity.id} 已损坏,请单击鼠标右键/触屏B键维修`); } else { entity.velocity.copy(direction.scale(2)); entity.hurt(1); } await sleep(2000); clicker.player.enableAction0 = true; clicker.pen.enableInteract = true; }); world.onTick(async ({ tick }) => { if (tick % 4 == 0) { for (const pen of world.querySelectorAll('.pen')) { if (!pen.velocity.equals(new Box3Vector3(0, 0, 0))) { pen.meshOrientation.copy(pen.meshOrientation.rotateY(Math.PI / 20)); } await sleep(1); } for (const p of world.querySelectorAll('.p')) { await update(p); if (p.player.cameraMode == "relative") { p.position.y = 10; } } const t = 64; const a = Math.floor(t * 63 / world.querySelectorAll('.pen').length); if (tick % t != 0) return; world.querySelectorAll('.pen').forEach(async p => { if (p.voxelContacts.length == 0) { await sleep(2000); if (p.voxelContacts.length == 0) p.position = randomPos(); } }); for (const npc of world.querySelectorAll('.npc')) { if (npc.target == null || !npc.target || npc.target.destroyed || npc.target.position.distance(npc.position) > 50) { let c = world.querySelectorAll('.pen'); c.splice(c.indexOf(npc), 1); npc.target = c.sort((a, b) => { return a.position.distance(npc.position) - b.position.distance(npc.position) })[0]; if (!npc.target) continue; } if (npc.hp < 1) continue; let direction; if (npc.position.x > 122 || npc.position.x < 5 || npc.position.z > 115 || npc.position.z < 12) { direction = new Box3Vector3(64, npc.position.y, 64).sub(npc.position); } else { direction = npc.target.position.sub(npc.position); } const dist = direction.mag(); const speed = 0.8; npc.velocity.x = direction.x * speed / dist; npc.velocity.z = direction.z * speed / dist; await sleep(a); } } }); world.onPress(async ({ entity, button }) => { if (button == "action1") { let eto; let opt; let rs = sPW(); if (entity.pen && !entity.pen.destroyed && entity.pen.hp * 2 < entity.pen.maxHp) { entity.player.directMessage('正在维修'); await sleep(1000); entity.pen.hp = entity.pen.maxHp; entity.player.directMessage('维修成功'); return; } while (true) { eto = entity.player.name; opt = ['帮助', '赛季分数排行榜', '游戏设置']; if (entity.pen && !entity.pen.destroyed) { if (entity.pen.hp < (entity.pen.maxHp / 2)) { eto += '[已损坏]'; } if (entity.position.distance(entity.pen.position) > 10) { opt.unshift(`传送至笔所在位置`); } rs += `\n本轮分数:${entity.pen.killed}` } if (entity.playing == false) { //opt.unshift('文具店'); opt.unshift(`文具盲盒(${entity.boxes.length})`); opt.unshift(`文具(${entity.items.length})`); opt.unshift('报名参加游戏'); } if (entity.hasTag('j')) { rs += '\n您已报名参加游戏,下轮游戏开始时会自动加入。'; } await entity.selectDialog( eto, rs + `\n累计分数:${entity.score}\n小橡皮:${entity.smallErasers}`, opt ); if (!entity.dialog || entity.dialog == null) break; if (rs != '') rs = sPW(); switch (entity.dialog.value) { case '帮助': await entity.textDialog('帮助', Help); break; case `传送至笔所在位置`: entity.position.set(entity.pen.position.x, entity.position.y, entity.pen.position.z); rs = '传送成功'; break; case '赛季分数排行榜': let result = `用户名|分数`; for await (const l of db.sql`SELECT name,score FROM table2 ORDER BY score DESC LIMIT 10`) { result += `\n${l.name}|${l.score}`; } await entity.textDialog('测试赛季分数排行榜', result); break; case '游戏设置': while (true) { await entity.selectDialog('游戏设置', undefined, ['对话框颜色设置', '视角设置', '开发者选项','我的贡献']); if (!entity.dialog || entity.dialog == null) break; switch (entity.dialog.value) { case '我的贡献': await entity.textDialog('我的贡献', `您已对地图贡献${entity.joinTime}播放量。`); break; case '对话框颜色设置': await entity.selectDialog('对话框颜色设置', undefined, ['香肠橙', '符文绿'] ); if (!entity.dialog || entity.dialog == null) break; entity.dC = [ [new Box3RGBAColor(0.9, 0.7, 0.3, 1), new Box3RGBAColor(1, 1, 1, 1), new Box3RGBAColor(1, 1, 1, 1), new Box3RGBAColor(0, 0, 0, 1)], [new Box3RGBAColor(0, 0, 0, 1), new Box3RGBAColor(0, 1, 0, 1), new Box3RGBAColor(0, 0, 0, 1), new Box3RGBAColor(0, 1, 0, 1)] ][entity.dialog.index] break; case '开发者选项': await entity.selectDialog('开发者选项', '请谨慎使用这些功能,使用后果请自行承担', ['删档', '代码调试'] ); if (!entity.dialog || entity.dialog == null) break; switch (entity.dialog.value) { case '删档': entity.removeTag('p'); entity.textDialog('删档成功', '您的数据已清除'); await db.sql`DELETE FROM table2 WHERE name = ${entity.player.name}`; await db.sql`DELETE FROM newTable WHERE name = ${entity.player.name}`; await sleep(5000); entity.kick(); break; case '代码调试': if (!world.Admins.includes(entity.player.name)) { rs = '您没有代码执行权限!'; break; } await entity.inputDialog('调试', `欢迎您,管理员 ${entity.player.name}`, undefined, '执行'); if (!entity.dialog || entity.dialog == null) break; world.say(`~> ${entity.dialog}`); try { if (entity.dialog.includes('await')) world.say(`<~ ${eval(`(async function(){${entity.dialog}})()`)}`); else world.say(`<~ ${eval(entity.dialog)}`) } catch (e) { world.say(`< ~${e} `); } break; } break; case '视角设置': await entity.selectDialog('视角设置', `※视角设置后页面可能会自动刷新以生效设置 触屏建议选择俯视视角,鼠标建议选择跟随视角`, ['俯视视角', '跟随视角']); if (!entity.dialog || entity.dialog == null) break; switch (entity.dialog.value) { case '俯视视角': entity.setUpCameraRelativeMode(); break; case '跟随视角': entity.player.cameraMode = "follow"; await update(entity); entity.kick(); break; } break; } } break; case '报名参加游戏': entity.addTag('j'); await entity.textDialog('报名参加成功', `下次游戏开始时,你会自动加入。 ${ sPW()} `) break; case `文具(${entity.items.length})`: if (entity.items.length < 1) { await entity.textDialog('我的文具(0)', `还没有文具。文具可以在文具店购买或打开盲盒获得。 ${sPW()}`); break; } while (true) { await entity.selectDialog( `我的文具(${entity.items.length})`, '', entity.items ); if (!entity.dialog || entity.dialog == null) break; if (!Pens[entity.dialog.value]) { world.say(`⚠pen "${entity.dialog.value}" is not defined⚠`); return; } const i = Pens[entity.dialog.value]; await entity.textDialog( entity.dialog.value, `重量: ${i[0] * 100} 摩擦力: ${ i[1] * 10} 耐久度: ${ i[3]} 稀有度: ${ howRare(entity.dialog.value)} `); } break; case `文具盲盒(${entity.boxes.length})`: if (entity.boxes.length < 1) { await entity.textDialog('我的文具盲盒(0)', `还没有文具盲盒。文具盲盒可以在文具店购买或参与游戏后结算分数获得。 ${sPW()}`); break; } while (entity.boxes.length > 0) { let boxesNames = []; for (const l of entity.boxes) { boxesNames.push(l[0]); } await entity.selectDialog(`我的文具盲盒(${entity.boxes.length})`, sPW(), boxesNames); if (!entity.dialog || entity.dialog == null) break; const boxName = entity.dialog.value; const boxIndex = entity.dialog.index; const box = entity.boxes[boxIndex]; let dsc = ''; let openOpt = []; let time = new Date(); if (box[1] == null) { dsc += `盲盒还未开始准备`; openOpt.unshift('开始准备'); } else { let ts = Math.floor((Date.parse(box[1]) - Date.parse(time)) / 1000); let m = Math.floor(ts / 60); let s = ts - m * 60; if (Date.parse(time) < Date.parse(box[1])) { dsc = `盲盒正在准备,还需${m} 分${s} 秒才可免费打开`; if (entity.smallErasers > 4) { openOpt.unshift(`加速准备(4小橡皮)`); } } else { dsc = '盲盒已经准备就绪,可以免费打开'; openOpt.unshift('立刻打开'); } } await entity.selectDialog(boxName, dsc, openOpt); if (!entity.dialog || entity.dialog == null) break; switch (entity.dialog.value) { case '开始准备': time.setHours(time.getHours() + 1); box[1] = time; break; case '加速准备(4小橡皮)': box[1] = time; entity.smallErasers -= 4; rs = `加速准备完成,剩余${entity.smallErasers} 小橡皮`; break; case '立刻打开': let r = ''; let p = ''; for (let l = 0; l < BoxesPenNum[box[0]]; l++) { p = getaPen(); entity.items.unshift(p); r += `您开出了${p} 。`; } entity.boxes.splice(boxIndex, 1); await entity.textDialog(boxName, `${r} ${sPW()}`); break; } } break; /*case '文具店': while (1) { await entity.selectDialog(`文具店`, `欢迎光临文具店! 您有 ${entity.smallErasers} 小橡皮 ${sPW()}`, ['买文具', '卖文具']) if (!entity.dialog || entity.dialog == null) break; switch (entity.dialog.value) { case '买文具': if (getStore.length < 1) { await entity.textDialog('买文具', '暂时没有在线玩家售卖文具'); break; } await entity.selectDialog(`买文具`, `您有${entity.smallErasers}小橡皮名称|价格(小橡皮)`, list); break; case '卖文具': if (entity.items.length < 1) { await entity.textDialog('卖文具', '您没有可以出售的文具!'); break; } await entity.selectDialog('卖文具', `请选择你要卖的文具。`, entity.items); if (!entity.dialog || entity.dialog == null) break; let name = entity.dialog.value; let price = 0; while (1) { await entity.inputDialog('卖文具', `您已选择出售 ${name} 请输入一个≤100的自然数作为售价。单位:小橡皮`, '请输入', '确认出售'); if (!entity.dialog || entity.dialog == null) break; price = Number(entity.dialog); if (isNaN(price) || price > 100 || price < 0 || price - Math.trunc(price) != 0) { await entity.textDialog('卖文具', `您输入的售价无效。请输入一个≤100的自然数。`); } else { break; } } let saleName = `${entity.player.name} 的 ${name}|${price}`;//待办 entity.sale.push(saleName); await entity.textDialog('卖文具', `${name} 已以 ${price} 价格放在文具店出售。请等待其他人购买。`); break; } } break;*/ } } } }); const PDZ = world.addZone({ selector: '.pen', bounds: { lo: [-20, -10, -20], hi: [148, -1, 148] }, }); PDZ.onEnter(async ({ entity }) => { entity.destroy(); }); async function onDestroy({ entity }) { if (entity.isPlayer) return; if (entity.attacker.hasTag && entity.attacker.hasTag('pen')) { entity.attacker.say(`${entity.attacker.id} 淘汰了 ${entity.id}`); } entity.attacker.killed += 1; if (!entity.owner || entity.owner.destroyed) return; entity.owner.score += entity.killed; entity.owner.playing = false; await entity.owner.textDialog( `游戏结束`, `${world.gameRanTime > 0 ? `您的 ${entity.id} 被 ${entity.attacker.id} 弹下了课桌。` : '本局游戏结束,恭喜您吃鸡!'} ${ await entity.owner.exitGame(entity.killed)} ${ sPW()} ` ); } world.onDie(async ({ entity }) => { if (entity.hasTag('npc')) { await sleep(10000); entity.hp = entity.maxHp; } }); async function createBoss(name = '') { floor('13'); name = bossNames[Math.floor(bossNames.length * Math.random())]; world.say(`- [[boss]${name} 即将出现,请各位玩家做好迎战准备] - `); floor('11').then(async () => { await sleep(2000); floor('13'); await sleep(2000); floor('11'); await sleep(2000); floor('13'); await sleep(2000); floor('11'); await sleep(2000); floor('13'); await sleep(2000); floor('11'); }); await sleep(5000); world.say(`- [[boss]${name} 出现!] - `); const boss = world.createEntity({ mesh: `mesh/${name}.vb`, id: `[boss]${name} `, meshScale: new Box3Vector3(Bosses[name][0], Bosses[name][0], Bosses[name][0]), collides: true, friction: 0.1, mass: 0.5, restitution: 0.7, position: randomPos().add(new Box3Vector3(0, 2, 0)), }); boss.addTag('pen'); boss.addTag('boss'); boss.enableDamage = true; boss.maxHp = 50; boss.hp = boss.maxHp; boss.interactHint = boss.id; boss.onDest = boss.onDestroy(onDestroy); boss.target = null; boss.enableInteract = true; boss.interactRadius = 50; boss.interactColor = new Box3RGBColor(1, 0, 0); await sleep(1000); boss.addTag('npc'); return boss; } async function createNPC() { const name = penNames[Math.floor(Math.random() * penNames.length)]; const npc = world.createEntity({ id: `npc 的 ${name}`, mesh: `mesh/${name}.vb`, meshScale: new Box3Vector3(Pens[name][2], Pens[name][2], Pens[name][2]), interactColor: new Box3RGBColor(0, 1, 1), interactRadius: 50, position: randomPos(), restitution: 0.7 }); npc.addTag('pen'); npc.enableInteract = true; npc.interactHint = npc.id; npc.hp = npc.maxHp = Pens[name][3]; npc.enableDamage = true; npc.target = null; npc.showHealthBar = false; npc.onDest = npc.onDestroy(onDestroy); await sleep(1000); npc.addTag('npc'); return npc; }; async function floor(color = '11') { for (let x = 0; x < 128; x++) { for (let z = 0; z < 128; z++) { voxels.setVoxel(x, 0, z, 'carpet_' + color); } } } var onErr = async function (v) { world.say(`${v}`); world.say(`⚠游戏出现异常⚠`); await sleep(5000); for (; ;) { } } var main = async function () { await sleep(5000); world.say('-[ 弹笔大战即将打响,请想要参加的玩家尽快报名参加游戏 ]-'); floor('11'); await sleep(10000); for (let l = 0; l < 10 - world.querySelectorAll('pen').length; l++) { createNPC(); await sleep(100); } world.querySelectorAll('.j').forEach(async entity => { entity.removeTag('j'); entity.joinGame(); await sleep(5000); if (!entity.playing == true) entity.player.cancelDialogs(); }); world.say('-[ 弹笔大战打响 ]-'); sleep(GameRunTime * 500).then(createBoss); while (world.gameRanTime < GameRunTime) { if (((GameRunTime - world.gameRanTime) % 30 == 0 || GameRunTime - world.gameRanTime <= 10) && world.gameRanTime > 10) { world.say(`-[游戏将在${GameRunTime - world.gameRanTime}秒后结束 ]-`); } world.gameRanTime += 1; if (world.querySelectorAll('.pen').length < 2 & GameRunTime - world.gameRanTime < 60) { world.say('-[本局游戏提前结束]-'); break; }; await sleep(999); } let players = world.querySelectorAll('.pen').sort(async (a, b) => { return b.killed > a.killed; }); world.gameRanTime = 0; if (players.length > 0) { world.say(`- [本局游戏结束 MVP: ${players[0].id} 击杀数: ${players[0].killed}] - `); } await sleep(1000); players.forEach(async p => { p.destroy(); }); floor('08'); await sleep(5000); main().catch(onErr); } main().catch(onErr); //请勿删除最后一行