diff --git a/main.js b/main.js index 05f0435..0295c32 100644 --- a/main.js +++ b/main.js @@ -276,7 +276,7 @@ main.prototype.init = function (mode, callback) { coreData[t] = main[t]; }); main.core.init(coreData, callback); - main.core.resize(); + core.resize(); // 自动放缩最大化 if (!main.replayChecking) { if (core.getLocalStorage("autoScale") == null) { diff --git a/project/functions.js b/project/functions.js index 97c0782..c70a441 100644 --- a/project/functions.js +++ b/project/functions.js @@ -82,19 +82,19 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = }); }, "lose": function (reason) { - // 游戏失败事件 - core.ui.closePanel(); - var replaying = core.isReplaying(); - core.stopReplay(); - core.waitHeroToStop(function () { - core.drawText( - ["\t[" + (reason || "结局1") + "]你死了。\n如题。"], - function () { - core.events.gameOver(null, replaying); - } - ); - }); - }, + // 游戏失败事件 + core.ui.closePanel(); + var replaying = core.isReplaying(); + core.stopReplay(); + core.waitHeroToStop(function () { + core.drawText( + ["\t[" + (reason || "结局1") + "]你死了。\n如题。"], + function () { + core.events.gameOver(null, replaying); + } + ); + }); +}, "changingFloor": function (floorId, heroLoc) { // 正在切换楼层过程中执行的操作;此函数的执行时间是“屏幕完全变黑“的那一刻 // floorId为要切换到的楼层ID;heroLoc表示勇士切换到的位置 @@ -1804,70 +1804,70 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = }; }, "moveOneStep": function (callback) { - // 勇士每走一步后执行的操作。callback为行走完毕后的回调 - // 这个函数执行在“刚走完”的时候,即还没有检查该点的事件和领域伤害等。 - // 请注意:瞬间移动不会执行该函数。如果要控制能否瞬间移动有三种方法: - // 1. 将全塔属性中的cannotMoveDirectly这个开关勾上,即可在全塔中全程禁止使用瞬移。 - // 2, 将楼层属性中的cannotMoveDirectly这个开关勾上,即禁止在该层楼使用瞬移。 - // 3. 将flag:cannotMoveDirectly置为true,即可使用flag控制在某段剧情范围内禁止瞬移。 + // 勇士每走一步后执行的操作。callback为行走完毕后的回调 + // 这个函数执行在“刚走完”的时候,即还没有检查该点的事件和领域伤害等。 + // 请注意:瞬间移动不会执行该函数。如果要控制能否瞬间移动有三种方法: + // 1. 将全塔属性中的cannotMoveDirectly这个开关勾上,即可在全塔中全程禁止使用瞬移。 + // 2, 将楼层属性中的cannotMoveDirectly这个开关勾上,即禁止在该层楼使用瞬移。 + // 3. 将flag:cannotMoveDirectly置为true,即可使用flag控制在某段剧情范围内禁止瞬移。 - // 增加步数 - core.status.hero.steps++; - // 更新跟随者状态,并绘制 - core.updateFollowers(); - core.drawHero(); - // 检查中毒状态的扣血和死亡 - if (core.hasFlag("poison")) { - core.status.hero.statistics.poisonDamage += core.values.poisonDamage; - core.status.hero.hp -= core.values.poisonDamage; - if (core.status.hero.hp <= 0) { - core.status.hero.hp = 0; - core.updateStatusBar(false, true); - core.events.lose(); - return; - } else { - core.updateStatusBar(false, true); - } - } + // 增加步数 + core.status.hero.steps++; + // 更新跟随者状态,并绘制 + core.updateFollowers(); + core.drawHero(); + // 检查中毒状态的扣血和死亡 + if (core.hasFlag("poison")) { + core.status.hero.statistics.poisonDamage += core.values.poisonDamage; + core.status.hero.hp -= core.values.poisonDamage; + if (core.status.hero.hp <= 0) { + core.status.hero.hp = 0; + core.updateStatusBar(false, true); + core.events.lose(); + return; + } else { + core.updateStatusBar(false, true); + } + } - // 从v2.7开始,每一步行走不会再刷新状态栏。 - // 如果有特殊要求(如每走一步都加buff之类),可手动取消注释下面这一句: - // core.updateStatusBar(true, true); + // 从v2.7开始,每一步行走不会再刷新状态栏。 + // 如果有特殊要求(如每走一步都加buff之类),可手动取消注释下面这一句: + // core.updateStatusBar(true, true); - // 检查自动事件 - core.checkAutoEvents(); + // 检查自动事件 + core.checkAutoEvents(); - // ------ 检查目标点事件 ------ // - // 无事件的道具(如血瓶)需要优先于阻激夹域判定 - var nowx = core.getHeroLoc("x"), - nowy = core.getHeroLoc("y"); - var block = core.getBlock(nowx, nowy); - var hasTrigger = false; - if ( - block != null && - block.event.trigger == "getItem" && - !core.floors[core.status.floorId].afterGetItem[nowx + "," + nowy] - ) { - hasTrigger = true; - core.trigger(nowx, nowy, callback); - } - // 执行目标点的阻激夹域事件 - core.checkBlock(); + // ------ 检查目标点事件 ------ // + // 无事件的道具(如血瓶)需要优先于阻激夹域判定 + var nowx = core.getHeroLoc("x"), + nowy = core.getHeroLoc("y"); + var block = core.getBlock(nowx, nowy); + var hasTrigger = false; + if ( + block != null && + block.event.trigger == "getItem" && + !core.floors[core.status.floorId].afterGetItem[nowx + "," + nowy] + ) { + hasTrigger = true; + core.trigger(nowx, nowy, callback); + } + // 执行目标点的阻激夹域事件 + core.checkBlock(); - // 执行目标点的script和事件 - if (!hasTrigger) core.trigger(nowx, nowy, callback); + // 执行目标点的script和事件 + if (!hasTrigger) core.trigger(nowx, nowy, callback); - // 检查该点是否是滑冰 - if (core.onSki()) { - // 延迟到事件最后执行,因为这之前可能有阻激夹域动画 - core.insertAction({ type: "moveAction" }, null, null, null, true); - } + // 检查该点是否是滑冰 + if (core.onSki()) { + // 延迟到事件最后执行,因为这之前可能有阻激夹域动画 + core.insertAction({ type: "moveAction" }, null, null, null, true); + } - // ------ 检查目标点事件 END ------ // + // ------ 检查目标点事件 END ------ // - // 如需强行终止行走可以在这里条件判定: - // core.stopAutomaticRoute(); - }, + // 如需强行终止行走可以在这里条件判定: + // core.stopAutomaticRoute(); +}, "moveDirectly": function (x, y, ignoreSteps) { // 瞬间移动;x,y为要瞬间移动的点;ignoreSteps为减少的步数,可能之前已经被计算过 // 返回true代表成功瞬移,false代表没有成功瞬移 diff --git a/project/plugins.js b/project/plugins.js index b93a7b2..b9bca3d 100644 --- a/project/plugins.js +++ b/project/plugins.js @@ -2728,6 +2728,12 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = main.dom.boss5.style.width = obj.totalWidth + 3 + "px"; main.dom.boss5.style.height = obj.totalHeight + 3 + "px"; + main.dom.boss6.style.width = obj.totalWidth + 3 + "px"; + main.dom.boss6.style.height = obj.totalHeight + 3 + "px"; + main.dom.boss7.style.width = obj.totalWidth + 3 + "px"; + main.dom.boss7.style.height = obj.totalHeight + 3 + "px"; + main.dom.boss8.style.width = obj.totalWidth + 3 + "px"; + main.dom.boss8.style.height = obj.totalHeight + 3 + "px"; main.dom.boss.style.width = obj.totalWidth + 3 + "px"; main.dom.boss.style.height = obj.totalHeight + 3 + "px"; @@ -8335,445 +8341,478 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = }; }, "func": function () { - // 功能函数集,具体有哪些函数看每个函数前的注释即可 - // 安装方式:直接复制到插件里面,注意新建插件自带的 function () { } 不能删 - // 使用方式:可以直接使用对象解构按需引入 - // 例如:const { has, slide } = core.plugin.utils; - // slide([1, 2, 3], -1); // [2, 3, 1] + // 功能函数集,具体有哪些函数看每个函数前的注释即可 + // 安装方式:直接复制到插件里面,注意新建插件自带的 function () { } 不能删 + // 使用方式:可以直接使用对象解构按需引入 + // 例如:const { has, slide } = core.plugin.utils; + // slide([1, 2, 3], -1); // [2, 3, 1] - /** - * 滑动数组,使数组元素平移若干项 - * @example slide([1, 2, 3], -1); // [2, 3, 1] - * @example slide([1, 3, 5], 10); // [5, 3, 1]; - * @param {any[]} arr 需要滑动的数组 - * @param {number} delta 滑动的项数,正负均可 - */ - function slide(arr, delta) { - if (delta === 0) return arr; - delta %= arr.length; - if (delta > 0) { - arr.unshift(...arr.splice(arr.length - delta, delta)); - return arr; - } - if (delta < 0) { - arr.push(...arr.splice(0, -delta)); - return arr; - } - } + /** + * 滑动数组,使数组元素平移若干项 + * @example slide([1, 2, 3], -1); // [2, 3, 1] + * @example slide([1, 3, 5], 10); // [5, 3, 1]; + * @param {any[]} arr 需要滑动的数组 + * @param {number} delta 滑动的项数,正负均可 + */ + function slide(arr, delta) { + if (delta === 0) return arr; + delta %= arr.length; + if (delta > 0) { + arr.unshift(...arr.splice(arr.length - delta, delta)); + return arr; + } + if (delta < 0) { + arr.push(...arr.splice(0, -delta)); + return arr; + } + } - /** - * 获取一个方向的反方向 - * @example backDir('up'); // 'down' - * @example backDir('leftup'); // 'rightdown' - * @param {string} dir 方向 - */ - function backDir(dir) { - const map = { - up: "down", - down: "up", - left: "right", - right: "left", - leftup: "rightdown", - leftdown: "rightup", - rightdown: "leftup", - rightup: "leftdown", - }; - if (!dir in map) { - throw new TypeError( - `Wrong dir is delivered when getting back direction.` - ); - } - return map[dir]; - } + /** + * 获取一个方向的反方向 + * @example backDir('up'); // 'down' + * @example backDir('leftup'); // 'rightdown' + * @param {string} dir 方向 + */ + function backDir(dir) { + const map = { + up: "down", + down: "up", + left: "right", + right: "left", + leftup: "rightdown", + leftdown: "rightup", + rightdown: "leftup", + rightup: "leftdown", + }; + if (!dir in map) { + throw new TypeError( + `Wrong dir is delivered when getting back direction.` + ); + } + return map[dir]; + } - /** - * 判断一个值是否不是undefined和null - * @example has(0); // true - * @example has(false); // true - * @example has(NaN); // true - * @example has(null); // false - * @param {any} v 要判断的值 - */ - function has(v) { - return v !== null && v !== void 0; - } + /** + * 判断一个值是否不是undefined和null + * @example has(0); // true + * @example has(false); // true + * @example has(NaN); // true + * @example has(null); // false + * @param {any} v 要判断的值 + */ + function has(v) { + return v !== null && v !== void 0; + } - /** - * 解析css字符串为CSSStyleDeclaration对象 - * @example - * parseCss('background-color: cyan; cursor: pointer; user-select: none'); - * // 输出 { backgroundColor: 'cyan', cursor: 'pointer', userSelect: 'none' } - * @param {string} css 要解析的css字符串 - */ - function parseCss(css) { - const str = css.replace(/[\n\s\t]*/g, "").replace(/;*/g, ";"); - const styles = str.split(";"); - const res = {}; + /** + * 解析css字符串为CSSStyleDeclaration对象 + * @example + * parseCss('background-color: cyan; cursor: pointer; user-select: none'); + * // 输出 { backgroundColor: 'cyan', cursor: 'pointer', userSelect: 'none' } + * @param {string} css 要解析的css字符串 + */ + function parseCss(css) { + const str = css.replace(/[\n\s\t]*/g, "").replace(/;*/g, ";"); + const styles = str.split(";"); + const res = {}; - for (const one of styles) { - const [key, data] = one.split(":"); - const cssKey = key.replace(/\-([a-z])/g, (str, $1) => $1.toUpperCase()); - res[cssKey] = data; - } - return res; - } + for (const one of styles) { + const [key, data] = one.split(":"); + const cssKey = key.replace(/\-([a-z])/g, (str, $1) => $1.toUpperCase()); + res[cssKey] = data; + } + return res; + } - /** - * 等待一段时间,需在async function中使用,否则报错 - * @example await sleep(500); // 等待500毫秒 - * @param {number} time 等待的毫秒数 - */ - async function sleep(time) { - return new Promise((res) => setTimeout(res, time)); - } + /** + * 等待一段时间,需在async function中使用,否则报错 + * @example await sleep(500); // 等待500毫秒 + * @param {number} time 等待的毫秒数 + */ + async function sleep(time) { + return new Promise((res) => setTimeout(res, time)); + } - /** - * 在下一帧的下一帧执行一个函数 - * @example nextFrame(() => console.log(1)); // 两帧后在控制台输出1 - * @param cb 执行的函数 - */ - function nextFrame(cb) { - requestAnimationFrame(() => { - requestAnimationFrame(cb); - }); - } + /** + * 在下一帧的下一帧执行一个函数 + * @example nextFrame(() => console.log(1)); // 两帧后在控制台输出1 + * @param cb 执行的函数 + */ + function nextFrame(cb) { + requestAnimationFrame(() => { + requestAnimationFrame(cb); + }); + } - /** - * 将一个css颜色解析成一个rgba数组 - * 目前仅支持 #RGB #RGBA #RRGGBB #RRGGBBAA rgb() rgba() hsl() hsla() css自带颜色 这几种的转换 - * @exmaple parseColor('#fff'); // [255, 255, 255] - * @example parseColor('#abcd'); // [170, 187, 204, 0.8666666666666667] - * @example parseColor('rgba(170, 230, 13, 0.2)'); // [170, 230, 13, 0.2] - * @example parseColor('cyan'); // [0, 255, 255] - * @example parseColor('lightcoral'); // [240, 128, 128] - * @example parseColor('hsla(0.2, 0.3, 0.4, 0.2)'); // [120, 133, 71, 0.2] - * @example parseColor('rgba(20%, 50, 33%, 0.2)'); // [51, 50, 84.15, 0.2] - * @param color 要解析的颜色字符串 - */ - function parseColor(color) { - if (color.startsWith("rgb")) { - // rgb - const match = color.match(/rgba?\([\d\,\s\.%]+\)/); - if (!has(match)) throw new Error(`Invalid color is delivered!`); - const l = color.includes("a"); - return match[0] - .slice(l ? 5 : 4, -1) - .split(",") - .map((v, i) => { - const vv = v.trim(); - if (vv.endsWith("%")) { - if (i === 3) { - return parseInt(vv) / 100; - } else { - return (parseInt(vv) * 255) / 100; - } - } else return parseFloat(vv); - }) - .slice(0, l ? 4 : 3); - } else if (color.startsWith("#")) { - // 十六进制 - const content = color.slice(1); - if (![3, 4, 6, 8].includes(content.length)) { - throw new Error(`Invalid color is delivered!`); - } + /** + * 将一个css颜色解析成一个rgba数组 + * 目前仅支持 #RGB #RGBA #RRGGBB #RRGGBBAA rgb() rgba() hsl() hsla() css自带颜色 这几种的转换 + * @exmaple parseColor('#fff'); // [255, 255, 255] + * @example parseColor('#abcd'); // [170, 187, 204, 0.8666666666666667] + * @example parseColor('rgba(170, 230, 13, 0.2)'); // [170, 230, 13, 0.2] + * @example parseColor('cyan'); // [0, 255, 255] + * @example parseColor('lightcoral'); // [240, 128, 128] + * @example parseColor('hsla(0.2, 0.3, 0.4, 0.2)'); // [120, 133, 71, 0.2] + * @example parseColor('rgba(20%, 50, 33%, 0.2)'); // [51, 50, 84.15, 0.2] + * @param color 要解析的颜色字符串 + */ + function parseColor(color) { + if (color.startsWith("rgb")) { + // rgb + const match = color.match(/rgba?\([\d\,\s\.%]+\)/); + if (!has(match)) throw new Error(`Invalid color is delivered!`); + const l = color.includes("a"); + return match[0] + .slice(l ? 5 : 4, -1) + .split(",") + .map((v, i) => { + const vv = v.trim(); + if (vv.endsWith("%")) { + if (i === 3) { + return parseInt(vv) / 100; + } else { + return (parseInt(vv) * 255) / 100; + } + } else return parseFloat(vv); + }) + .slice(0, l ? 4 : 3); + } else if (color.startsWith("#")) { + // 十六进制 + const content = color.slice(1); + if (![3, 4, 6, 8].includes(content.length)) { + throw new Error(`Invalid color is delivered!`); + } - if (content.length <= 4) { - const res = content.split("").map((v) => Number(`0x${v}${v}`)); - if (res.length === 4) res[3] /= 255; - return res; - } else { - const res = Array(content.length / 2) - .fill(1) - .map((v, i) => Number(`0x${content[i * 2]}${content[i * 2 + 1]}`)); - if (res.length === 4) res[3] /= 255; - return res; - } - } else if (color.startsWith("hsl")) { - // hsl,转成rgb后输出 - const match = color.match(/hsla?\([\d\,\s\.%]+\)/); - if (!has(match)) throw new Error(`Invalid color is delivered!`); - const l = color.includes("a"); - const hsl = match[0] - .slice(l ? 5 : 4, -1) - .split(",") - .map((v) => { - const vv = v.trim(); - if (vv.endsWith("%")) return parseInt(vv) / 100; - else return parseFloat(vv); - }); - const rgb = hslToRgb(hsl[0], hsl[1], hsl[2]); - return l ? rgb.concat([hsl[3]]) : rgb; - } else { - // 单词 - const rgb = cssColors[color]; - if (!has(rgb)) { - throw new Error(`Invalid color is delivered!`); - } - return parseColor(rgb); - } - } + if (content.length <= 4) { + const res = content.split("").map((v) => Number(`0x${v}${v}`)); + if (res.length === 4) res[3] /= 255; + return res; + } else { + const res = Array(content.length / 2) + .fill(1) + .map((v, i) => Number(`0x${content[i * 2]}${content[i * 2 + 1]}`)); + if (res.length === 4) res[3] /= 255; + return res; + } + } else if (color.startsWith("hsl")) { + // hsl,转成rgb后输出 + const match = color.match(/hsla?\([\d\,\s\.%]+\)/); + if (!has(match)) throw new Error(`Invalid color is delivered!`); + const l = color.includes("a"); + const hsl = match[0] + .slice(l ? 5 : 4, -1) + .split(",") + .map((v) => { + const vv = v.trim(); + if (vv.endsWith("%")) return parseInt(vv) / 100; + else return parseFloat(vv); + }); + const rgb = hslToRgb(hsl[0], hsl[1], hsl[2]); + return l ? rgb.concat([hsl[3]]) : rgb; + } else { + // 单词 + const rgb = cssColors[color]; + if (!has(rgb)) { + throw new Error(`Invalid color is delivered!`); + } + return parseColor(rgb); + } + } - /** - * hsl转rgb - * @param h 色相 - * @param s 饱和度 - * @param l 亮度 - */ - function hslToRgb(h, s, l) { - if (s == 0) { - return [0, 0, 0]; - } else { - const hue2rgb = (p, q, t) => { - if (t < 0) t += 1; - if (t > 1) t -= 1; - if (t < 1 / 6) return p + (q - p) * 6 * t; - if (t < 1 / 2) return q; - if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6; - return p; - }; + /** + * hsl转rgb + * @param h 色相 + * @param s 饱和度 + * @param l 亮度 + */ + function hslToRgb(h, s, l) { + if (s == 0) { + return [0, 0, 0]; + } else { + const hue2rgb = (p, q, t) => { + if (t < 0) t += 1; + if (t > 1) t -= 1; + if (t < 1 / 6) return p + (q - p) * 6 * t; + if (t < 1 / 2) return q; + if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6; + return p; + }; - const q = l < 0.5 ? l * (1 + s) : l + s - l * s; - const p = 2 * l - q; - const r = hue2rgb(p, q, h + 1 / 3); - const g = hue2rgb(p, q, h); - const b = hue2rgb(p, q, h - 1 / 3); - return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)]; - } - } + const q = l < 0.5 ? l * (1 + s) : l + s - l * s; + const p = 2 * l - q; + const r = hue2rgb(p, q, h + 1 / 3); + const g = hue2rgb(p, q, h); + const b = hue2rgb(p, q, h - 1 / 3); + return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)]; + } + } - /** - * 确保一个变量是一个数组,不是的话转为数组并返回,是的话直接返回传入的数组 - * @param arr 要判断的变量 - * @example ensureArray(1); // [1] - * @example ensureArray([1, 2]); // [1, 2] - * @example ensureArray('test'); // ['test'] - */ - function ensureArray(arr) { - // @ts-ignore - return arr instanceof Array ? arr : [arr]; - } + /** + * 确保一个变量是一个数组,不是的话转为数组并返回,是的话直接返回传入的数组 + * @param arr 要判断的变量 + * @example ensureArray(1); // [1] + * @example ensureArray([1, 2]); // [1, 2] + * @example ensureArray('test'); // ['test'] + */ + function ensureArray(arr) { + // @ts-ignore + return arr instanceof Array ? arr : [arr]; + } - /** - * 返回一个坐标在某个方向上移动 d 格后的坐标 - * @param d 移动多少格,默认为1 - * @example ofDir(7, 7, 'left'); // [6, 7] - * @example ofDir(10, 8, 'leftup', 5); // [5, 3] - */ - function ofDir(x, y, dir, d = 1) { - const { x: dx, y: dy } = core.utils.scan2[dir]; - return [x + dx * d, y + dy * d]; - } + /** + * 返回一个坐标在某个方向上移动 d 格后的坐标 + * @param d 移动多少格,默认为1 + * @example ofDir(7, 7, 'left'); // [6, 7] + * @example ofDir(10, 8, 'leftup', 5); // [5, 3] + */ + function ofDir(x, y, dir, d = 1) { + const { x: dx, y: dy } = core.utils.scan2[dir]; + return [x + dx * d, y + dy * d]; + } - const cssColors = { - black: "#000000", - silver: "#c0c0c0", - gray: "#808080", - white: "#ffffff", - maroon: "#800000", - red: "#ff0000", - purple: "#800080", - fuchsia: "#ff00ff", - green: "#008000", - lime: "#00ff00", - olive: "#808000", - yellow: "#ffff00", - navy: "#000080", - blue: "#0000ff", - teal: "#008080", - aqua: "#00ffff", - orange: "#ffa500", - aliceblue: "#f0f8ff", - antiquewhite: "#faebd7", - aquamarine: "#7fffd4", - azure: "#f0ffff", - beige: "#f5f5dc", - bisque: "#ffe4c4", - blanchedalmond: "#ffebcd", - blueviolet: "#8a2be2", - brown: "#a52a2a", - burlywood: "#deb887", - cadetblue: "#5f9ea0", - chartreuse: "#7fff00", - chocolate: "#d2691e", - coral: "#ff7f50", - cornflowerblue: "#6495ed", - cornsilk: "#fff8dc", - crimson: "#dc143c", - cyan: "#00ffff", - darkblue: "#00008b", - darkcyan: "#008b8b", - darkgoldenrod: "#b8860b", - darkgray: "#a9a9a9", - darkgreen: "#006400", - darkgrey: "#a9a9a9", - darkkhaki: "#bdb76b", - darkmagenta: "#8b008b", - darkolivegreen: "#556b2f", - darkorange: "#ff8c00", - darkorchid: "#9932cc", - darkred: "#8b0000", - darksalmon: "#e9967a", - darkseagreen: "#8fbc8f", - darkslateblue: "#483d8b", - darkslategray: "#2f4f4f", - darkslategrey: "#2f4f4f", - darkturquoise: "#00ced1", - darkviolet: "#9400d3", - deeppink: "#ff1493", - deepskyblue: "#00bfff", - dimgray: "#696969", - dimgrey: "#696969", - dodgerblue: "#1e90ff", - firebrick: "#b22222", - floralwhite: "#fffaf0", - forestgreen: "#228b22", - gainsboro: "#dcdcdc", - ghostwhite: "#f8f8ff", - gold: "#ffd700", - goldenrod: "#daa520", - greenyellow: "#adff2f", - grey: "#808080", - honeydew: "#f0fff0", - hotpink: "#ff69b4", - indianred: "#cd5c5c", - indigo: "#4b0082", - ivory: "#fffff0", - khaki: "#f0e68c", - lavender: "#e6e6fa", - lavenderblush: "#fff0f5", - lawngreen: "#7cfc00", - lemonchiffon: "#fffacd", - lightblue: "#add8e6", - lightcoral: "#f08080", - lightcyan: "#e0ffff", - lightgoldenrodyellow: "#fafad2", - lightgray: "#d3d3d3", - lightgreen: "#90ee90", - lightgrey: "#d3d3d3", - lightpink: "#ffb6c1", - lightsalmon: "#ffa07a", - lightseagreen: "#20b2aa", - lightskyblue: "#87cefa", - lightslategray: "#778899", - lightslategrey: "#778899", - lightsteelblue: "#b0c4de", - lightyellow: "#ffffe0", - limegreen: "#32cd32", - linen: "#faf0e6", - magenta: "#ff00ff", - mediumaquamarine: "#66cdaa", - mediumblue: "#0000cd", - mediumorchid: "#ba55d3", - mediumpurple: "#9370db", - mediumseagreen: "#3cb371", - mediumslateblue: "#7b68ee", - mediumspringgreen: "#00fa9a", - mediumturquoise: "#48d1cc", - mediumvioletred: "#c71585", - midnightblue: "#191970", - mintcream: "#f5fffa", - mistyrose: "#ffe4e1", - moccasin: "#ffe4b5", - navajowhite: "#ffdead", - oldlace: "#fdf5e6", - olivedrab: "#6b8e23", - orangered: "#ff4500", - orchid: "#da70d6", - palegoldenrod: "#eee8aa", - palegreen: "#98fb98", - paleturquoise: "#afeeee", - palevioletred: "#db7093", - papayawhip: "#ffefd5", - peachpuff: "#ffdab9", - peru: "#cd853f", - pink: "#ffc0cb", - plum: "#dda0dd", - powderblue: "#b0e0e6", - rosybrown: "#bc8f8f", - royalblue: "#4169e1", - saddlebrown: "#8b4513", - salmon: "#fa8072", - sandybrown: "#f4a460", - seagreen: "#2e8b57", - seashell: "#fff5ee", - sienna: "#a0522d", - skyblue: "#87ceeb", - slateblue: "#6a5acd", - slategray: "#708090", - slategrey: "#708090", - snow: "#fffafa", - springgreen: "#00ff7f", - steelblue: "#4682b4", - tan: "#d2b48c", - thistle: "#d8bfd8", - tomato: "#ff6347", - turquoise: "#40e0d0", - violet: "#ee82ee", - wheat: "#f5deb3", - whitesmoke: "#f5f5f5", - yellowgreen: "#9acd32", - transparent: "#0000", - }; + const cssColors = { + black: "#000000", + silver: "#c0c0c0", + gray: "#808080", + white: "#ffffff", + maroon: "#800000", + red: "#ff0000", + purple: "#800080", + fuchsia: "#ff00ff", + green: "#008000", + lime: "#00ff00", + olive: "#808000", + yellow: "#ffff00", + navy: "#000080", + blue: "#0000ff", + teal: "#008080", + aqua: "#00ffff", + orange: "#ffa500", + aliceblue: "#f0f8ff", + antiquewhite: "#faebd7", + aquamarine: "#7fffd4", + azure: "#f0ffff", + beige: "#f5f5dc", + bisque: "#ffe4c4", + blanchedalmond: "#ffebcd", + blueviolet: "#8a2be2", + brown: "#a52a2a", + burlywood: "#deb887", + cadetblue: "#5f9ea0", + chartreuse: "#7fff00", + chocolate: "#d2691e", + coral: "#ff7f50", + cornflowerblue: "#6495ed", + cornsilk: "#fff8dc", + crimson: "#dc143c", + cyan: "#00ffff", + darkblue: "#00008b", + darkcyan: "#008b8b", + darkgoldenrod: "#b8860b", + darkgray: "#a9a9a9", + darkgreen: "#006400", + darkgrey: "#a9a9a9", + darkkhaki: "#bdb76b", + darkmagenta: "#8b008b", + darkolivegreen: "#556b2f", + darkorange: "#ff8c00", + darkorchid: "#9932cc", + darkred: "#8b0000", + darksalmon: "#e9967a", + darkseagreen: "#8fbc8f", + darkslateblue: "#483d8b", + darkslategray: "#2f4f4f", + darkslategrey: "#2f4f4f", + darkturquoise: "#00ced1", + darkviolet: "#9400d3", + deeppink: "#ff1493", + deepskyblue: "#00bfff", + dimgray: "#696969", + dimgrey: "#696969", + dodgerblue: "#1e90ff", + firebrick: "#b22222", + floralwhite: "#fffaf0", + forestgreen: "#228b22", + gainsboro: "#dcdcdc", + ghostwhite: "#f8f8ff", + gold: "#ffd700", + goldenrod: "#daa520", + greenyellow: "#adff2f", + grey: "#808080", + honeydew: "#f0fff0", + hotpink: "#ff69b4", + indianred: "#cd5c5c", + indigo: "#4b0082", + ivory: "#fffff0", + khaki: "#f0e68c", + lavender: "#e6e6fa", + lavenderblush: "#fff0f5", + lawngreen: "#7cfc00", + lemonchiffon: "#fffacd", + lightblue: "#add8e6", + lightcoral: "#f08080", + lightcyan: "#e0ffff", + lightgoldenrodyellow: "#fafad2", + lightgray: "#d3d3d3", + lightgreen: "#90ee90", + lightgrey: "#d3d3d3", + lightpink: "#ffb6c1", + lightsalmon: "#ffa07a", + lightseagreen: "#20b2aa", + lightskyblue: "#87cefa", + lightslategray: "#778899", + lightslategrey: "#778899", + lightsteelblue: "#b0c4de", + lightyellow: "#ffffe0", + limegreen: "#32cd32", + linen: "#faf0e6", + magenta: "#ff00ff", + mediumaquamarine: "#66cdaa", + mediumblue: "#0000cd", + mediumorchid: "#ba55d3", + mediumpurple: "#9370db", + mediumseagreen: "#3cb371", + mediumslateblue: "#7b68ee", + mediumspringgreen: "#00fa9a", + mediumturquoise: "#48d1cc", + mediumvioletred: "#c71585", + midnightblue: "#191970", + mintcream: "#f5fffa", + mistyrose: "#ffe4e1", + moccasin: "#ffe4b5", + navajowhite: "#ffdead", + oldlace: "#fdf5e6", + olivedrab: "#6b8e23", + orangered: "#ff4500", + orchid: "#da70d6", + palegoldenrod: "#eee8aa", + palegreen: "#98fb98", + paleturquoise: "#afeeee", + palevioletred: "#db7093", + papayawhip: "#ffefd5", + peachpuff: "#ffdab9", + peru: "#cd853f", + pink: "#ffc0cb", + plum: "#dda0dd", + powderblue: "#b0e0e6", + rosybrown: "#bc8f8f", + royalblue: "#4169e1", + saddlebrown: "#8b4513", + salmon: "#fa8072", + sandybrown: "#f4a460", + seagreen: "#2e8b57", + seashell: "#fff5ee", + sienna: "#a0522d", + skyblue: "#87ceeb", + slateblue: "#6a5acd", + slategray: "#708090", + slategrey: "#708090", + snow: "#fffafa", + springgreen: "#00ff7f", + steelblue: "#4682b4", + tan: "#d2b48c", + thistle: "#d8bfd8", + tomato: "#ff6347", + turquoise: "#40e0d0", + violet: "#ee82ee", + wheat: "#f5deb3", + whitesmoke: "#f5f5f5", + yellowgreen: "#9acd32", + transparent: "#0000", + }; + // 计算两个数的最大公约数 + function gcdOfTwo(a, b) { + while (b !== 0) { + let temp = b; + b = a % b; + a = temp; + } + return a; + } - if (has(core.plugin.utils)) { - throw new ReferenceError( - `core.plugin上已经有'utils'属性,因此功能函数插件将无法使用!` - ); - } - core.plugin.utils = { - has, - slide, - backDir, - parseCss, - sleep, - nextFrame, - parseColor, - hslToRgb, - ensureArray, - ofDir, - }; - // Utility.js - // 通用函數插件 - // 本插件與古祠發佈的《功能插件 --- 实用功能函数集》不同,函數是定義在全域的。 - // 自訂常見事件模板插件(editorBlocklyconfigPlus.js)的前置插件 + // 计算任意项整数的最大公约数 + function gcd(...numbers) { + if (numbers.length < 2) { + throw new Error("至少需要两个数"); + } + return numbers.reduce((a, b) => gcdOfTwo(a, b)); + } + // 计算两个数的最小公倍数 + function lcmOfTwo(a, b) { + return (a * b) / gcdOfTwo(a, b); + } - /** - * 使js暫停指定時間 - * async環境下await Sleep(500) - * @param {number} millisecond 暫停毫秒數 - */ - self.Sleep = async function (millisecond) { - return new Promise((resolve) => setTimeout(resolve, millisecond)); - }; + // 计算任意项整数的最小公倍数 + function lcm(...numbers) { + if (numbers.length < 2) { + throw new Error("至少需要两个数"); + } + return numbers.reduce((a, b) => lcmOfTwo(a, b)); + } - /** - * 使js暫停一幀 - * async環境下await SleepFrame() - */ - self.SleepFrame = async function () { - return new Promise((resolve) => requestAnimationFrame(resolve)); - }; + if (has(core.plugin.utils)) { + throw new ReferenceError( + `core.plugin上已经有'utils'属性,因此功能函数插件将无法使用!` + ); + } + core.plugin.utils = { + gcdOfTwo, + lcmOfTwo, + gcd, + lcm, + has, + slide, + backDir, + parseCss, + sleep, + nextFrame, + parseColor, + hslToRgb, + ensureArray, + ofDir, + }; + // Utility.js + // 通用函數插件 + // 本插件與古祠發佈的《功能插件 --- 实用功能函数集》不同,函數是定義在全域的。 + // 自訂常見事件模板插件(editorBlocklyconfigPlus.js)的前置插件 - /** - * editor_file的isset函數 - */ - self.isset = function (val) { - if (val == undefined || val == null) { - return false; - } - return true; - }; + /** + * 使js暫停指定時間 + * async環境下await Sleep(500) + * @param {number} millisecond 暫停毫秒數 + */ + self.Sleep = async function (millisecond) { + return new Promise((resolve) => setTimeout(resolve, millisecond)); + }; - /** - * editor_file的checkCallback函數 - */ - self.checkCallback = function (callback) { - if (!isset(callback)) { - printe("未设置callback"); - throw "未设置callback"; - } - }; - }, + /** + * 使js暫停一幀 + * async環境下await SleepFrame() + */ + self.SleepFrame = async function () { + return new Promise((resolve) => requestAnimationFrame(resolve)); + }; + + /** + * editor_file的isset函數 + */ + self.isset = function (val) { + if (val == undefined || val == null) { + return false; + } + return true; + }; + + /** + * editor_file的checkCallback函數 + */ + self.checkCallback = function (callback) { + if (!isset(callback)) { + printe("未设置callback"); + throw "未设置callback"; + } + }; +}, "音频系统": function () { // 在此增加新插件 /*首先,在造塔群下载所需的库文件,然后放置在塔目录下的 libs/thirdparty 或其他目录下,之后在 index.html 的最后加上下面这几行: @@ -16478,6 +16517,41 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = boss5.style.transform = "translate(-50%,-50%)"; const ctx5 = boss5.getContext("2d"); main.dom.boss5 = boss5; + + const boss6 = document.createElement("canvas"); //boss战画布设置 + boss6.style.position = "absolute"; + boss6.style.zIndex = 305; + boss6.style.display = "none"; + boss6.id = "boss6"; + main.dom.gameGroup.insertAdjacentElement("afterend", boss6); + boss6.style.top = "50%"; + boss6.style.left = "50%"; + boss6.style.transform = "translate(-50%,-50%)"; + const ctx6 = boss6.getContext("2d"); + main.dom.boss6 = boss6; + const boss7 = document.createElement("canvas"); //boss战画布设置 + boss7.style.position = "absolute"; + boss7.style.zIndex = 306; + boss7.style.display = "none"; + boss7.id = "boss7"; + main.dom.gameGroup.insertAdjacentElement("afterend", boss7); + boss7.style.top = "50%"; + boss7.style.left = "50%"; + boss7.style.transform = "translate(-50%,-50%)"; + const ctx7 = boss7.getContext("2d"); + main.dom.boss7 = boss7; + const boss8 = document.createElement("canvas"); //boss战画布设置 + boss8.style.position = "absolute"; + boss8.style.zIndex = 307; + boss8.style.display = "none"; + boss8.id = "boss8"; + main.dom.gameGroup.insertAdjacentElement("afterend", boss8); + boss8.style.top = "50%"; + boss8.style.left = "50%"; + boss8.style.transform = "translate(-50%,-50%)"; + const ctx8 = boss8.getContext("2d"); + main.dom.boss8 = boss8; + boss.onclick = function (e) { try { e.preventDefault(); @@ -16496,7 +16570,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = main.log(ee); } }; - + const { sleep } = core.plugin.utils class Boss { constructor() { @@ -16504,14 +16578,14 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = this.bg = "bg_3512.webp"; this.heroImage = "tati_310101.webp" this.hero = { hp: 1000, atk: 100, def: 100, spell: 100, speed: 10, mdef: 10 } - this.boss = { name: "菲奥奈", id: "angel", image: "tati_050143.webp", hp: 1000, atk: 100, def: 100, speed: 10, mdef: 10 } + this.boss = { name: "菲奥奈", id: "angel", image: "tati_050143.webp", hp: 1000, atk: 200, def: 100, speed: 10, mdef: 10, skill: ['普通攻击', '重斩'], index: 0 } this.enemy = [ - { name: "小蝙蝠", id: "bat", hp: 1000, atk: 100, def: 100, speed: 10, mdef: 10 }, - { name: "红蝙蝠", id: "redBat", hp: 1000, atk: 100, def: 100, speed: 10, mdef: 10 }, - { name: "大蝙蝠", id: "bigBat", hp: 1000, atk: 100, def: 100, speed: 10, mdef: 10 }, - { name: "绿色史莱姆", id: "greenSlime", hp: 1000, atk: 100, def: 100, speed: 10, mdef: 10 }, - { name: "红色史莱姆", id: "redSlime", hp: 1000, atk: 100, def: 100, speed: 10, mdef: 10 }, - { name: "黑色史莱姆", id: "blackSlime", hp: 1000, atk: 100, def: 100, speed: 10, mdef: 10 }, + { name: "小蝙蝠", id: "bat", hp: 1000, atk: 100, def: 100, speed: 10, mdef: 10, skill: ['普通攻击', '重斩'], index: 0 }, + { name: "红蝙蝠", id: "redBat", hp: 1000, atk: 100, def: 100, speed: 10, mdef: 10, skill: ['普通攻击', '重斩'], index: 0 }, + { name: "大蝙蝠", id: "bigBat", hp: 1000, atk: 100, def: 100, speed: 10, mdef: 10, skill: ['普通攻击', '重斩'], index: 0 }, + { name: "绿色史莱姆", id: "greenSlime", hp: 1000, atk: 100, def: 100, speed: 10, mdef: 10, skill: ['普通攻击', '重斩'], index: 0 }, + { name: "红色史莱姆", id: "redSlime", hp: 1000, atk: 100, def: 100, speed: 10, mdef: 10, skill: ['普通攻击', '重斩'], index: 0 }, + { name: "黑色史莱姆", id: "blackSlime", hp: 1000, atk: 100, def: 100, speed: 10, mdef: 10, skill: ['普通攻击', '重斩'], index: 0 }, ] this.bossImage = "tati_050143.webp" this.selection = "boss" @@ -16525,7 +16599,13 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = [], [] ] + this.skills = { //技能列表,便于调用(可通过this.skills[name]调用) + "菲奥奈": ['普通攻击', '重斩'] + } + this.turn = 0; + this.playingAnimate = new Set(); } + click(px, py) { //点击效果 const makeBox = ([x, y], [w, h]) => { @@ -16543,18 +16623,169 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = const pos = [px, py]; } async bossStart() { + boss.style.display = "block" + this.turn = 0 core.lockControl() await this.blackBg() this.moveboss() await this.movehero() await this.moveStatus() - this.drawenemy() - + this.update() + this.fight() } async bossEnd() { + hero.hp = this.hero.hp await this.close() - core.unlockControl() + core.unlockControl() + core.updateStatusBar() + if (hero.hp <= 0) { + hero.hp = 0 + core.events.lose("BOSS战失败"); + } + } + async fight() { + await this.drawturn() + const fightList = [] + fightList.push(['hero', this.hero.speed]) + if (this.boss.hp > 0) fightList.push(["boss", this.boss.speed]) + this.enemy.forEach((v, i) => { + if (v.id && v.hp > 0) fightList.push([i, v.speed]) + }) + fightList.sort((a, b) => b[1] - a[1]) + let damage; + for (const v of fightList) { + switch (v[0]) { + case 'hero': + await this.playanimate("sword", 1800, 800) //播放动画sword + await sleep(200) //等待200ms + break; + case 'boss': + if (this.boss.hp > 0) { + this.selection = "boss" + this.update() + + switch (this.boss.skill[this.boss.index]) { //这里写boss技能的效果 + case "普通攻击": + damage = Math.max(this.boss.atk - this.hero.def, 0) //基础伤害 + damage = Math.floor(damage * this.boss.speed / this.hero.speed) //速度比值伤害加成 + this.hero.hp -= damage //承受伤害 + core.status.hero.statistics.battleDamage += damage; //数据统计记录伤害 + await this.playanimate("sword", 350, 800) //播放动画sword + await sleep(200) //等待200ms + break; + + } + this.boss.index++ + if (this.boss.index >= this.boss.skill.length) this.boss.index = 0 + } + break; + default: + const enemy = this.enemy[v[0]]; + if (enemy.hp > 0) { + this.selection = v[0] + this.update() + + switch (enemy.skill[enemy.index]) { //这里写boss召唤物(小怪)的技能效果 + case "普通攻击": + damage = Math.max(enemy.atk - this.hero.def, 0) //基础伤害 + damage = Math.floor(damage * enemy.speed / enemy.speed) //速度比值伤害加成 + this.hero.hp -= damage //承受伤害 + core.status.hero.statistics.battleDamage += damage; //数据统计记录伤害 + + switch (enemy.id) { //根据怪物id选取不同的特效 + + case "bat": + await this.playanimate("sword", 350, 800) //播放动画sword + + break; + case "redBat": + await this.playanimate("Fire01", 350, 800) //播放动画Fire01 + break; + case "bigBat": + await this.playanimate("Fire02", 350, 800) //播放动画Fire02 + break; + case "greenSlime": + await this.playanimate("005-Attack03", 350, 800) //播放动画005-Attack03 + break; + case "redSlime": + await this.playanimate("012-Heal01", 350, 800) //播放动画012-Heal01 + break; + case "blackSlime": + await this.playanimate("sword", 350, 800) //播放动画sword + break; + + } + await sleep(200) //等待200ms + break; + } + if (enemy.index >= enemy.length) enemy.index = 0 + } + break; + + } + this.update() + + } + let end = true; + if (this.boss.hp > 0) end = false; + this.enemy.forEach(v => { if (v.hp > 0) end = false }) + + if (this.hero.hp <= 0) end = true + if (end) { this.bossEnd() } else { this.fight() } + } + drawturn() { + boss8.style.display = "block" + this.turn += 1 + let time = 0, + frame = 0, + frame2 = 0, + right = 1, + once = 10; + return new Promise((resolve) => { + core.registerAnimationFrame("drawturn", true, (temptime) => { + if (temptime - time > 1000 / 60) { + time = temptime + frame += 1 * right + core.clearMap(ctx) + if (core.domStyle.isVertical) { + ctx.canvas.width = 1248; + ctx.canvas.height = 2028; + ctx.save(); //保存设置 + ctx.translate(1248, 0); //重新定位右上角为基准 + ctx.rotate(Math.PI / 2); //旋转90度 + } else { + ctx.canvas.width = 2028; + ctx.canvas.height = 1248; + } + + core.fillRect(ctx, 0, 624 - once * frame, 2028, once * frame * 2, 'rgba(0,0,0,0.7)') + core.setTextAlign(ctx, "center") + core.fillBoldText1( + ctx, + 'ROUND ' + this.turn, + 1014, + 624, + "#FFFFFF", + "#000000", + 6, + core.ui._buildFont(frame * 5, true) + ) + if (1014 - once * frame * 7 <= 0) { + frame -= 1 + frame2++ + + if (frame2 > 30) right = -1 + + } + if (frame < 0) { + core.clearMap(ctx) + core.unregisterAnimationFrame("drawturn") + resolve() + } + } + }) + }) } drawenemy() { let block, @@ -16567,7 +16798,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = farme += 1 let animate = Math.floor(farme / 30), posx = 700, - posy = 350; + posy = 500; core.clearMap(ctx5) if (core.domStyle.isVertical) { ctx5.canvas.width = 1248; @@ -16584,7 +16815,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = if (enemy) { core.drawWindowSkin("winskin.webp", ctx5, 650, 250, 400, 660, null, null, null, 3) - if (this.selection === "boss") core.strokeRect(ctx5, 800, 600, 100, 150, "yellow", 6) + if (this.selection === "boss") core.strokeRect(ctx5, 800, 300, 100, 150, "yellow", 6) const bossBlock = core.getBlockInfo(this.boss.id) core.drawImage( ctx5, @@ -16594,7 +16825,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = 32, 48, 800, - 600, + 300, 96, 144 ); @@ -16611,7 +16842,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = 144 ); for (let i = 0; i < this.enemy.length; i++) { - if (this.enemy[i].id) { + if (this.enemy[i].id && this.enemy[i].hp > 0) { block = core.getBlockInfo(this.enemy[i].id) } else { posx += 100 @@ -16717,7 +16948,158 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = this.drawboss() this.drawhero() this.drawStatus() + let dodraw = false + for (let i = 0; i < this.enemy.length; i++) { + if (this.enemy[i].id && this.enemy[i].hp > 0) { dodraw = true } + } + if (dodraw === true) this.drawenemy() + } + playanimate(name, x, y, scalex = 10, scaley = 10) { + const one = { + name: name, + x: x, + y: y, + scalex: scalex, + scaley: scaley, + farme: 0 + + } + let time = 0 + boss6.style.display = "block" + return new Promise((resolve) => { + core.registerAnimationFrame("animateboss", true, (timestamp) => { + if (timestamp - time > 1000 / 60) { + time = timestamp; + core.clearMap(ctx6); + + + const data = flags["animate_" + one.name]; + if (core.domStyle.isVertical) { + ctx6.canvas.width = 1248; + ctx6.canvas.height = 2028; + ctx6.save(); //保存设置 + ctx6.translate(1248, 0); //重新定位右上角为基准 + ctx6.rotate(Math.PI / 2); //旋转90度 + } else { + ctx6.canvas.width = 2028; + ctx6.canvas.height = 1248; + } + + if (!data) { + + core.registerAnimationFrame("animateboss") + resolve() + } else { + data.imageList.forEach(function (image) { + if ( + one.farme >= (image.beforefarme ?? 0) && + one.farme <= (image.afterfarme ?? data.allFarme) + ) { + const img = core.material.images.images?.[image.image]; + if (img) { + const gla = image.globalAlpha ?? 100; + const agla = image.aglobalAlpha ?? gla, + beforefarme = image.beforefarme ?? 0; + const afterfarme = image.afterfarme ?? data.allFarme; + + ctx6.globalAlpha = + (gla + + ((agla - gla) * (one.farme - beforefarme)) / + (afterfarme - beforefarme || 1)) / + 100; + + const cx = + (image.cx ?? 0) + + (((image.acx ?? 0) - (image.cx ?? 0)) * + (one.farme - beforefarme)) / + (afterfarme - beforefarme || 1), + cy = + (image.cy ?? 0) + + (((image.acy ?? 0) - (image.cy ?? 0)) * + (one.farme - beforefarme)) / + (afterfarme - beforefarme || 1), + cw = + (image.cw ?? img.width) + + (((image.acw ?? img.width) - (image.cw ?? img.width)) * + (one.farme - beforefarme)) / + (afterfarme - beforefarme || 1), + ch = + (image.ch ?? img.height) + + (((image.acw ?? img.height) - (image.cw ?? img.height)) * + (one.farme - beforefarme)) / + (afterfarme - beforefarme || 1), + x = + (image.x ?? 0) + + (((image.ax ?? 0) - (image.x ?? 0)) * + (one.farme - beforefarme)) / + (afterfarme - beforefarme || 1), + y = + (image.y ?? 0) + + (((image.ay ?? 0) - (image.y ?? 0)) * + (one.farme - beforefarme)) / + (afterfarme - beforefarme || 1), + w = + (image.w ?? one.width) + + (((image.aw ?? one.width) - (image.w ?? one.width)) * + (one.farme - beforefarme)) / + (afterfarme - beforefarme || 1), + h = + (image.h ?? one.height) + + (((image.aw ?? one.height) - (image.w ?? one.height)) * + (one.farme - beforefarme)) / + (afterfarme - beforefarme || 1), + angle = + (Math.PI * + ((image.image.angle ?? 0) + + (((image.aangle ?? 0) - (image.image.angle ?? 0)) * + (one.farme - beforefarme)) / + (afterfarme - beforefarme || 1))) / + 180; + + + core.drawImage( + ctx6, + img, + cx, + cy, + cw, + ch, + one.x + (x - data.px) * one.scalex, + one.y + (y - data.py) * one.scaley, + w * one.scalex, + h * one.scaley, + angle + ); + } + + } + }); + data.soundList.forEach(function (sound) { + const lisen = + sound.sound && + core.sounds[sound.sound] && + core.musicStatus.soundStatus; + if (one.farme == sound.startfarme && lisen) { + if (sound.stopbefore) core.stopSound(); + core.playSound(sound.sound); + } + }); + one.farme++; + ctx6.restore(); + if (one.farme > data.allFarme) { + core.clearMap(ctx6) + core.registerAnimationFrame("animateboss") + resolve() + } + } + } + }); + + }) + + } + drawboss() { core.clearMap(ctx3) if (core.domStyle.isVertical) { @@ -17391,7 +17773,6 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = close() { let globalAlpha = 0, time = 0 - boss.style.display = 'block' return new Promise((resolve) => { core.registerAnimationFrame("closeblack", true, (temptime) => { if (temptime - time > 1000 / 60) { @@ -17424,6 +17805,10 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = boss3.style.display = 'none' boss4.style.display = 'none' boss5.style.display = 'none' + boss6.style.display = 'none' + boss7.style.display = 'none' + boss8.style.display = 'none' + core.registerAnimationFrame("closeblack2", true, (temptime) => { if (temptime - time > 1000 / 60) { time = temptime @@ -17439,7 +17824,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = ctx.canvas.height = 1248; } ctx.globalAlpha = globalAlpha - core.fillRect(ctx1, 0, 0, 2028, 1248, "#000000"); + core.fillRect(ctx, 0, 0, 2028, 1248, "#000000"); ctx.restore(); globalAlpha -= 1 / 30 if (globalAlpha < 0) { @@ -19049,207 +19434,207 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = }; }, "帧动画特效(游戏界面)": function () { - // 在此增加新插件 - const animate2 = document.createElement("canvas"); //画布设置 - animate2.style.zIndex = 91; - animate2.id = "animate2"; - animate2.classList.add("gameCanvas", "anti-aliasing"); - animate2.style.display = "block"; - animate2.width = 416; - animate2.height = 416; - animate2.style.width = core.__PIXELS__ * core.domStyle.scale + "px"; - animate2.style.height = core.__PIXELS__ * core.domStyle.scale + "px"; - main.dom.animate2 = animate2; - const anctx = animate2.getContext("2d"); + // 在此增加新插件 + const animate2 = document.createElement("canvas"); //画布设置 + animate2.style.zIndex = 91; + animate2.id = "animate2"; + animate2.classList.add("gameCanvas", "anti-aliasing"); + animate2.style.display = "block"; + animate2.width = 416; + animate2.height = 416; + animate2.style.width = core.__PIXELS__ * core.domStyle.scale + "px"; + animate2.style.height = core.__PIXELS__ * core.domStyle.scale + "px"; + main.dom.animate2 = animate2; + const anctx = animate2.getContext("2d"); - main.dom.gameDraw.appendChild(animate2); + main.dom.gameDraw.appendChild(animate2); - core.plugin.playing = new Set(); + core.plugin.playing = new Set(); - this.setanimate = function ( - name, - px, - py, - width, - height, - allFarme, - imageList, - soundList - ) { - const data = { - px: px, - py: py, - width: width, - height: height, - allFarme: allFarme, - imageList: imageList, - soundList: soundList, - }; - core.setFlag("animate_" + name, data); - }; - this.deleteanimate = function (name) { - core.setFlag("animate_" + name); - }; - let thistime = 0; - this.playanimate = function (name, x, y, hero, scalex, scaley, callback) { - const data = { - name: name, - x: x, - y: y, - hero: hero, - scalex: scalex, - scaley: scaley, - farme: 0, - callback, - }; + this.setanimate = function ( + name, + px, + py, + width, + height, + allFarme, + imageList, + soundList + ) { + const data = { + px: px, + py: py, + width: width, + height: height, + allFarme: allFarme, + imageList: imageList, + soundList: soundList, + }; + core.setFlag("animate_" + name, data); + }; + this.deleteanimate = function (name) { + core.setFlag("animate_" + name); + }; + let thistime = 0; + this.playanimate = function (name, x, y, hero, scalex, scaley, callback) { + const data = { + name: name, + x: x, + y: y, + hero: hero, + scalex: scalex, + scaley: scaley, + farme: 0, + callback, + }; - core.plugin.playing.add(data); - }; - core.registerAnimationFrame("animateonmap", true, function (timestamp) { - if (timestamp - thistime > 1000 / 60) { - thistime = timestamp; - core.clearMap(anctx); - core.plugin.playing.forEach((one) => { - const data = flags["animate_" + one.name]; - if (!data) { - core.plugin.playing.delete(one); - } else { - data.imageList.forEach(function (image) { - if ( - one.farme >= (image.beforefarme ?? 0) && - one.farme <= (image.afterfarme ?? data.allFarme) - ) { - const img = core.material.images.images?.[image.image]; - if (img) { - const gla = image.globalAlpha ?? 100; - const agla = image.aglobalAlpha ?? gla, - beforefarme = image.beforefarme ?? 0; - const afterfarme = image.afterfarme ?? data.allFarme; + core.plugin.playing.add(data); + }; + core.registerAnimationFrame("animateonmap", true, function (timestamp) { + if (timestamp - thistime > 1000 / 60) { + thistime = timestamp; + core.clearMap(anctx); + core.plugin.playing.forEach((one) => { + const data = flags["animate_" + one.name]; + if (!data) { + core.plugin.playing.delete(one); + } else { + data.imageList.forEach(function (image) { + if ( + one.farme >= (image.beforefarme ?? 0) && + one.farme <= (image.afterfarme ?? data.allFarme) + ) { + const img = core.material.images.images?.[image.image]; + if (img) { + const gla = image.globalAlpha ?? 100; + const agla = image.aglobalAlpha ?? gla, + beforefarme = image.beforefarme ?? 0; + const afterfarme = image.afterfarme ?? data.allFarme; - anctx.globalAlpha = - (gla + - ((agla - gla) * (one.farme - beforefarme)) / - (afterfarme - beforefarme || 1)) / - 100; + anctx.globalAlpha = + (gla + + ((agla - gla) * (one.farme - beforefarme)) / + (afterfarme - beforefarme || 1)) / + 100; - const cx = - (image.cx ?? 0) + - (((image.acx ?? 0) - (image.cx ?? 0)) * - (one.farme - beforefarme)) / - (afterfarme - beforefarme || 1), - cy = - (image.cy ?? 0) + - (((image.acy ?? 0) - (image.cy ?? 0)) * - (one.farme - beforefarme)) / - (afterfarme - beforefarme || 1), - cw = - (image.cw ?? img.width) + - (((image.acw ?? img.width) - (image.cw ?? img.width)) * - (one.farme - beforefarme)) / - (afterfarme - beforefarme || 1), - ch = - (image.ch ?? img.height) + - (((image.acw ?? img.height) - (image.cw ?? img.height)) * - (one.farme - beforefarme)) / - (afterfarme - beforefarme || 1), - x = - (image.x ?? 0) + - (((image.ax ?? 0) - (image.x ?? 0)) * - (one.farme - beforefarme)) / - (afterfarme - beforefarme || 1), - y = - (image.y ?? 0) + - (((image.ay ?? 0) - (image.y ?? 0)) * - (one.farme - beforefarme)) / - (afterfarme - beforefarme || 1), - w = - (image.w ?? one.width) + - (((image.aw ?? one.width) - (image.w ?? one.width)) * - (one.farme - beforefarme)) / - (afterfarme - beforefarme || 1), - h = - (image.h ?? one.height) + - (((image.aw ?? one.height) - (image.w ?? one.height)) * - (one.farme - beforefarme)) / - (afterfarme - beforefarme || 1), - angle = - (Math.PI * - ((image.image.angle ?? 0) + - (((image.aangle ?? 0) - (image.image.angle ?? 0)) * - (one.farme - beforefarme)) / - (afterfarme - beforefarme || 1))) / - 180; + const cx = + (image.cx ?? 0) + + (((image.acx ?? 0) - (image.cx ?? 0)) * + (one.farme - beforefarme)) / + (afterfarme - beforefarme || 1), + cy = + (image.cy ?? 0) + + (((image.acy ?? 0) - (image.cy ?? 0)) * + (one.farme - beforefarme)) / + (afterfarme - beforefarme || 1), + cw = + (image.cw ?? img.width) + + (((image.acw ?? img.width) - (image.cw ?? img.width)) * + (one.farme - beforefarme)) / + (afterfarme - beforefarme || 1), + ch = + (image.ch ?? img.height) + + (((image.acw ?? img.height) - (image.cw ?? img.height)) * + (one.farme - beforefarme)) / + (afterfarme - beforefarme || 1), + x = + (image.x ?? 0) + + (((image.ax ?? 0) - (image.x ?? 0)) * + (one.farme - beforefarme)) / + (afterfarme - beforefarme || 1), + y = + (image.y ?? 0) + + (((image.ay ?? 0) - (image.y ?? 0)) * + (one.farme - beforefarme)) / + (afterfarme - beforefarme || 1), + w = + (image.w ?? one.width) + + (((image.aw ?? one.width) - (image.w ?? one.width)) * + (one.farme - beforefarme)) / + (afterfarme - beforefarme || 1), + h = + (image.h ?? one.height) + + (((image.aw ?? one.height) - (image.w ?? one.height)) * + (one.farme - beforefarme)) / + (afterfarme - beforefarme || 1), + angle = + (Math.PI * + ((image.image.angle ?? 0) + + (((image.aangle ?? 0) - (image.image.angle ?? 0)) * + (one.farme - beforefarme)) / + (afterfarme - beforefarme || 1))) / + 180; - if (one.hero) { - let sx, sy; - if (core.status.heroMoving < 0) { - sx = 0; - sy = 0; - } else { - sx = - core.utils.scan[core.status.hero.loc.direction].x * - 4 * - core.status.heroMoving; - sy = - core.utils.scan[core.status.hero.loc.direction].y * - 4 * - core.status.heroMoving; - } - const herox = core.status.hero.loc.x * 32 + 16 + sx; - const heroy = core.status.hero.loc.y * 32 + 16 + sy; - core.drawImage( - anctx, - img, - cx, - cy, - cw, - ch, - herox + (x - data.px) * one.scalex, - heroy + (y - data.py) * one.scaley, - w * one.scalex, - h * one.scaley, - angle - ); - } else { - core.drawImage( - anctx, - img, - cx, - cy, - cw, - ch, - one.x + (x - data.px) * one.scalex, - one.y + (y - data.py) * one.scaley, - w * one.scalex, - h * one.scaley, - angle - ); - } - } - } - }); - data.soundList.forEach(function (sound) { - const lisen = - sound.sound && - core.sounds[sound.sound] && - core.musicStatus.soundStatus; - if (one.farme == sound.startfarme && lisen) { - if (sound.stopbefore) core.stopSound(); - core.playSound(sound.sound); - } - }); - one.farme++; - if (one.farme > data.allFarme) { - core.plugin.playing.delete(one); - if (one.callback) { - one.callback(); - } - } - } - }); - } - }); - }, + if (one.hero) { + let sx, sy; + if (core.status.heroMoving < 0) { + sx = 0; + sy = 0; + } else { + sx = + core.utils.scan[core.status.hero.loc.direction].x * + 4 * + core.status.heroMoving; + sy = + core.utils.scan[core.status.hero.loc.direction].y * + 4 * + core.status.heroMoving; + } + const herox = core.status.hero.loc.x * 32 + 16 + sx; + const heroy = core.status.hero.loc.y * 32 + 16 + sy; + core.drawImage( + anctx, + img, + cx, + cy, + cw, + ch, + herox + (x - data.px) * one.scalex, + heroy + (y - data.py) * one.scaley, + w * one.scalex, + h * one.scaley, + angle + ); + } else { + core.drawImage( + anctx, + img, + cx, + cy, + cw, + ch, + one.x + (x - data.px) * one.scalex, + one.y + (y - data.py) * one.scaley, + w * one.scalex, + h * one.scaley, + angle + ); + } + } + } + }); + data.soundList.forEach(function (sound) { + const lisen = + sound.sound && + core.sounds[sound.sound] && + core.musicStatus.soundStatus; + if (one.farme == sound.startfarme && lisen) { + if (sound.stopbefore) core.stopSound(); + core.playSound(sound.sound); + } + }); + one.farme++; + if (one.farme > data.allFarme) { + core.plugin.playing.delete(one); + if (one.callback) { + one.callback(); + } + } + } + }); + } + }); +}, "intro&loop": function () { // 在此增加新插件 this.introAndLoop = function (intro, time, loop) { @@ -19605,14 +19990,15 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = const ctx = animateAttack.getContext("2d"); main.dom.gameDraw.appendChild(animateAttack); - + const { lcm, gcd } = core.plugin.utils this.drawAttackAnimate = function ( heroInfo, oneTurn, enemyInfo, equipInfo, farme, - damageInfo + damageInfo, + onegcd ) { let attack = false; if (heroInfo.isAttack) attack = true; @@ -19852,8 +20238,8 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = "bold 36px pala" ); - if (!attack) enemyInfo.now += (enemyInfo.speed / oneTurn) * 215; - let enemynow = Math.min(100 + enemyInfo.now, 315); + if (!attack) enemyInfo.now += enemyInfo.speed / onegcd; + let enemynow = Math.min(100 + enemyInfo.now / oneTurn * 215, 315); ctx.fillStyle = "#FFFFFF"; ctx.beginPath(); ctx.moveTo(enemynow, 100); @@ -19891,8 +20277,8 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = } core.drawLine(ctx, 100, 105, 315, 105, "#FFFFFF", 5); equipInfo.forEach(function (v) { - if (!attack) v.now += (v.speed / oneTurn) * 215; - let vnow = Math.min(100 + v.now, 315); + if (!attack) v.now += v.speed / onegcd; + let vnow = Math.min(100 + v.now / oneTurn * 215, 315); ctx.beginPath(); ctx.moveTo(vnow, 100); ctx.lineTo(vnow + 3, 90); @@ -19903,41 +20289,60 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = core.drawIcon(ctx, v.id, vnow - 16, 64, 32, 32); }); - if (!attack) heroInfo.now += (heroInfo.speed / oneTurn) * 215; - let heronow = Math.min(100 + heroInfo.now, 315); + if (!attack) heroInfo.now += hero.speed / onegcd; + let heronow = Math.min(100 + heroInfo.now / oneTurn * 215, 315); ctx.beginPath(); ctx.moveTo(heronow, 100); - ctx.lineTo(heronow + 3, 90); - ctx.lineTo(heronow - 3, 90); + ctx.lineTo(heronow + 5, 90); + ctx.lineTo(heronow - 5, 90); ctx.closePath(); ctx.fill(); core.drawImage(ctx, "hero.webp", 0, 0, 32, 19, heronow - 16, 70, 32, 19); + let nowattacking = false + if (heroInfo.now >= oneTurn && !heroInfo.isAttack) { - if (heroInfo.now >= 215 && !heroInfo.isAttack) { heroInfo.isAttack = true; - animateOnAttack("sword", true, () => { - heroInfo.now -= 215; - heroInfo.isAttack = false; - }); - } - if (enemyInfo.now >= 215 && !enemyInfo.isAttack) { - enemyInfo.isAttack = true; - animateOnAttack("sword", false, () => { - enemyInfo.now -= 215; - enemyInfo.isAttack = false; - }); - } - equipInfo.forEach((v) => { - if (v.now >= 215 && !v.isAttack) { - v.isAttack = true; + nowattacking = true + + } + if (enemyInfo.now >= oneTurn && !enemyInfo.isAttack) { + + enemyInfo.isAttack = true; + nowattacking = true + + } + const equipanimate = [] + equipInfo.forEach(v => { + if (v.now >= oneTurn && !v.isAttack) { + v.isAttack = true; + nowattacking = true + equipanimate.push(v) - animateOnAttack("sword", true, () => { - v.now -= 215; - v.isAttack = false; - }); } }); + if (!attack && nowattacking) { + if (heroInfo.isAttack) { + animateOnAttack("sword", true, () => { + heroInfo.now = 0; + heroInfo.isAttack = false; + }); + } + if (enemyInfo.isAttack) { + animateOnAttack("sword", false, () => { + enemyInfo.now = 0; + enemyInfo.isAttack = false; + }); + } + if (equipanimate.length > 0) { + equipanimate.forEach(v => { + animateOnAttack("sword", true, () => { + v.now = 0; + v.isAttack = false; + }); + }) + } + } }; function animateOnAttack(name, onenemy, callback) { @@ -19985,15 +20390,18 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = enemyInfo.name = core.material.enemys[enemyId].name; enemyInfo.now = 0; enemyInfo.isAttack = false; - let oneTurn = heroInfo.speed + enemyInfo.speed; + let oneTurn = [heroInfo.speed, enemyInfo.speed]; if (equipInfo.length > 0) { for (let i; i < equipInfo.length - 1; i++) { equipInfo[i].now = 0; equipInfo[i].isAttack = false; - oneTurn += equipInfo[i].speed; + oneTurn.push(equipInfo[i].speed); } } - oneTurn *= 25; + + const onegcd = gcd(...oneTurn) + oneTurn = lcm(...oneTurn) / onegcd + if (oneTurn < 60) oneTurn *= Math.round(60 / oneTurn) let time = 0, farme = 0; @@ -20006,7 +20414,8 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = enemyInfo, equipInfo, farme, - damageInfo + damageInfo, + onegcd ); farme++; }