diff --git a/_server/table/comment.js b/_server/table/comment.js index 15d2b679..1a63a47f 100644 --- a/_server/table/comment.js +++ b/_server/table/comment.js @@ -106,6 +106,14 @@ var comment_c456ea59_6018_45ef_8bcc_211a24c627dc = { "_lint": true, "_docs": "能否使用或装备", "_data": "当前能否使用或装备该道具,仅对cls不为items有效。null表示始终不可使用但可装备" + }, + "noBatchUse": { + "_leaf": true, + "_type": "textarea", + "_string": true, + "_lint": true, + "_docs": "不可批量使用", + "_data": "该道具是否不允许批量使用,true表示不可批量使用" } } }, diff --git a/libs/ui.js b/libs/ui.js index a48dcebb..38ed9806 100644 --- a/libs/ui.js +++ b/libs/ui.js @@ -2699,13 +2699,28 @@ ui.prototype._drawToolbox = function (index) { } ////// 获得所有应该在道具栏显示的某个类型道具 ////// -ui.prototype.getToolboxItems = function (cls) { - if (this.uidata.getToolboxItems) { - return this.uidata.getToolboxItems(cls); +ui.prototype.getToolboxItems = function (cls, showHide) { + let list = Object.keys(core.status.hero.items[cls] || {});; + if (cls === 'all') { + for (let name in core.status.hero.items) { + if (name == "equips") continue; + list = list.concat(Object.keys(core.status.hero.items[name])); // 获取'constants'和'tools'整体的列表 + } + if (!showHide) list = list.filter(function (id) { + return !core.material.items[id].hideInToolbox; + }) + list = list.sort(); + return list; } - return Object.keys(core.status.hero.items[cls] || {}) - .filter(function (id) { return !core.material.items[id].hideInToolbox; }) - .sort(); + + if (this.uidata.getToolboxItems) { + return this.uidata.getToolboxItems(cls, showHide); + } + if (!showHide) list = list.filter(function (id) { + return !core.material.items[id].hideInToolbox; + }) + list = list.sort(); + return list; } ui.prototype._drawToolbox_getInfo = function (index) { diff --git a/mynote.md b/mynote.md index 4335e0fe..6340c596 100644 --- a/mynote.md +++ b/mynote.md @@ -18,3 +18,49 @@ extractBlocks->_mapIntoBlocks->initBlock cannotOut和cannotIn的关键 箭头还在getBlockByNumber中 + +首先抽象一下 思考一下顶层设计 +ItemBox类 +需要的属性:当前持有的Item和数量 当前的页数 + +使用道具时,情况会改变,所以,每次重绘时,都需要获取一遍core.status.hero.items,然后依据此获取一个列表itemList。根据当前页数(currPage)获取该绘制的内容。 + +整个道具栏做成一个大按钮,还需要属性selectedItem 每次根据selectedItem重绘右侧的物品详细说明 + +按钮可往前不往后,以防一页的道具全用光会不去 + +点击时:点左侧 根据位置和itemList和currPage推导处在哪里,更新selectedItem,更新右侧 左侧是一个大按钮 +点下方 左右 currPage +右侧按键: +使用 尝试使用selectedItem +批量使用 新功能 +隐藏/显示 修改道具的隐藏属性 +显示隐藏 页面级属性 showHidedItem + +最高级 MenuPage 名为boxPage +拥有背景和背景中的两个箭头和道具栏|装备栏的字样 +按键切换两栏 监听tab等 +右下角的× + +toolBox 拥有底部两按钮,右侧的一切,中间的大按钮 +equipBox 拥有 +```js +const itemClsName = { + "constants": "永久道具", + "tools": "消耗道具", +} +const itemNum = 12; + +core.initThisEventInfo(); +let info = core.status.thisUIEventInfo +info.index = 1; +core.setIndexAndSelect('select'); +let ctx =core.canvas.ui; +core.status.thisEventClickArea = []; + +let info1 = core.drawBoxBackground(ctx); +info1.itemNum = itemNum; +core.drawItemListbox(ctx, info1.obj); +core.drawToolboxRightbar(ctx, info1); + +``` \ No newline at end of file diff --git a/project/floors/MT0.js b/project/floors/MT0.js index 5e1adb34..da474738 100644 --- a/project/floors/MT0.js +++ b/project/floors/MT0.js @@ -7,7 +7,7 @@ main.floors.MT0= "canFlyFrom": true, "canUseQuickShop": true, "cannotViewMap": false, - "defaultGround": "ground", + "defaultGround": "X10036", "images": [], "ratio": 2, "map": [ @@ -16,9 +16,9 @@ main.floors.MT0= [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [ 0, 0, 0, 0, 0,121,121, 0, 0, 0, 0, 0, 0], [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [ 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0], [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], @@ -28,18 +28,25 @@ main.floors.MT0= "firstArrive": [], "parallelDo": "", "events": { - "6,5": [ - "欢迎使用事件编辑器(双击方块可直接预览)" - ], - "5,5": [ - "欢迎使用事件编辑器(双击方块可直接预览)", + "6,8": [ { - "type": "jumpHero", - "loc": [ - 0, - 0 - ], - "time": 500 + "type": "setValue", + "name": "item:poisonWine", + "value": "2" + }, + { + "type": "setValue", + "name": "item:yellowKey", + "value": "99" + }, + { + "type": "setValue", + "name": "item:silverCoin", + "value": "999" + }, + { + "type": "comment", + "text": "unlockControl" } ] }, diff --git a/project/functions.js b/project/functions.js index 4b21d4e5..e91e3593 100644 --- a/project/functions.js +++ b/project/functions.js @@ -1,8 +1,8 @@ /// -var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = +var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = { - "events": { - "resetGame": function (hero, hard, floorId, maps, values) { + "events": { + "resetGame": function (hero, hard, floorId, maps, values) { // 重置整个游戏;此函数将在游戏开始时,或者每次读档时最先被调用 // hero:勇士信息;hard:难度;floorId:当前楼层ID;maps:地图信息;values:全局数值信息 @@ -53,7 +53,7 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = // 隐藏右下角的音乐按钮 core.dom.musicBtn.style.display = 'none'; }, - "win": function (reason, norank, noexit) { + "win": function (reason, norank, noexit) { // 游戏获胜事件 // 请注意,成绩统计时是按照hp进行上传并排名 // 可以先在这里对最终分数进行计算,比如将2倍攻击和5倍黄钥匙数量加到分数上 @@ -82,7 +82,7 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = }) }); }, - "lose": function (reason) { + "lose": function (reason) { // 游戏失败事件 core.ui.closePanel(); var replaying = core.isReplaying(); @@ -95,7 +95,7 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = }); }) }, - "changingFloor": function (floorId, heroLoc) { + "changingFloor": function (floorId, heroLoc) { // 正在切换楼层过程中执行的操作;此函数的执行时间是“屏幕完全变黑“的那一刻 // floorId为要切换到的楼层ID;heroLoc表示勇士切换到的位置 @@ -165,7 +165,7 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = // ...可以新增一些其他内容,比如创建个画布在右上角显示什么内容等等 }, - "afterChangeFloor": function (floorId) { + "afterChangeFloor": function (floorId) { // 转换楼层结束的事件;此函数会在整个楼层切换完全结束后再执行 // floorId是切换到的楼层 @@ -184,7 +184,7 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = } } }, - "flyTo": function (toId, callback) { + "flyTo": function (toId, callback) { // 楼层传送器的使用,从当前楼层飞往toId // 如果不能飞行请返回false @@ -227,7 +227,7 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = return true; }, - "beforeBattle": function (enemyId, x, y) { + "beforeBattle": function (enemyId, x, y) { // 战斗前触发的事件,可以加上一些战前特效(详见下面支援的例子) // 此函数在“检测能否战斗和自动存档”【之后】执行。如果需要更早的战前事件,请在插件中覆重写 core.events.doSystemEvent 函数。 // 返回true则将继续战斗,返回false将不再战斗。 @@ -258,7 +258,7 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = return true; }, - "afterBattle": function (enemyId, x, y) { + "afterBattle": function (enemyId, x, y) { // 战斗结束后触发的事件 var enemy = core.material.enemys[enemyId]; @@ -472,7 +472,7 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = core.clearContinueAutomaticRoute(); }, - "afterOpenDoor": function (doorId, x, y) { + "afterOpenDoor": function (doorId, x, y) { // 开一个门后触发的事件 var todo = []; @@ -493,7 +493,7 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = else core.clearContinueAutomaticRoute(); }, - "afterGetItem": function (itemId, x, y, isGentleClick) { + "afterGetItem": function (itemId, x, y, isGentleClick) { // 获得一个道具后触发的事件 // itemId:获得的道具ID;x和y是该道具所在的坐标 // isGentleClick:是否是轻按触发的 @@ -515,7 +515,7 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = if (todo.length > 0) core.insertAction(todo, x, y); }, - "afterPushBox": function () { + "afterPushBox": function () { // 推箱子后的事件 if (core.searchBlock('box').length == 0) { // 可以通过if语句来进行开门操作 @@ -528,9 +528,9 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = */ } } - }, - "enemys": { - "getSpecials": function () { + }, + "enemys": { + "getSpecials": function () { // 获得怪物的特殊属性,每一行定义一个特殊属性。 // 分为五项,第一项为该特殊属性的数字,第二项为特殊属性的名字,第三项为特殊属性的描述 // 第四项为该特殊属性的颜色,可以写十六进制 #RRGGBB 或者 [r,g,b,a] 四元数组 @@ -569,7 +569,7 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = [30, "吸噬", function (enemy) { return ""; }, "#c0ddbb"], ]; }, - "getEnemyInfo": function (enemy, hero, x, y, floorId) { + "getEnemyInfo": function (enemy, hero, x, y, floorId) { // 获得某个怪物变化后的数据;该函数将被伤害计算和怪物手册使用 // 例如:坚固、模仿、仿攻等等 // @@ -692,7 +692,7 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = "guards": guards, // 返回支援情况 }; }, - "getDamageInfo": function (enemy, hero, x, y, floorId) { + "getDamageInfo": function (enemy, hero, x, y, floorId) { // 获得战斗伤害信息(实际伤害计算函数) // // 参数说明: @@ -850,9 +850,9 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = "damage": Math.floor(damage) }; } - }, - "actions": { - "onKeyUp": function (keyCode, altKey) { + }, + "actions": { + "onKeyUp": function (keyCode, altKey) { // 键盘按键处理,可以在这里自定义快捷键列表 // keyCode:当前按键的keyCode(每个键的keyCode自行百度) // altKey:Alt键是否被按下,为true代表同时按下了Alt键 @@ -1029,7 +1029,7 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = } }, - "onStatusBarClick": function (px, py, vertical) { + "onStatusBarClick": function (px, py, vertical) { // 点击状态栏时触发的事件,仅在自绘状态栏开启时生效 // px和py为点击的像素坐标 // vertical为录像播放过程中的横竖屏信息 @@ -1097,9 +1097,9 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = */ } - }, - "control": { - "saveData": function () { + }, + "control": { + "saveData": function () { // 存档操作,此函数应该返回“具体要存档的内容” // 差异化存储values @@ -1124,7 +1124,7 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = return data; }, - "loadData": function (data, callback) { + "loadData": function (data, callback) { // 读档操作;从存储中读取了内容后的行为 // 重置游戏和路线 @@ -1163,7 +1163,7 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = if (callback) callback(); }); }, - "getStatusLabel": function (name) { + "getStatusLabel": function (name) { // 返回某个状态英文名的对应中文标签,如atk -> 攻击,def -> 防御等。 // 请注意此项仅影响 libs/ 下的内容(如绘制怪物手册、数据统计等) // 自行定义的(比如获得道具效果)中用到的“攻击+3”等需要自己去对应地方修改 @@ -1184,7 +1184,7 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = steps: "步数", }[name] || name; }, - "triggerDebuff": function (action, type) { + "triggerDebuff": function (action, type) { // 毒衰咒效果的获得与解除 // action:获得还是解除;'get'表示获得,'remove'表示解除 // type:一个数组表示获得了哪些毒衰咒效果;poison, weak,curse @@ -1241,7 +1241,7 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = if (success) core.playSound('回血'); } }, - "updateStatusBar": function () { + "updateStatusBar": function () { // 更新状态栏 // 检查等级 @@ -1323,7 +1323,7 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = // updateDamage只能在此处执行!!更新全地图显伤 core.updateDamage(); }, - "getCheckBlock": function (floorId) { + "getCheckBlock": function (floorId) { // 领域、夹击、阻击等的伤害值计算 floorId = floorId || core.status.floorId; if (!floorId || !core.status.maps) return; @@ -1563,7 +1563,7 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = cache: {} // clear cache }; }, - "moveOneStep": function (callback) { + "moveOneStep": function (callback) { // 勇士每走一步后执行的操作。callback为行走完毕后的回调 // 这个函数执行在“刚走完”的时候,即还没有检查该点的事件和领域伤害等。 // 请注意:瞬间移动不会执行该函数。如果要控制能否瞬间移动有三种方法: @@ -1626,7 +1626,7 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = // 如需强行终止行走可以在这里条件判定: // core.stopAutomaticRoute(); }, - "moveDirectly": function (x, y, ignoreSteps) { + "moveDirectly": function (x, y, ignoreSteps) { // 瞬间移动;x,y为要瞬间移动的点;ignoreSteps为减少的步数,可能之前已经被计算过 // 返回true代表成功瞬移,false代表没有成功瞬移 @@ -1664,7 +1664,7 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = } return false; }, - "parallelDo": function (timestamp) { + "parallelDo": function (timestamp) { // 并行事件处理,可以在这里写任何需要并行处理的脚本或事件 // 该函数将被系统反复执行,每次执行间隔视浏览器或设备性能而定,一般约为16.6ms一次 // 参数timestamp为“从游戏资源加载完毕到当前函数执行时”的时间差,以毫秒为单位 @@ -1681,19 +1681,23 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = } } } - }, - "ui": { - "getToolboxItems": function (cls) { - // 获得道具栏中当前某类型道具的显示项和显示顺序 - // cls为道具类型,只可能是 tools, constants 和 equips - // 返回一个数组,代表当前某类型道具的显示内容和顺序 - // 默认按id升序排列,您可以取消下面的注释改为按名称排列 + }, + "ui": { + "getToolboxItems": function (cls, showHide) { + // 获得道具栏中当前某类型道具的显示项和显示顺序 + // cls为道具类型,只可能是 tools, constants 和 equips + // 返回一个数组,代表当前某类型道具的显示内容和顺序 + // 默认按id升序排列,您可以取消下面的注释改为按名称排列 + // showHide 是否显示隐藏的道具 - return Object.keys(core.status.hero.items[cls] || {}) - .filter(function (id) { return !core.material.items[id].hideInToolbox; }) - .sort( /*function (id1, id2) { return core.material.items[id1].name <= core.material.items[id2].name ? -1 : 1 }*/); - }, - "drawStatusBar": function () { + let list = Object.keys(core.status.hero.items[cls] || {}); + if (!showHide) list = list.filter(function (id) { + return !core.material.items[id].hideInToolbox; + }) + list = list.sort( /*function (id1, id2) { return core.material.items[id1].name <= core.material.items[id2].name ? -1 : 1 }*/ ); + return list; +}, + "drawStatusBar": function () { // 自定义绘制状态栏,需要开启状态栏canvas化 // 如果是非状态栏canvas化,直接返回 @@ -1796,7 +1800,7 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = _fillBoldTextWithFontCheck(core.setTwoDigits(core.itemCount('redKey')), 212, 90, '#FF8888'); } }, - "drawStatistics": function () { + "drawStatistics": function () { // 浏览地图时参与的统计项目 return [ @@ -1812,7 +1816,7 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = // 在这里可以增加新的ID来进行统计个数,只能增加道具ID ]; }, - "drawAbout": function () { + "drawAbout": function () { // 绘制“关于”界面 core.ui.closePanel(); core.lockControl(); @@ -1840,5 +1844,5 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = // TODO: 写自己的“关于”页面,每次增加32像素即可 core.playSound('打开界面'); } - } + } } \ No newline at end of file diff --git a/project/items.js b/project/items.js index 2a61392d..07d73f25 100644 --- a/project/items.js +++ b/project/items.js @@ -357,7 +357,8 @@ var items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a = "text": "可以查看当前楼层各怪物属性", "hideInToolbox": true, "useItemEffect": "core.ui.drawBook(0);", - "canUseItemEffect": "true" + "canUseItemEffect": "true", + "noBatchUse": "true" }, "fly": { "cls": "constants", @@ -366,7 +367,8 @@ var items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a = "hideInReplay": true, "hideInToolbox": true, "useItemEffect": "core.ui.drawFly(core.floorIds.indexOf(core.status.floorId));", - "canUseItemEffect": "(function () {\n\tif (core.flags.flyNearStair && !core.nearStair()) return false;\n\treturn core.status.maps[core.status.floorId].canFlyFrom;\n})();" + "canUseItemEffect": "(function () {\n\tif (core.flags.flyNearStair && !core.nearStair()) return false;\n\treturn core.status.maps[core.status.floorId].canFlyFrom;\n})();", + "noBatchUse": "true" }, "coin": { "cls": "constants", @@ -440,7 +442,8 @@ var items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a = "name": "中心对称飞行器", "text": "可以飞向当前楼层中心对称的位置", "useItemEffect": "core.playSound('centerFly.mp3');\ncore.clearMap('hero');\ncore.setHeroLoc('x', core.bigmap.width - 1 - core.getHeroLoc('x'));\ncore.setHeroLoc('y', core.bigmap.height - 1 - core.getHeroLoc('y'));\ncore.drawHero();\ncore.drawTip(core.material.items[itemId].name + '使用成功');", - "canUseItemEffect": "(function () {\n\tvar toX = core.bigmap.width - 1 - core.getHeroLoc('x'),\n\t\ttoY = core.bigmap.height - 1 - core.getHeroLoc('y');\n\tvar id = core.getBlockId(toX, toY);\n\treturn id == null;\n})();" + "canUseItemEffect": "(function () {\n\tvar toX = core.bigmap.width - 1 - core.getHeroLoc('x'),\n\t\ttoY = core.bigmap.height - 1 - core.getHeroLoc('y');\n\tvar id = core.getBlockId(toX, toY);\n\treturn id == null;\n})();", + "noBatchUse": "true" }, "upFly": { "cls": "tools", @@ -519,9 +522,18 @@ var items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a = "canUseItemEffect": "true" }, "silverCoin": { - "cls": "items", + "cls": "tools", "name": "新物品", - "canUseItemEffect": "true" + "canUseItemEffect": "true", + "useItemEffect": "core.status.hero.hp += 1;", + "useItemEvent": [ + { + "type": "setValue", + "name": "status:hp", + "operator": "+=", + "value": "1" + } + ] }, "orb": { "cls": "items", @@ -538,7 +550,8 @@ var items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a = "name": "设置", "canUseItemEffect": "true", "text": "可以调节设置开关。", - "useItemEffect": "core.plugin.openSetting();" + "useItemEffect": "core.plugin.openSetting();", + "noBatchUse": "true" }, "redWand": { "cls": "items", diff --git a/project/plugins.js b/project/plugins.js index 709c9528..c275cee0 100644 --- a/project/plugins.js +++ b/project/plugins.js @@ -1,7 +1,7 @@ /// -var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = +var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = { - "init": function () { + "init": function () { console.log("插件编写测试"); @@ -19,7 +19,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = // 可以在任何地方(如afterXXX或自定义脚本事件)调用函数,方法为 core.plugin.xxx(); // 从V2.6开始,插件中用this.XXX方式定义的函数也会被转发到core中,详见文档-脚本-函数的转发。 }, - "shop": function () { + "shop": function () { // 【全局商店】相关的功能 // // 打开一个全局商店 @@ -214,7 +214,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = return false; }, 60); }, - "removeMap": function () { + "removeMap": function () { // 高层塔砍层插件,删除后不会存入存档,不可浏览地图也不可飞到。 // 推荐用法: // 对于超高层或分区域塔,当在1区时将2区以后的地图删除;1区结束时恢复2区,进二区时删除1区地图,以此类推 @@ -301,7 +301,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = }); } }, - "fiveLayers": function () { + "fiveLayers": function () { // 是否启用五图层(增加背景2层和前景2层) 将__enable置为true即会启用;启用后请保存后刷新编辑器 // 背景层2将会覆盖背景层 被事件层覆盖 前景层2将会覆盖前景层 // 另外 请注意加入两个新图层 会让大地图的性能降低一些 @@ -455,7 +455,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = }; } }, - "itemShop": function () { + "itemShop": function () { // 道具商店相关的插件 // 可在全塔属性-全局商店中使用「道具商店」事件块进行编辑(如果找不到可以在入口方块中找) @@ -761,7 +761,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = } }, - "enemyLevel": function () { + "enemyLevel": function () { // 此插件将提供怪物手册中的怪物境界显示 // 使用此插件需要先给每个怪物定义境界,方法如下: // 点击怪物的【配置表格】,找到“【怪物】相关的表格配置”,然后在【名称】仿照增加境界定义: @@ -849,7 +849,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = }, - "multiHeros": function () { + "multiHeros": function () { // 多角色插件 // Step 1: 启用本插件 // Step 2: 定义每个新的角色各项初始数据(参见下方注释) @@ -995,7 +995,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = core.setFlag("heroId", toHeroId); // 保存切换到的角色ID } }, - "heroFourFrames": function () { + "heroFourFrames": function () { // 样板的勇士/跟随者移动时只使用2、4两帧,观感较差。本插件可以将四帧全用上。 // 是否启用本插件 @@ -1048,7 +1048,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = return false; } }, - "startCanvas": function () { + "startCanvas": function () { // 使用本插件可以将自绘的标题界面居中。仅在【标题开启事件化】后才有效。 // 由于一些技术性的原因,标题界面事件化无法应用到覆盖状态栏的整个界面。 // 这是一个较为妥协的插件,会在自绘标题界面时隐藏状态栏、工具栏和边框,并将画布进行居中。 @@ -1134,564 +1134,593 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = _loadData.call(core.control, data, callback); } }, - "advancedAnimation": function () { - // -------------------- 插件说明 -------------------- // - // github仓库:https://github.com/unanmed/animate - // npm包名:mutate-animate - // npm地址:https://www.npmjs.com/package/mutate-animate + "advancedAnimation": function () { + // -------------------- 插件说明 -------------------- // + // github仓库:https://github.com/unanmed/animate + // npm包名:mutate-animate + // npm地址:https://www.npmjs.com/package/mutate-animate - if (main.replayChecking) return core.plugin.animate = {} + // 是否开启本插件,默认启用;将此改成 false 将禁用本插件。 + var __enable = false; - // 保存所有Ticker的引用 - const tickersMap = new Map(); + if (main.replayChecking) __enable = false; + if (!__enable) { + core.plugin.animate = { + Ticker: class { + add() { } + } + }; + this.deleteTicker = () => { }; + this.deleteAllTickers = () => { }; + this.getAllTickers = () => { }; + return; + } + // core.plugin.animate = { + // Animation: j, + // AnimationBase: F, + // Ticker: I, + // Transition: O, + // bezier: q, + // bezierPath: H, + // circle: D, + // hyper: G, + // inverseTrigo: N, + // linear: Y, + // power: C, + // shake: B, + // sleep: R, + // trigo: U, + // } + // 保存所有Ticker的引用 + const tickersMap = new Map(); - /** 摧毁指定名字的ticker */ - this.deleteTicker = function (name) { - const ticker = tickersMap.get(name); + /** 摧毁指定名字的ticker */ + this.deleteTicker = function (name) { + const ticker = tickersMap.get(name); + if (!ticker) return; + ticker.destroy(); + tickersMap.delete(name); + } + + /** 摧毁所有有名字的ticker */ + this.deleteAllTickers = function () { + tickersMap.forEach((ticker) => { if (!ticker) return; ticker.destroy(); - tickersMap.delete(name); - } + }) + tickersMap.clear(); + } - /** 摧毁所有有名字的ticker */ - this.deleteAllTickers = function () { - tickersMap.forEach((ticker) => { - if (!ticker) return; - ticker.destroy(); - }) - tickersMap.clear(); - } + this.getAllTickers = () => tickersMap; - this.getAllTickers = () => tickersMap; - - var M = Object.defineProperty; - var E = (n, i, t) => i in n ? M(n, i, { enumerable: !0, configurable: !0, writable: !0, value: t }) : n[i] = t; - var o = (n, i, t) => (E(n, typeof i != "symbol" ? i + "" : i, t), t); - let w = []; - const k = (n) => { - for (const i of w) - if (i.status === "running") - try { - for (const t of i.funcs) - t(n - i.startTime); - } catch (t) { - i.destroy(), console.error(t); - } - requestAnimationFrame(k); - }; + var M = Object.defineProperty; + var E = (n, i, t) => i in n ? M(n, i, { enumerable: !0, configurable: !0, writable: !0, value: t }) : n[i] = t; + var o = (n, i, t) => (E(n, typeof i != "symbol" ? i + "" : i, t), t); + let w = []; + const k = (n) => { + for (const i of w) + if (i.status === "running") + try { + for (const t of i.funcs) + t(n - i.startTime); + } catch (t) { + i.destroy(), console.error(t); + } requestAnimationFrame(k); - class I { - constructor() { - o(this, "funcs", /* @__PURE__ */ new Set()); - o(this, "status", "stop"); - o(this, "startTime", 0); - this.status = "running", w.push(this), requestAnimationFrame((i) => this.startTime = i); - } - add(i) { - return this.funcs.add(i), this; - } - remove(i) { - return this.funcs.delete(i), this; - } - clear() { - this.funcs.clear(); - } - destroy() { - this.clear(), this.stop(); - } - stop() { - this.status = "stop", w = w.filter((i) => i !== this); - } + }; + requestAnimationFrame(k); + class I { + constructor() { + o(this, "funcs", /* @__PURE__ */ new Set()); + o(this, "status", "stop"); + o(this, "startTime", 0); + this.status = "running", w.push(this), requestAnimationFrame((i) => this.startTime = i); } - class F { - constructor(name) { - o(this, "timing"); - o(this, "relation", "absolute"); - o(this, "easeTime", 0); - o(this, "applying", {}); - o(this, "getTime", Date.now); - const ticker = new I(); - o(this, "ticker", ticker); - o(this, "value", {}); - o(this, "listener", {}); - this.timing = (i) => i; - if (typeof name === 'string') tickersMap.set(name, ticker); - } - async all() { - if (Object.values(this.applying).every((i) => i === !0)) - throw new ReferenceError("There is no animates to be waited."); - await new Promise((i) => { - const t = () => { - Object.values(this.applying).every((e) => e === !1) && (this.unlisten("end", t), i("all animated.")); - }; - this.listen("end", t); - }); - } - async n(i) { - const t = Object.values(this.applying).filter((s) => s === !0).length; - if (t < i) - throw new ReferenceError( - `You are trying to wait ${i} animate, but there are only ${t} animate animating.` - ); - let e = 0; - await new Promise((s) => { - const r = () => { - e++, e === i && (this.unlisten("end", r), s(`${i} animated.`)); - }; - this.listen("end", r); - }); - } - async w(i) { - if (this.applying[i] === !1) - throw new ReferenceError(`The ${i} animate is not animating.`); - await new Promise((t) => { - const e = () => { - this.applying[i] === !1 && (this.unlisten("end", e), t(`${i} animated.`)); - }; - this.listen("end", e); - }); - } - listen(i, t) { - var e, s; - (s = (e = this.listener)[i]) != null || (e[i] = []), this.listener[i].push(t); - } - unlisten(i, t) { - const e = this.listener[i].findIndex((s) => s === t); - if (e === -1) - throw new ReferenceError( - "You are trying to remove a nonexistent listener." - ); - this.listener[i].splice(e, 1); - } - hook(...i) { - const t = Object.entries(this.listener).filter( - (e) => i.includes(e[0]) + add(i) { + return this.funcs.add(i), this; + } + remove(i) { + return this.funcs.delete(i), this; + } + clear() { + this.funcs.clear(); + } + destroy() { + this.clear(), this.stop(); + } + stop() { + this.status = "stop", w = w.filter((i) => i !== this); + } + } + class F { + constructor(name) { + o(this, "timing"); + o(this, "relation", "absolute"); + o(this, "easeTime", 0); + o(this, "applying", {}); + o(this, "getTime", Date.now); + const ticker = new I(); + o(this, "ticker", ticker); + o(this, "value", {}); + o(this, "listener", {}); + this.timing = (i) => i; + if (typeof name === 'string') tickersMap.set(name, ticker); + } + async all() { + if (Object.values(this.applying).every((i) => i === !0)) + throw new ReferenceError("There is no animates to be waited."); + await new Promise((i) => { + const t = () => { + Object.values(this.applying).every((e) => e === !1) && (this.unlisten("end", t), i("all animated.")); + }; + this.listen("end", t); + }); + } + async n(i) { + const t = Object.values(this.applying).filter((s) => s === !0).length; + if (t < i) + throw new ReferenceError( + `You are trying to wait ${i} animate, but there are only ${t} animate animating.` ); - for (const [e, s] of t) - for (const r of s) - r(this, e); - } + let e = 0; + await new Promise((s) => { + const r = () => { + e++, e === i && (this.unlisten("end", r), s(`${i} animated.`)); + }; + this.listen("end", r); + }); } + async w(i) { + if (this.applying[i] === !1) + throw new ReferenceError(`The ${i} animate is not animating.`); + await new Promise((t) => { + const e = () => { + this.applying[i] === !1 && (this.unlisten("end", e), t(`${i} animated.`)); + }; + this.listen("end", e); + }); + } + listen(i, t) { + var e, s; + (s = (e = this.listener)[i]) != null || (e[i] = []), this.listener[i].push(t); + } + unlisten(i, t) { + const e = this.listener[i].findIndex((s) => s === t); + if (e === -1) + throw new ReferenceError( + "You are trying to remove a nonexistent listener." + ); + this.listener[i].splice(e, 1); + } + hook(...i) { + const t = Object.entries(this.listener).filter( + (e) => i.includes(e[0]) + ); + for (const [e, s] of t) + for (const r of s) + r(this, e); + } + } - function y(n) { - return n != null; + function y(n) { + return n != null; + } + async function R(n) { + return new Promise((i) => setTimeout(i, n)); + } + class j extends F { + constructor() { + super(); + o(this, "shakeTiming"); + o(this, "path"); + o(this, "multiTiming"); + o(this, "value", {}); + o(this, "size", 1); + o(this, "angle", 0); + o(this, "targetValue", { + system: { + move: [0, 0], + moveAs: [0, 0], + resize: 0, + rotate: 0, + shake: 0, + "@@bind": [] + }, + custom: {} + }); + o(this, "animateFn", { + system: { + move: [() => 0, () => 0], + moveAs: () => 0, + resize: () => 0, + rotate: () => 0, + shake: () => 0, + "@@bind": () => 0 + }, + custom: {} + }); + o(this, "ox", 0); + o(this, "oy", 0); + o(this, "sx", 0); + o(this, "sy", 0); + o(this, "bindInfo", []); + this.timing = (t) => t, this.shakeTiming = (t) => t, this.multiTiming = (t) => [t, t], this.path = (t) => [t, t], this.applying = { + move: !1, + scale: !1, + rotate: !1, + shake: !1 + }, this.ticker.add(() => { + const { running: t } = this.listener; + if (y(t)) + for (const e of t) + e(this, "running"); + }); } - async function R(n) { - return new Promise((i) => setTimeout(i, n)); + get x() { + return this.ox + this.sx; } - class j extends F { - constructor() { - super(); - o(this, "shakeTiming"); - o(this, "path"); - o(this, "multiTiming"); - o(this, "value", {}); - o(this, "size", 1); - o(this, "angle", 0); - o(this, "targetValue", { - system: { - move: [0, 0], - moveAs: [0, 0], - resize: 0, - rotate: 0, - shake: 0, - "@@bind": [] - }, - custom: {} + get y() { + return this.oy + this.sy; + } + mode(t, e = !1) { + return typeof t(0) == "number" ? e ? this.shakeTiming = t : this.timing = t : this.multiTiming = t, this; + } + time(t) { + return this.easeTime = t, this; + } + relative() { + return this.relation = "relative", this; + } + absolute() { + return this.relation = "absolute", this; + } + bind(...t) { + return this.applying["@@bind"] === !0 && this.end(!1, "@@bind"), this.bindInfo = t, this; + } + unbind() { + return this.applying["@@bind"] === !0 && this.end(!1, "@@bind"), this.bindInfo = [], this; + } + move(t, e) { + return this.applying.move && this.end(!0, "move"), this.applySys("ox", t, "move"), this.applySys("oy", e, "move"), this; + } + rotate(t) { + return this.applySys("angle", t, "rotate"), this; + } + scale(t) { + return this.applySys("size", t, "resize"), this; + } + shake(t, e) { + this.applying.shake === !0 && this.end(!0, "shake"), this.applying.shake = !0; + const { easeTime: s, shakeTiming: r } = this, l = this.getTime(); + if (this.hook("start", "shakestart"), s <= 0) + return this.end(!1, "shake"), this; + const a = () => { + const c = this.getTime() - l; + if (c > s) { + this.ticker.remove(a), this.applying.shake = !1, this.sx = 0, this.sy = 0, this.hook("end", "shakeend"); + return; + } + const h = c / s, + m = r(h); + this.sx = m * t, this.sy = m * e; + }; + return this.ticker.add(a), this.animateFn.system.shake = a, this; + } + moveAs(t) { + this.applying.moveAs && this.end(!0, "moveAs"), this.applying.moveAs = !0, this.path = t; + const { easeTime: e, relation: s, timing: r } = this, l = this.getTime(), [a, u] = [this.x, this.y], [c, h] = (() => { + if (s === "absolute") + return t(1); { + const [d, f] = t(1); + return [a + d, u + f]; + } + })(); + if (this.hook("start", "movestart"), e <= 0) + return this.end(!1, "moveAs"), this; + const m = () => { + const f = this.getTime() - l; + if (f > e) { + this.end(!0, "moveAs"); + return; + } + const g = f / e, + [v, x] = t(r(g)); + s === "absolute" ? (this.ox = v, this.oy = x) : (this.ox = a + v, this.oy = u + x); + }; + return this.ticker.add(m), this.animateFn.system.moveAs = m, this.targetValue.system.moveAs = [c, h], this; + } + register(t, e) { + if (typeof this.value[t] == "number") + return this.error( + `Property ${t} has been regietered twice.`, + "reregister" + ); + this.value[t] = e, this.applying[t] = !1; + } + apply(t, e) { + this.applying[t] === !0 && this.end(!1, t), t in this.value || this.error( + `You are trying to execute nonexistent property ${t}.` + ), this.applying[t] = !0; + const s = this.value[t], + r = this.getTime(), + { timing: l, relation: a, easeTime: u } = this, + c = a === "absolute" ? e - s : e; + if (this.hook("start"), u <= 0) + return this.end(!1, t), this; + const h = () => { + const d = this.getTime() - r; + if (d > u) { + this.end(!1, t); + return; + } + const f = d / u, + g = l(f); + this.value[t] = s + g * c; + }; + return this.ticker.add(h), this.animateFn.custom[t] = h, this.targetValue.custom[t] = c + s, this; + } + applyMulti() { + this.applying["@@bind"] === !0 && this.end(!1, "@@bind"), this.applying["@@bind"] = !0; + const t = this.bindInfo, + e = t.map((h) => this.value[h]), + s = this.getTime(), + { multiTiming: r, relation: l, easeTime: a } = this, + u = r(1); + if (u.length !== e.length) + throw new TypeError( + `The number of binded animate attributes and timing function returns's length does not match. binded: ${t.length}, timing: ${u.length}` + ); + if (this.hook("start"), a <= 0) + return this.end(!1, "@@bind"), this; + const c = () => { + const m = this.getTime() - s; + if (m > a) { + this.end(!1, "@@bind"); + return; + } + const d = m / a, + f = r(d); + t.forEach((g, v) => { + l === "absolute" ? this.value[g] = f[v] : this.value[g] = e[v] + f[v]; }); - o(this, "animateFn", { - system: { - move: [() => 0, () => 0], - moveAs: () => 0, - resize: () => 0, - rotate: () => 0, - shake: () => 0, - "@@bind": () => 0 - }, - custom: {} - }); - o(this, "ox", 0); - o(this, "oy", 0); - o(this, "sx", 0); - o(this, "sy", 0); - o(this, "bindInfo", []); - this.timing = (t) => t, this.shakeTiming = (t) => t, this.multiTiming = (t) => [t, t], this.path = (t) => [t, t], this.applying = { - move: !1, - scale: !1, - rotate: !1, - shake: !1 - }, this.ticker.add(() => { - const { running: t } = this.listener; - if (y(t)) - for (const e of t) - e(this, "running"); - }); - } - get x() { - return this.ox + this.sx; - } - get y() { - return this.oy + this.sy; - } - mode(t, e = !1) { - return typeof t(0) == "number" ? e ? this.shakeTiming = t : this.timing = t : this.multiTiming = t, this; - } - time(t) { - return this.easeTime = t, this; - } - relative() { - return this.relation = "relative", this; - } - absolute() { - return this.relation = "absolute", this; - } - bind(...t) { - return this.applying["@@bind"] === !0 && this.end(!1, "@@bind"), this.bindInfo = t, this; - } - unbind() { - return this.applying["@@bind"] === !0 && this.end(!1, "@@bind"), this.bindInfo = [], this; - } - move(t, e) { - return this.applying.move && this.end(!0, "move"), this.applySys("ox", t, "move"), this.applySys("oy", e, "move"), this; - } - rotate(t) { - return this.applySys("angle", t, "rotate"), this; - } - scale(t) { - return this.applySys("size", t, "resize"), this; - } - shake(t, e) { - this.applying.shake === !0 && this.end(!0, "shake"), this.applying.shake = !0; - const { easeTime: s, shakeTiming: r } = this, l = this.getTime(); - if (this.hook("start", "shakestart"), s <= 0) - return this.end(!1, "shake"), this; - const a = () => { - const c = this.getTime() - l; - if (c > s) { - this.ticker.remove(a), this.applying.shake = !1, this.sx = 0, this.sy = 0, this.hook("end", "shakeend"); - return; - } - const h = c / s, - m = r(h); - this.sx = m * t, this.sy = m * e; - }; - return this.ticker.add(a), this.animateFn.system.shake = a, this; - } - moveAs(t) { - this.applying.moveAs && this.end(!0, "moveAs"), this.applying.moveAs = !0, this.path = t; - const { easeTime: e, relation: s, timing: r } = this, l = this.getTime(), [a, u] = [this.x, this.y], [c, h] = (() => { - if (s === "absolute") - return t(1); { - const [d, f] = t(1); - return [a + d, u + f]; - } - })(); - if (this.hook("start", "movestart"), e <= 0) - return this.end(!1, "moveAs"), this; - const m = () => { - const f = this.getTime() - l; - if (f > e) { - this.end(!0, "moveAs"); - return; - } - const g = f / e, - [v, x] = t(r(g)); - s === "absolute" ? (this.ox = v, this.oy = x) : (this.ox = a + v, this.oy = u + x); - }; - return this.ticker.add(m), this.animateFn.system.moveAs = m, this.targetValue.system.moveAs = [c, h], this; - } - register(t, e) { - if (typeof this.value[t] == "number") - return this.error( - `Property ${t} has been regietered twice.`, - "reregister" - ); - this.value[t] = e, this.applying[t] = !1; - } - apply(t, e) { - this.applying[t] === !0 && this.end(!1, t), t in this.value || this.error( - `You are trying to execute nonexistent property ${t}.` - ), this.applying[t] = !0; - const s = this.value[t], - r = this.getTime(), - { timing: l, relation: a, easeTime: u } = this, - c = a === "absolute" ? e - s : e; - if (this.hook("start"), u <= 0) - return this.end(!1, t), this; - const h = () => { - const d = this.getTime() - r; - if (d > u) { - this.end(!1, t); - return; - } - const f = d / u, - g = l(f); - this.value[t] = s + g * c; - }; - return this.ticker.add(h), this.animateFn.custom[t] = h, this.targetValue.custom[t] = c + s, this; - } - applyMulti() { - this.applying["@@bind"] === !0 && this.end(!1, "@@bind"), this.applying["@@bind"] = !0; - const t = this.bindInfo, - e = t.map((h) => this.value[h]), - s = this.getTime(), - { multiTiming: r, relation: l, easeTime: a } = this, - u = r(1); - if (u.length !== e.length) - throw new TypeError( - `The number of binded animate attributes and timing function returns's length does not match. binded: ${t.length}, timing: ${u.length}` - ); - if (this.hook("start"), a <= 0) - return this.end(!1, "@@bind"), this; - const c = () => { - const m = this.getTime() - s; - if (m > a) { - this.end(!1, "@@bind"); - return; - } - const d = m / a, - f = r(d); - t.forEach((g, v) => { - l === "absolute" ? this.value[g] = f[v] : this.value[g] = e[v] + f[v]; - }); - }; - return this.ticker.add(c), this.animateFn.custom["@@bind"] = c, this.targetValue.system["@@bind"] = u, this; - } - applySys(t, e, s) { - s !== "move" && this.applying[s] === !0 && this.end(!0, s), this.applying[s] = !0; - const r = this[t], - l = this.getTime(), - a = this.timing, - u = this.relation, - c = this.easeTime, - h = u === "absolute" ? e - r : e; - if (this.hook("start", `${s}start`), c <= 0) - return this.end(!0, s); - const m = () => { - const f = this.getTime() - l; - if (f > c) { - this.end(!0, s); - return; - } - const g = f / c, - v = a(g); - this[t] = r + h * v, t !== "oy" && this.hook(s); - }; - this.ticker.add(m), t === "ox" ? this.animateFn.system.move[0] = m : t === "oy" ? this.animateFn.system.move[1] = m : this.animateFn.system[s] = m, s === "move" ? (t === "ox" && (this.targetValue.system.move[0] = h + r), t === "oy" && (this.targetValue.system.move[1] = h + r)) : s !== "shake" && (this.targetValue.system[s] = h + r); - } - error(t, e) { - throw e === "repeat" ? new Error( - `Cannot execute the same animation twice. Info: ${t}` - ) : e === "reregister" ? new Error( - `Cannot register an animated property twice. Info: ${t}` - ) : new Error(t); - } - end(t, e) { - if (t === !0) - if (this.applying[e] = !1, e === "move" ? (this.ticker.remove(this.animateFn.system.move[0]), this.ticker.remove(this.animateFn.system.move[1])) : e === "moveAs" ? this.ticker.remove(this.animateFn.system.moveAs) : e === "@@bind" ? this.ticker.remove(this.animateFn.system["@@bind"]) : this.ticker.remove( + }; + return this.ticker.add(c), this.animateFn.custom["@@bind"] = c, this.targetValue.system["@@bind"] = u, this; + } + applySys(t, e, s) { + s !== "move" && this.applying[s] === !0 && this.end(!0, s), this.applying[s] = !0; + const r = this[t], + l = this.getTime(), + a = this.timing, + u = this.relation, + c = this.easeTime, + h = u === "absolute" ? e - r : e; + if (this.hook("start", `${s}start`), c <= 0) + return this.end(!0, s); + const m = () => { + const f = this.getTime() - l; + if (f > c) { + this.end(!0, s); + return; + } + const g = f / c, + v = a(g); + this[t] = r + h * v, t !== "oy" && this.hook(s); + }; + this.ticker.add(m), t === "ox" ? this.animateFn.system.move[0] = m : t === "oy" ? this.animateFn.system.move[1] = m : this.animateFn.system[s] = m, s === "move" ? (t === "ox" && (this.targetValue.system.move[0] = h + r), t === "oy" && (this.targetValue.system.move[1] = h + r)) : s !== "shake" && (this.targetValue.system[s] = h + r); + } + error(t, e) { + throw e === "repeat" ? new Error( + `Cannot execute the same animation twice. Info: ${t}` + ) : e === "reregister" ? new Error( + `Cannot register an animated property twice. Info: ${t}` + ) : new Error(t); + } + end(t, e) { + if (t === !0) + if (this.applying[e] = !1, e === "move" ? (this.ticker.remove(this.animateFn.system.move[0]), this.ticker.remove(this.animateFn.system.move[1])) : e === "moveAs" ? this.ticker.remove(this.animateFn.system.moveAs) : e === "@@bind" ? this.ticker.remove(this.animateFn.system["@@bind"]) : this.ticker.remove( this.animateFn.system[e] ), e === "move") { - const [s, r] = this.targetValue.system.move; - this.ox = s, this.oy = r, this.hook("moveend", "end"); - } else if (e === "moveAs") { - const [s, r] = this.targetValue.system.moveAs; - this.ox = s, this.oy = r, this.hook("moveend", "end"); - } else - e === "rotate" ? (this.angle = this.targetValue.system.rotate, this.hook("rotateend", "end")) : e === "resize" ? (this.size = this.targetValue.system.resize, this.hook("resizeend", "end")) : e === "@@bind" ? this.bindInfo.forEach((r, l) => { - this.value[r] = this.targetValue.system["@@bind"][l]; - }) : (this.sx = 0, this.sy = 0, this.hook("shakeend", "end")); - else - this.applying[e] = !1, this.ticker.remove(this.animateFn.custom[e]), this.value[e] = this.targetValue.custom[e], this.hook("end"); - } + const [s, r] = this.targetValue.system.move; + this.ox = s, this.oy = r, this.hook("moveend", "end"); + } else if (e === "moveAs") { + const [s, r] = this.targetValue.system.moveAs; + this.ox = s, this.oy = r, this.hook("moveend", "end"); + } else + e === "rotate" ? (this.angle = this.targetValue.system.rotate, this.hook("rotateend", "end")) : e === "resize" ? (this.size = this.targetValue.system.resize, this.hook("resizeend", "end")) : e === "@@bind" ? this.bindInfo.forEach((r, l) => { + this.value[r] = this.targetValue.system["@@bind"][l]; + }) : (this.sx = 0, this.sy = 0, this.hook("shakeend", "end")); + else + this.applying[e] = !1, this.ticker.remove(this.animateFn.custom[e]), this.value[e] = this.targetValue.custom[e], this.hook("end"); } - class O extends F { - constructor() { - super(); - o(this, "now", {}); - o(this, "target", {}); - o(this, "transitionFn", {}); - o(this, "value"); - o(this, "handleSet", (t, e, s) => (this.transition(e, s), !0)); - o(this, "handleGet", (t, e) => this.now[e]); - this.timing = (t) => t, this.value = new Proxy(this.target, { - set: this.handleSet, - get: this.handleGet - }); - } - mode(t) { - return this.timing = t, this; - } - time(t) { - return this.easeTime = t, this; - } - relative() { - return this.relation = "relative", this; - } - absolute() { - return this.relation = "absolute", this; - } - transition(t, e) { - if (e === this.target[t]) - return this; - if (!y(this.now[t])) - return this.now[t] = e, this; - this.applying[t] && this.end(t, !0), this.applying[t] = !0, this.hook("start"); - const s = this.getTime(), - r = this.easeTime, - l = this.timing, - a = this.now[t], - u = e + (this.relation === "absolute" ? 0 : a), - c = u - a; - this.target[t] = u; - const h = () => { - const d = this.getTime() - s; - if (d >= r) { - this.end(t); - return; - } - const f = d / r; - this.now[t] = l(f) * c + a, this.hook("running"); - }; - return this.transitionFn[t] = h, this.ticker.add(h), r <= 0 ? (this.end(t), this) : this; - } - end(t, e = !1) { - const s = this.transitionFn[t]; - if (!y(s)) - throw new ReferenceError( - `You are trying to end an ended transition: ${t}` - ); - this.ticker.remove(this.transitionFn[t]), delete this.transitionFn[t], this.applying[t] = !1, this.hook("end"), e || (this.now[t] = this.target[t]); - } + } + class O extends F { + constructor() { + super(); + o(this, "now", {}); + o(this, "target", {}); + o(this, "transitionFn", {}); + o(this, "value"); + o(this, "handleSet", (t, e, s) => (this.transition(e, s), !0)); + o(this, "handleGet", (t, e) => this.now[e]); + this.timing = (t) => t, this.value = new Proxy(this.target, { + set: this.handleSet, + get: this.handleGet + }); } - const T = (...n) => n.reduce((i, t) => i + t, 0), - b = (n) => { - if (n === 0) - return 1; - let i = n; - for (; n > 1;) - n--, i *= n; - return i; - }, - A = (n, i) => Math.round(b(i) / (b(n) * b(i - n))), - p = (n, i, t = (e) => 1 - i(1 - e)) => n === "in" ? i : n === "out" ? t : n === "in-out" ? (e) => e < 0.5 ? i(e * 2) / 2 : 0.5 + t((e - 0.5) * 2) / 2 : (e) => e < 0.5 ? t(e * 2) / 2 : 0.5 + i((e - 0.5) * 2) / 2, - $ = Math.cosh(2), - z = Math.acosh(2), - V = Math.tanh(3), - P = Math.atan(5); - - function Y() { - return (n) => n; + mode(t) { + return this.timing = t, this; } - - function q(...n) { - const i = [0].concat(n); - i.push(1); - const t = i.length, - e = Array(t).fill(0).map((s, r) => A(r, t - 1)); - return (s) => { - const r = e.map((l, a) => l * i[a] * (1 - s) ** (t - a - 1) * s ** a); - return T(...r); + time(t) { + return this.easeTime = t, this; + } + relative() { + return this.relation = "relative", this; + } + absolute() { + return this.relation = "absolute", this; + } + transition(t, e) { + if (e === this.target[t]) + return this; + if (!y(this.now[t])) + return this.now[t] = e, this; + this.applying[t] && this.end(t, !0), this.applying[t] = !0, this.hook("start"); + const s = this.getTime(), + r = this.easeTime, + l = this.timing, + a = this.now[t], + u = e + (this.relation === "absolute" ? 0 : a), + c = u - a; + this.target[t] = u; + const h = () => { + const d = this.getTime() - s; + if (d >= r) { + this.end(t); + return; + } + const f = d / r; + this.now[t] = l(f) * c + a, this.hook("running"); }; + return this.transitionFn[t] = h, this.ticker.add(h), r <= 0 ? (this.end(t), this) : this; } - - function U(n, i) { - if (n === "sin") { - const t = (s) => Math.sin(s * Math.PI / 2); - return p(i, (s) => 1 - t(1 - s), t); - } - if (n === "sec") { - const t = (s) => 1 / Math.cos(s); - return p(i, (s) => t(s * Math.PI / 3) - 1); - } - throw new TypeError( - "Unexpected parameters are delivered in trigo timing function." - ); - } - - function C(n, i) { - if (!Number.isInteger(n)) - throw new TypeError( - "The first parameter of power timing function only allow integer." + end(t, e = !1) { + const s = this.transitionFn[t]; + if (!y(s)) + throw new ReferenceError( + `You are trying to end an ended transition: ${t}` ); - return p(i, (e) => e ** n); + this.ticker.remove(this.transitionFn[t]), delete this.transitionFn[t], this.applying[t] = !1, this.hook("end"), e || (this.now[t] = this.target[t]); } + } + const T = (...n) => n.reduce((i, t) => i + t, 0), + b = (n) => { + if (n === 0) + return 1; + let i = n; + for (; n > 1;) + n--, i *= n; + return i; + }, + A = (n, i) => Math.round(b(i) / (b(n) * b(i - n))), + p = (n, i, t = (e) => 1 - i(1 - e)) => n === "in" ? i : n === "out" ? t : n === "in-out" ? (e) => e < 0.5 ? i(e * 2) / 2 : 0.5 + t((e - 0.5) * 2) / 2 : (e) => e < 0.5 ? t(e * 2) / 2 : 0.5 + i((e - 0.5) * 2) / 2, + $ = Math.cosh(2), + z = Math.acosh(2), + V = Math.tanh(3), + P = Math.atan(5); - function G(n, i) { - if (n === "sin") - return p(i, (e) => (Math.cosh(e * 2) - 1) / ($ - 1)); - if (n === "tan") { - const t = (s) => Math.tanh(s * 3) * 1 / V; - return p(i, (s) => 1 - t(1 - s), t); - } - if (n === "sec") { - const t = (s) => 1 / Math.cosh(s); - return p(i, (s) => 1 - (t(s * z) - 0.5) * 2); - } + function Y() { + return (n) => n; + } + + function q(...n) { + const i = [0].concat(n); + i.push(1); + const t = i.length, + e = Array(t).fill(0).map((s, r) => A(r, t - 1)); + return (s) => { + const r = e.map((l, a) => l * i[a] * (1 - s) ** (t - a - 1) * s ** a); + return T(...r); + }; + } + + function U(n, i) { + if (n === "sin") { + const t = (s) => Math.sin(s * Math.PI / 2); + return p(i, (s) => 1 - t(1 - s), t); + } + if (n === "sec") { + const t = (s) => 1 / Math.cos(s); + return p(i, (s) => t(s * Math.PI / 3) - 1); + } + throw new TypeError( + "Unexpected parameters are delivered in trigo timing function." + ); + } + + function C(n, i) { + if (!Number.isInteger(n)) throw new TypeError( - "Unexpected parameters are delivered in hyper timing function." + "The first parameter of power timing function only allow integer." ); - } + return p(i, (e) => e ** n); + } - function N(n, i) { - if (n === "sin") { - const t = (s) => Math.asin(s) / Math.PI * 2; - return p(i, (s) => 1 - t(1 - s), t); - } - if (n === "tan") { - const t = (s) => Math.atan(s * 5) / P; - return p(i, (s) => 1 - t(1 - s), t); - } - throw new TypeError( - "Unexpected parameters are delivered in inverse trigo timing function." - ); + function G(n, i) { + if (n === "sin") + return p(i, (e) => (Math.cosh(e * 2) - 1) / ($ - 1)); + if (n === "tan") { + const t = (s) => Math.tanh(s * 3) * 1 / V; + return p(i, (s) => 1 - t(1 - s), t); } - - function B(n, i = () => 1) { - let t = -1; - return (e) => (t *= -1, e < 0.5 ? n * i(e * 2) * t : n * i((1 - e) * 2) * t); + if (n === "sec") { + const t = (s) => 1 / Math.cosh(s); + return p(i, (s) => 1 - (t(s * z) - 0.5) * 2); } + throw new TypeError( + "Unexpected parameters are delivered in hyper timing function." + ); + } - function D(n, i = 1, t = [0, 0], e = 0, s = (l) => 1, r = !1) { - return (l) => { - const a = i * l * Math.PI * 2 + e * Math.PI / 180, - u = Math.cos(a), - c = Math.sin(a), - h = n * s(s(r ? 1 - l : l)); - return [h * u + t[0], h * c + t[1]]; - }; + function N(n, i) { + if (n === "sin") { + const t = (s) => Math.asin(s) / Math.PI * 2; + return p(i, (s) => 1 - t(1 - s), t); } - - function H(n, i, ...t) { - const e = [n].concat(t); - e.push(i); - const s = e.length, - r = Array(s).fill(0).map((l, a) => A(a, s - 1)); - return (l) => { - const a = r.map((c, h) => c * e[h][0] * (1 - l) ** (s - h - 1) * l ** h), - u = r.map((c, h) => c * e[h][1] * (1 - l) ** (s - h - 1) * l ** h); - return [T(...a), T(...u)]; - }; + if (n === "tan") { + const t = (s) => Math.atan(s * 5) / P; + return p(i, (s) => 1 - t(1 - s), t); } + throw new TypeError( + "Unexpected parameters are delivered in inverse trigo timing function." + ); + } - core.plugin.animate = { - Animation: j, - AnimationBase: F, - Ticker: I, - Transition: O, - bezier: q, - bezierPath: H, - circle: D, - hyper: G, - inverseTrigo: N, - linear: Y, - power: C, - shake: B, - sleep: R, - trigo: U, - } + function B(n, i = () => 1) { + let t = -1; + return (e) => (t *= -1, e < 0.5 ? n * i(e * 2) * t : n * i((1 - e) * 2) * t); + } - }, - "drawItemDetail": function () { + function D(n, i = 1, t = [0, 0], e = 0, s = (l) => 1, r = !1) { + return (l) => { + const a = i * l * Math.PI * 2 + e * Math.PI / 180, + u = Math.cos(a), + c = Math.sin(a), + h = n * s(s(r ? 1 - l : l)); + return [h * u + t[0], h * c + t[1]]; + }; + } + + function H(n, i, ...t) { + const e = [n].concat(t); + e.push(i); + const s = e.length, + r = Array(s).fill(0).map((l, a) => A(a, s - 1)); + return (l) => { + const a = r.map((c, h) => c * e[h][0] * (1 - l) ** (s - h - 1) * l ** h), + u = r.map((c, h) => c * e[h][1] * (1 - l) ** (s - h - 1) * l ** h); + return [T(...a), T(...u)]; + }; + } + + core.plugin.animate = { + Animation: j, + AnimationBase: F, + Ticker: I, + Transition: O, + bezier: q, + bezierPath: H, + circle: D, + hyper: G, + inverseTrigo: N, + linear: Y, + power: C, + shake: B, + sleep: R, + trigo: U, + } + +}, + "drawItemDetail": function () { /* 宝石血瓶左下角显示数值 * 需要将 变量:itemDetail改为true才可正常运行 * 请尽量减少勇士的属性数量,否则可能会出现严重卡顿(划掉,现在你放一万个属性也不会卡) @@ -1891,7 +1920,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = } } }, - "autoGet": function () { + "autoGet": function () { // 在此增加新插件 /** * --------------- 使用说明 --------------- @@ -1908,10 +1937,9 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = const ctxName = 'globalAnimate'; - if (!main.replayChecking) { + if (!core.isReplaying() && Ticker) { const ticker = new Ticker(); ticker.add(() => { - if (!core.isPlaying()) return; const ctx = core.getContextByName(ctxName); if (!has(ctx)) return; core.clearMap(ctx); @@ -2168,1033 +2196,16 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = core.updateStatusBar(); }; }, - "newBackpackLook": function () { - // 注:///// *** 裹起来的区域: 该区域内参数可以随意更改调整ui绘制 不会影响总体布局 - // 请尽量修改该区域而不是其他区域 修改的时候最好可以对照现有ui修改 - - ///// *** 道具类型 - // cls对应name - var itemClsName = { - "constants": "永久道具", - "tools": "消耗道具", - } - // 一页最大放的道具数量 将把整个道具左栏分成num份 每份是一个道具项 - var itemNum = 12; - ///// *** - - // 背景设置 - this.drawBoxBackground = function (ctx) { - core.setTextAlign(ctx, "left"); - core.clearMap(ctx); - core.deleteCanvas("_selector"); - var info = core.status.thisUIEventInfo || {}; - - ///// *** 背景设置 - var max = core.__PIXELS__; - var x = 2, - y = x, - w = max - x * 2, - h = w; - var borderWidth = 2, - borderRadius = 5, // radius:圆角矩形的圆角半径 - borderStyle = "#fff"; - var backgroundColor = "gray"; - // 设置背景不透明度(0.85) - var backgroundAlpha = 0.85; - ///// *** - - var start_x = x + borderWidth / 2, - start_y = y + borderWidth / 2, - width = max - start_x * 2, - height = max - start_y * 2; - - // 渐变色背景的一个例子(黑色渐变白色): - // 有关渐变色的具体知识请网上搜索canvas createGradient了解 - /* - var grd = ctx.createLinearGradient(x, y, x + w, y); - grd.addColorStop(0, "black"); - grd.addColorStop(1, "white"); - backgroundColor = grd; - */ - // 使用图片背景要注释掉下面的strokeRect和fillRoundRect - // 图片背景的一个例子: - /* - core.drawImage(ctx, "xxx.png", x, y, w, h); - core.strokeRect(ctx, x, y, w, h, borderStyle, borderWidth); - */ - core.setAlpha(ctx, backgroundAlpha); - core.strokeRoundRect(ctx, x, y, w, h, borderRadius, borderStyle, borderWidth); - core.fillRoundRect(ctx, start_x, start_y, width, height, borderRadius, backgroundColor); - core.setAlpha(ctx, 1); - - ///// *** 左栏配置 - var leftbar_height = height; - // 左边栏宽度(width*0.6) 本身仅为坐标使用 需要与底下的rightbar_width(width*0.4)同时更改 - var leftbar_width = width * 0.6; - ///// *** - - // xxx_right参数 代表最右侧坐标 - var leftbar_right = start_x + leftbar_width - borderWidth / 2; - var leftbar_bottom = start_y + leftbar_height; - var leftbar_x = start_x; - var leftbar_y = start_y; - - ///// *** 道具栏配置 - var boxName_color = "#fff"; - var boxName_fontSize = 15; - var boxName_font = core.ui._buildFont(boxName_fontSize, true); - var arrow_x = 10 + start_x; - var arrow_y = 10 + start_y; - var arrow_width = 20; - var arrow_style = "white"; - // 暂时只能是1 否则不太行 等待新样板(2.7.3)之后对drawArrow做优化 - var arrow_lineWidth = 1; - // 右箭头 - var rightArrow_right = leftbar_right - 10; - // 道具内栏顶部坐标 本质是通过该项 控制(道具栏顶部文字和箭头)与道具内栏顶部的间隔 - var itembar_top = arrow_y + 15; - ///// *** - - var itembar_right = rightArrow_right; - var boxName = core.status.event.id == "toolbox" ? "\r[yellow]道具栏\r | 装备栏" : "道具栏 | \r[yellow]装备栏\r"; - core.drawArrow(ctx, arrow_x + arrow_width, arrow_y, arrow_x, arrow_y, arrow_style, arrow_lineWidth); - core.drawArrow(ctx, rightArrow_right - arrow_width, arrow_y, rightArrow_right, arrow_y, arrow_style, arrow_lineWidth); - core.setTextAlign(ctx, "center"); - core.setTextBaseline(ctx, "middle"); - var changeBox = function () { - var id = core.status.event.id; - core.closePanel(); - if (id == "toolbox") core.openEquipbox(); - else core.openToolbox(); - } - core.fillText(ctx, boxName, (leftbar_right + leftbar_x) / 2, arrow_y + 2, boxName_color, boxName_font); - - ///// *** 底栏按钮 - var pageBtn_radius = 8; - // xxx_left 最左侧坐标 - var pageBtn_left = leftbar_x + 3; - var pageBtn_right = leftbar_right - 3; - // xxx_bottom 最底部坐标 - var pageBtn_bottom = leftbar_bottom - 2; - var pageBtn_borderStyle = "#fff"; - var pageBtn_borderWidth = 2; - var pageText_color = "#fff"; - // 底部按钮与上面的道具内栏的间隔大小 - var bottomSpace = 8; - ///// *** - - core.drawItemListbox_setPageBtn(ctx, pageBtn_left, pageBtn_right, pageBtn_bottom, pageBtn_radius, pageBtn_borderStyle, pageBtn_borderWidth); - var page = info.page || 1; - var pageFontSize = pageBtn_radius * 2 - 4; - var pageFont = core.ui._buildFont(pageFontSize); - core.setPageItems(page); - var num = itemNum; - if (core.status.event.id == "equipbox") num -= 5; - var maxPage = info.maxPage; - var pageText = page + " / " + maxPage; - core.setTextAlign(ctx, "center"); - core.setTextBaseline(ctx, "bottom"); - core.fillText(ctx, pageText, (leftbar_x + leftbar_right) / 2, pageBtn_bottom, pageText_color, pageFont); - core.addUIEventListener(start_x, start_y, leftbar_right - start_x, arrow_y - start_y + 13, changeBox); - var itembar_height = Math.ceil(pageBtn_bottom - pageBtn_radius * 2 - pageBtn_borderWidth / 2 - bottomSpace - itembar_top); - var oneItemHeight = (itembar_height - 4) / itemNum; - return { - x: start_x, - y: start_y, - width: width, - height: height, - leftbar_right: leftbar_right, - obj: { - x: arrow_x, - y: itembar_top, - width: itembar_right - arrow_x, - height: itembar_height, - oneItemHeight: oneItemHeight - } - } - } - - this.drawItemListbox = function (ctx, obj) { - ctx = ctx || core.canvas.ui; - var itembar_x = obj.x, - itembar_y = obj.y, - itembar_width = obj.width, - itembar_height = obj.height, - itemNum = obj.itemNum, - oneItemHeight = obj.oneItemHeight; - var itembar_right = itembar_x + itembar_width; - var info = core.status.thisUIEventInfo || {}; - var obj = {}; - var page = info.page || 1, - index = info.index, - select = info.select || {}; - - ///// *** 道具栏内栏配置 - var itembar_style = "black"; - var itembar_alpha = 0.7; - // 一个竖屏下减少道具显示的例子: - // if (core.domStyle.isVertical) itemNum = 10; - // 每个道具项的上下空隙占总高度的比例 - var itembar_marginHeightRatio = 0.2; - // 左右间隔空隙 - var item_marginLeft = 2; - var item_x = itembar_x + 2, - item_y = itembar_y + 2, - item_right = itembar_right - 2, - itemName_color = "#fff"; - // 修改此项以更换闪烁光标 - var item_selector = "winskin.png"; - ///// *** - - core.setAlpha(ctx, itembar_alpha); - core.fillRect(ctx, itembar_x, itembar_y, itembar_width, itembar_height, itembar_style); - core.setAlpha(ctx, 1); - var pageItems = core.setPageItems(page); - var marginHeight = itembar_marginHeightRatio * oneItemHeight; - core.setTextBaseline(ctx, "middle"); - var originColor = itemName_color; - for (var i = 0; i < pageItems.length; i++) { - itemName_color = originColor; - var item = pageItems[i]; - // 设置某个的字体颜色的一个例子 - // if (item.id == "xxx") itemName_color = "green"; - core.drawItemListbox_drawItem(ctx, item_x, item_right, item_y, oneItemHeight, item_marginLeft, marginHeight, itemName_color, pageItems[i]); - if (index == i + 1) core.ui._drawWindowSelector(item_selector, item_x + 1, item_y - 1, item_right - item_x - 2, oneItemHeight - 2); - item_y += oneItemHeight; - } - } - - this.drawToolboxRightbar = function (ctx, obj) { - ctx = ctx || core.canvas.ui; - var info = core.status.thisUIEventInfo || {}; - var page = info.page || 1, - index = info.index || 1, - select = info.select || {}; - var start_x = obj.x, - start_y = obj.y, - width = obj.width, - height = obj.height; - var toolboxRight = start_x + width, - toolboxBottom = start_y + height; - - - ///// *** 侧边栏(rightbar)背景设置(物品介绍) - var rightbar_width = width * 0.4; - var rightbar_height = height; - var rightbar_lineWidth = 2; - var rightbar_lineStyle = "#fff"; - ///// *** - - var rightbar_x = toolboxRight - rightbar_width - rightbar_lineWidth / 2; - var rightbar_y = start_y; - core.drawLine(ctx, rightbar_x, rightbar_y, rightbar_x, rightbar_y + rightbar_height, rightbar_lineStyle, rightbar_lineWidth); - - // 获取道具id(有可能为null) - var itemId = select.id; - var item = core.material.items[itemId]; - - ///// *** 侧边栏物品Icon信息 - var iconRect_y = rightbar_y + 10; - // space:间距 - // 这里布局设定iconRect与侧边栏左边框 itemName与工具栏右边框 itemRect与itemName的间距均为space - var space = 15; - var iconRect_x = rightbar_x + space; - var iconRect_radius = 2, - iconRect_width = 32, - iconRect_height = 32, - iconRect_style = "#fff", - iconRect_lineWidth = 2; - ///// *** - - var iconRect_bottom = iconRect_y + iconRect_height, - iconRect_right = iconRect_x + iconRect_width; - - ///// *** 侧边栏各项信息 - var itemTextFontSize = 15, - itemText_x = iconRect_x - 4, - itemText_y = Math.floor(start_y + rightbar_height * 0.25), // 坐标取整防止模糊 - itemClsFontSize = 15, - itemClsFont = core.ui._buildFont(itemClsFontSize), - itemClsColor = "#fff", - itemCls_x = itemText_x - itemClsFontSize / 2, - itemCls_middle = (iconRect_bottom + itemText_y) / 2, //_middle代表文字的中心y坐标 - itemNameFontSize = 18, - itemNameColor = "#fff", - itemNameFont = core.ui._buildFont(itemNameFontSize, true); - var itemName_x = iconRect_right + space; - var itemName_middle = iconRect_y + iconRect_height / 2 + iconRect_lineWidth; - // 修改这里可以编辑未选中道具时的默认值 - var defaultItem = { - cls: "constants", - name: "未知道具", - text: "没有道具最永久" - } - var defaultEquip = { - cls: "equips", - name: "未知装备", - text: "一无所有,又何尝不是一种装备", - equip: { - type: "装备" - } - } - ///// *** - - var originItem = item; - if (core.status.event.id == "equipbox") item = item || defaultEquip; - item = item || defaultItem; - var itemCls = item.cls, - itemName = item.name, - itemText = item.text; - itemText = core.replaceText(itemText); - /* 一个根据道具id修改道具名字(右栏)的例子 - * if (item.id == "xxx") itemNameColor = "red"; - */ - var itemClsName = core.getItemClsName(item); - var itemNameMaxWidth = rightbar_width - iconRect_width - iconRect_lineWidth * 2 - space * 2; - core.strokeRoundRect(ctx, iconRect_x, iconRect_y, iconRect_width, iconRect_height, iconRect_radius, iconRect_style, iconRect_lineWidth); - if (item.id) - core.drawIcon(ctx, item.id, iconRect_x + iconRect_lineWidth / 2, iconRect_y + iconRect_lineWidth / 2, iconRect_width - iconRect_lineWidth, iconRect_height - iconRect_lineWidth); - core.setTextAlign(ctx, "left"); - core.setTextBaseline(ctx, "middle"); - core.fillText(ctx, itemName, itemName_x, itemName_middle, itemNameColor, itemNameFont, itemNameMaxWidth); - core.fillText(ctx, "【" + itemClsName + "】", itemCls_x, itemCls_middle, itemClsColor, itemClsFont); - var statusText = ""; - if (core.status.event.id == "equipbox") { - var type = item.equip.type; - if (typeof type == "string") type = core.getEquipTypeByName(type); - var compare = core.compareEquipment(item.id, core.getEquip(type)); - if (info.select.action == "unload") compare = core.compareEquipment(null, item.id); - // --- 变化值... - for (var name in core.status.hero) { - if (typeof core.status.hero[name] != 'number') continue; - var nowValue = core.getRealStatus(name); - // 查询新值 - var newValue = Math.floor((core.getStatus(name) + (compare.value[name] || 0)) * - (core.getBuff(name) * 100 + (compare.percentage[name] || 0)) / 100); - if (nowValue == newValue) continue; - var color = newValue > nowValue ? '#00FF00' : '#FF0000'; - nowValue = core.formatBigNumber(nowValue); - newValue = core.formatBigNumber(newValue); - statusText += core.getStatusLabel(name) + " " + nowValue + "->\r[" + color + "]" + newValue + "\r\n"; - } - } - itemText = statusText + itemText; - core.drawTextContent(ctx, itemText, { - left: itemText_x, - top: itemText_y, - bold: false, - color: "white", - align: "left", - fontSize: itemTextFontSize, - maxWidth: rightbar_width - (itemText_x - rightbar_x) * 2 + itemTextFontSize / 2 - }); - - ///// *** 退出按钮设置 - var btnRadius = 10; - var btnBorderWidth = 2; - var btnRight = toolboxRight - 2; - var btnBottom = toolboxBottom - 2; - var btnBorderStyle = "#fff"; - ///// *** - - // 获取圆心位置 - var btn_x = btnRight - btnRadius - btnBorderWidth / 2; - btn_y = btnBottom - btnRadius - btnBorderWidth / 2; - core.drawToolbox_setExitBtn(ctx, btn_x, btn_y, btnRadius, btnBorderStyle, btnBorderWidth); - - ///// *** 使用按钮设置 - var useBtnHeight = btnRadius * 2; - // 这里不设置useBtnWidth而是根据各项数据自动得出width - var useBtnRadius = useBtnHeight / 2; - var useBtn_x = rightbar_x + 4, - useBtn_y = btnBottom - useBtnHeight; - var useBtnBorderStyle = "#fff"; - var useBtnBorderWidth = btnBorderWidth; - ///// *** - - core.drawToolbox_setUseBtn(ctx, useBtn_x, useBtn_y, useBtnRadius, useBtnHeight, useBtnBorderStyle, useBtnBorderWidth); - } - - this.drawEquipbox_drawOthers = function (ctx, obj) { - var info = core.status.thisUIEventInfo; - - ///// *** 装备格设置 - var equipList_lineWidth = 2; - var equipList_boxSize = 32; - var equipList_borderWidth = 2; - var equipList_borderStyle = "#fff"; - var equipList_nameColor = "#fff"; - ///// *** - - var equipList_x = obj.x + 4, - equipList_bottom = obj.obj.y - equipList_lineWidth, - equipList_y = equipList_bottom - obj.obj.oneItemHeight * reduceItem - 2, - equipList_height = equipList_bottom - equipList_y; - var equipList_right = obj.leftbar_right, - equipList_width = equipList_right - equipList_x; - core.drawLine(ctx, obj.x, equipList_bottom + equipList_lineWidth / 2, equipList_right, equipList_bottom + equipList_lineWidth / 2, equipList_borderStyle, equipList_lineWidth); - var toDrawList = core.status.globalAttribute.equipName, - len = toDrawList.length; - - ///// *** 装备格设置 - var maxItem = 4; - var box_width = 32, - box_height = 32, - box_borderStyle = "#fff", - box_selectBorderStyle = "gold", // 选中的装备格的颜色 - box_borderWidth = 2; - var boxName_fontSize = 14, - boxName_space = 2, - boxName_color = "#fff"; // 装备格名称与上面的装备格框的距离 - var maxLine = Math.ceil(len / maxItem); - ///// *** - var l = Math.sqrt(len) - if (Math.pow(l) == len && len != 4) { - if (l <= maxItem) maxItem = l; - } - maxItem = Math.min(toDrawList.length, maxItem); - info.equips = maxItem; - - var boxName_font = core.ui._buildFont(boxName_fontSize); - // 总宽高减去所有装备格宽高得到空隙大小 - var oneBoxWidth = box_width + box_borderWidth * 2; - var oneBoxHeight = box_height + boxName_fontSize + boxName_space + 2 * box_borderWidth; - var space_y = (equipList_height - maxLine * oneBoxHeight) / (1 + maxLine), - space_x = (equipList_width - maxItem * oneBoxWidth) / (1 + maxItem); - var box_x = equipList_x + space_x, - box_y = equipList_y + space_y; - for (var i = 0; i < len; i++) { - var id = core.getEquip(i), - name = toDrawList[i]; - var selectBorder = false; - if (core.status.thisUIEventInfo.select.type == i) selectBorder = true; - var borderStyle = selectBorder ? box_selectBorderStyle : box_borderStyle; - core.drawEquipbox_drawOne(ctx, name, id, box_x, box_y, box_width, box_height, boxName_space, boxName_font, boxName_color, borderStyle, box_borderWidth); - var todo = new Function("core.clickOneEquipbox('" + id + "'," + i + ")"); - core.addUIEventListener(box_x - box_borderWidth / 2, box_y - box_borderWidth / 2, oneBoxWidth, oneBoxHeight, todo); - box_x += space_x + oneBoxWidth; - if ((i + 1) % maxItem == 0) { - box_x = equipList_x + space_x; - box_y += space_y + oneBoxHeight; - } - } - } - - this.drawToolbox = function (ctx) { - ctx = ctx || core.canvas.ui; - core.status.thisEventClickArea = []; - - var info = core.drawBoxBackground(ctx); - info.itemNum = itemNum; - core.drawItemListbox(ctx, info.obj); - core.drawToolboxRightbar(ctx, info); - core.setTextBaseline(ctx, "alphabetic"); - core.setTextAlign("left"); - } - - var reduceItem = 4; - this.drawEquipbox = function (ctx) { - ctx = ctx || core.canvas.ui; - core.status.thisEventClickArea = []; - var info = core.drawBoxBackground(ctx); - info.itemNum = itemNum - reduceItem; - info.obj.y += info.obj.oneItemHeight * reduceItem; - info.obj.height -= info.obj.oneItemHeight * reduceItem; - core.drawItemListbox(ctx, info.obj); - core.drawEquipbox_drawOthers(ctx, info); - core.drawToolboxRightbar(ctx, info); - core.setTextBaseline(ctx, "alphabetic"); - core.setTextAlign("left"); - } - - - this.drawEquipbox_drawOne = function (ctx, name, id, x, y, width, height, space, font, color, style, lineWidth) { - if (id) core.drawIcon(ctx, id, x + lineWidth / 2, y + lineWidth / 2, width, height); - core.strokeRect(ctx, x, y, width + lineWidth, height + lineWidth, style, lineWidth); - core.setTextAlign(ctx, "center"); - core.setTextBaseline(ctx, "top"); - var tx = (x + x + lineWidth / 2 + width) / 2, - ty = y + height + lineWidth / 2 * 3 + space; - core.fillText(ctx, name, tx, ty, color, font); - core.setTextBaseline(ctx, "alphabetic"); - core.setTextAlign("left"); - } - - this.drawItemListbox_drawItem = function (ctx, left, right, top, height, marginLeft, marginHeight, style, id) { - var info = core.status.thisUIEventInfo; - var nowClick = info.index; - var item = core.material.items[id] || {}; - var name = item.name || "???"; - var num = core.itemCount(id) || 0; - var fontSize = Math.floor(height - marginHeight * 2); - core.setTextAlign(ctx, "right"); - var numText = "x" + num; - core.fillText(ctx, numText, right - marginLeft, top + height / 2, style, core.ui._buildFont(fontSize)); - if (name != "???") core.drawIcon(ctx, id, left + marginLeft, top + marginHeight, fontSize, fontSize); - var text_x = left + marginLeft + fontSize + 2; - var maxWidth = right - core.calWidth(ctx, numText) - text_x; - core.setTextAlign(ctx, "left"); - core.fillText(ctx, name, text_x, top + height / 2, style, core.ui._buildFont(fontSize), maxWidth); - var todo = new Function("core.clickItemFunc('" + id + "');"); - core.addUIEventListener(left, top, right - left, height, todo); - } - - this.setPageItems = function (page) { - var num = itemNum; - if (core.status.event.id == "equipbox") num -= reduceItem; - var info = core.status.thisUIEventInfo; - if (!info) return; - page = page || info.page; - var items = core.getToolboxItems(core.status.event.id == "toolbox" ? "all" : "equips"); - info.allItems = items; - var maxPage = Math.ceil(items.length / num); - info.maxPage = maxPage; - var pageItems = items.slice((page - 1) * num, page * num); - info.pageItems = pageItems; - info.maxItem = pageItems.length; - if (items.length == 0 && pageItems.length == 0) info.index = null; - if (pageItems.length == 0 && info.page > 1) { - info.page = Math.max(1, info.page - 1); - return core.setPageItems(info.page); - } - return pageItems; - } - - this.drawToolbox_setExitBtn = function (ctx, x, y, r, style, lineWidth) { - core.strokeCircle(ctx, x, y, r, style, lineWidth); - ctx.textAlign = "center"; - ctx.textBaseline = "middle"; - var textSize = Math.sqrt(2) * r; - core.fillText(ctx, "x", x, y, style, core.ui._buildFont(textSize), textSize); - core.setTextAlign(ctx, "start"); - core.setTextBaseline(ctx, "top"); - - var todo = function () { - core.closePanel(); - } - core.addUIEventListener(x - r, y - r, r * 2, r * 2, todo); - } - - this.drawToolbox_setUseBtn = function (ctx, x, y, r, h, style, lineWidth) { - core.setTextAlign(ctx, "left"); - core.setTextBaseline(ctx, "top"); - var fontSize = h - 4; - var font = core.ui._buildFont(fontSize); - var text = core.status.event.id == "toolbox" ? "使用" : "装备"; - if (core.status.thisUIEventInfo.select.action == "unload") text = "卸下"; - var w = core.calWidth(ctx, text, font) + 2 * r + lineWidth / 2; - - core.strokeRoundRect(ctx, x, y, w, h, r, style, lineWidth); - core.fillText(ctx, text, x + r, y + lineWidth / 2 + 2, style, font); - - var todo = function () { - core.useSelectItemInBox(); - } - core.addUIEventListener(x, y, w, h, todo); - } - - this.drawItemListbox_setPageBtn = function (ctx, left, right, bottom, r, style, lineWidth) { - var offset = lineWidth / 2 + r; - - var x = left + offset; - var y = bottom - offset; - var pos = Math.sqrt(2) / 2 * (r - lineWidth / 2); - core.fillPolygon(ctx, [ - [x - pos, y], - [x + pos - 2, y - pos], - [x + pos - 2, y + pos] - ], style); - core.strokeCircle(ctx, x, y, r, style, lineWidth); - var todo = function () { - core.addItemListboxPage(-1); - } - core.addUIEventListener(x - r - 2, y - r - 2, r * 2 + 4, r * 2 + 4, todo); - - x = right - offset; - core.fillPolygon(ctx, [ - [x + pos, y], - [x - pos + 2, y - pos], - [x - pos + 2, y + pos] - ], style); - core.strokeCircle(ctx, x, y, r, style, lineWidth); - var todo = function () { - core.addItemListboxPage(1); - } - core.addUIEventListener(x - r - 2, y - r - 2, r * 2 + 4, r * 2 + 4, todo); - } - - this.clickItemFunc = function (id) { - var info = core.status.thisUIEventInfo; - if (!info) return; - if (info.select.id == id) return core.useSelectItemInBox(); - info.select = {}; - info.select.id = id; - core.setIndexAndSelect('index'); - core.refreshBox(); - } - - this.clickOneEquipbox = function (id, type) { - var info = core.status.thisUIEventInfo; - if (!info) return; - if (info.select.id == id && info.select.type == type) core.useSelectItemInBox(); - else core.status.thisUIEventInfo.select = { - id: id, - type: type, - action: "unload" - } - return core.refreshBox(); - } - - core.ui.getToolboxItems = function (cls) { - var list = Object.keys(core.status.hero.items[cls] || {}); - if (cls == "all") { - for (var name in core.status.hero.items) { - if (name == "equips") continue; - list = list.concat(Object.keys(core.status.hero.items[name])); - } - return list.filter(function (id) { - return !core.material.items[id].hideInToolbox; - }).sort(); - } - - if (this.uidata.getToolboxItems) { - return this.uidata.getToolboxItems(cls); - } - return list.filter(function (id) { - return !core.material.items[id].hideInToolbox; - }).sort(); - } - - this.useSelectItemInBox = function () { - var info = core.status.thisUIEventInfo; - if (!info) return; - if (!info.select.id) return; - var id = info.select.id; - if (core.status.event.id == "toolbox") { - core.events.tryUseItem(id); - // core.closePanel(); - } else if (core.status.event.id == "equipbox") { - var action = info.select.action || "load"; - info.index = 1; - if (action == "load") { - var type = core.getEquipTypeById(id); - core.loadEquip(id, function () { - core.status.route.push("equip:" + id); - info.select.type = type; - core.setIndexAndSelect("select"); - core.drawEquipbox(); - }); - } else { - var type = info.select.type; - core.unloadEquip(type, function () { - core.status.route.push("unEquip:" + type); - info.select.type = type; - //info.select.action = 'load' - core.setIndexAndSelect("select"); - core.drawEquipbox(); - }); - } - } - } - - this.setIndexAndSelect = function (toChange) { - var info = core.status.thisUIEventInfo; - if (!info) return; - core.setPageItems(info.page); - var index = info.index || 1; - var items = info.pageItems; - if (info.select.type != null) { - var type = info.select.type; - id = core.getEquip(type); - info.index = null; - info.select = { - id: id, - action: "unload", - type: type - }; - return; - } else { - info.select.action = null; - info.select.type = null; - if (toChange == "index") info.index = items.indexOf(info.select.id) + 1; - info.select.id = items[info.index - 1]; - } - - } - - this.addItemListboxPage = function (num) { - var info = core.status.thisUIEventInfo; - if (!info) return; - var maxPage = info.maxPage || 1; - info.page = info.page || 1; - info.page += num; - if (info.page <= 0) info.page = maxPage; - if (info.page > maxPage) info.page = 1; - info.index = 1; - core.setPageItems(info.page); - core.setIndexAndSelect("select"); - core.refreshBox(); - } - - this.addItemListboxIndex = function (num) { - var info = core.status.thisUIEventInfo; - if (!info) return; - var maxItem = info.maxItem || 0; - info.index = info.index || 0; - info.index += num; - if (info.index <= 0) info.index = 1; - if (info.index > maxItem) info.index = maxItem; - core.setIndexAndSelect("select"); - core.refreshBox(); - } - - this.addEquipboxType = function (num) { - var info = core.status.thisUIEventInfo; - var type = info.select.type; - if (type == null && num > 0) info.select.type = 0; - else info.select.type = type + num; - var max = core.status.globalAttribute.equipName.length; - if (info.select.type >= max) { - info.select = {}; - core.setIndexAndSelect("select") - return core.addItemListboxPage(0); - } else { - var m = Math.abs(info.select.type); - if (info.select.type < 0) info.select.type = max - m; - core.setIndexAndSelect("select") - core.refreshBox(); - return; - } - } - - core.actions._keyDownToolbox = function (keycode) { - if (!core.status.thisEventClickArea) return; - if (keycode == 37) { // left - core.addItemListboxPage(-1); - return; - } - if (keycode == 38) { // up - core.addItemListboxIndex(-1); - return; - } - if (keycode == 39) { // right - core.addItemListboxPage(1); - return; - } - if (keycode == 40) { // down - core.addItemListboxIndex(1); - return; - } - } - - ////// 工具栏界面时,放开某个键的操作 ////// - core.actions._keyUpToolbox = function (keycode) { - if (keycode == 81) { - core.ui.closePanel(); - if (core.isReplaying()) - core.control._replay_equipbox(); - else - core.openEquipbox(); - return; - } - if (keycode == 84 || keycode == 27 || keycode == 88) { - core.closePanel(); - return; - } - if (keycode == 13 || keycode == 32 || keycode == 67) { - var info = core.status.thisUIEventInfo; - if (info.select) { - core.useSelectItemInBox(); - } - return; - } - } - - core.actions._keyDownEquipbox = function (keycode) { - if (!core.status.thisEventClickArea) return; - if (keycode == 37) { // left - var info = core.status.thisUIEventInfo; - if (info.index != null) return core.addItemListboxPage(-1); - return core.addEquipboxType(-1); - } - if (keycode == 38) { // up - var info = core.status.thisUIEventInfo; - if (info.index == 1) { - info.select.type = core.status.globalAttribute.equipName.length - 1; - core.setIndexAndSelect(); - return core.refreshBox(); - } - if (info.index) return core.addItemListboxIndex(-1); - return core.addEquipboxType(-1 * info.equips); - } - if (keycode == 39) { // right - var info = core.status.thisUIEventInfo; - if (info.index != null) return core.addItemListboxPage(1); - return core.addEquipboxType(1); - } - if (keycode == 40) { // down - var info = core.status.thisUIEventInfo; - if (info.index) return core.addItemListboxIndex(1); - return core.addEquipboxType(info.equips); - } - } - - core.actions._keyUpEquipbox = function (keycode, altKey) { - if (altKey && keycode >= 48 && keycode <= 57) { - core.items.quickSaveEquip(keycode - 48); - return; - } - if (keycode == 84) { - core.ui.closePanel(); - if (core.isReplaying()) - core.control._replay_toolbox(); - else - core.openToolbox(); - return; - } - if (keycode == 81 || keycode == 27 || keycode == 88) { - core.closePanel(); - return; - } - if (keycode == 13 || keycode == 32 || keycode == 67) { - var info = core.status.thisUIEventInfo; - if (info.select) core.useSelectItemInBox(); - return; - } - } - - core.registerAction("ondown", "inEventClickAction", function (x, y, px, py) { - if (!core.status.thisEventClickArea) return false; - var info = core.status.thisEventClickArea; - for (var i = 0; i < info.length; i++) { - var obj = info[i]; - if (px >= obj.x && px <= obj.x + obj.width && py > obj.y && py < obj.y + obj.height) { - if (obj.todo) obj.todo(); - break; - } - } - return true; - }, 51); - core.registerAction("onclick", "stopClick", function () { - if (core.status.thisEventClickArea) return true; - }, 51); - - this.addUIEventListener = function (x, y, width, height, todo) { - if (!core.status.thisEventClickArea) return; - var obj = { - x: x, - y: y, - width: width, - height: height, - todo: todo - } - core.status.thisEventClickArea.push(obj); - } - - this.initThisEventInfo = function () { - core.status.thisUIEventInfo = { - page: 1, - select: {} - }; - core.status.thisEventClickArea = []; - } - - this.refreshBox = function () { - if (!core.status.event.id) return; - if (core.status.event.id == "toolbox") core.drawToolbox(); - else core.drawEquipbox(); - } - - core.ui.closePanel = function () { - if (core.status.hero && core.status.hero.flags) { - // 清除全部临时变量 - Object.keys(core.status.hero.flags).forEach(function (name) { - if (name.startsWith("@temp@") || /^arg\d+$/.test(name)) { - delete core.status.hero.flags[name]; - } - }); - } - this.clearUI(); - core.maps.generateGroundPattern(); - core.updateStatusBar(true); - core.unlockControl(); - core.status.event.data = null; - core.status.event.id = null; - core.status.event.selection = null; - core.status.event.ui = null; - core.status.event.interval = null; - core.status.thisUIEventInfo = null; - core.status.thisEventClickArea = null - } - - this.getItemClsName = function (item) { - if (item == null) return itemClsName; - if (item.cls == "equips") { - if (typeof item.equip.type == "string") return item.equip.type; - var type = core.getEquipTypeById(item.id); - return core.status.globalAttribute.equipName[type]; - } else return itemClsName[item.cls] || item.cls; - } - - core.events.openToolbox = function (fromUserAction) { - if (core.isReplaying()) return; - if (!this._checkStatus('toolbox', fromUserAction)) return; - core.initThisEventInfo(); - let info = core.status.thisUIEventInfo - info.index = 1 - core.setIndexAndSelect('select') - core.drawToolbox(); - } - - core.events.openEquipbox = function (fromUserAction) { - if (core.isReplaying()) return; - if (!this._checkStatus('equipbox', fromUserAction)) return; - core.initThisEventInfo(); - let info = core.status.thisUIEventInfo - info.select.type = 0 - core.setIndexAndSelect('select') - core.drawEquipbox(); - } - - core.control._replay_toolbox = function () { - if (!core.isPlaying() || !core.isReplaying()) return; - if (!core.status.replay.pausing) return core.drawTip("请先暂停录像"); - if (core.isMoving() || core.status.replay.animate || core.status.event.id) - return core.drawTip("请等待当前事件的处理结束"); - - core.lockControl(); - core.status.event.id = 'toolbox'; - core.drawToolbox(); - } - - core.control._replay_equipbox = function () { - if (!core.isPlaying() || !core.isReplaying()) return; - if (!core.status.replay.pausing) return core.drawTip("请先暂停录像"); - if (core.isMoving() || core.status.replay.animate || core.status.event.id) - return core.drawTip("请等待当前事件的处理结束"); - - core.lockControl(); - core.status.event.id = 'equipbox'; - core.drawEquipbox(); - } - - core.control._replayAction_item = function (action) { - if (action.indexOf("item:") != 0) return false; - var itemId = action.substring(5); - if (!core.canUseItem(itemId)) return false; - if (core.material.items[itemId].hideInReplay || core.status.replay.speed == 24) { - core.useItem(itemId, false, core.replay); - return true; - } - core.status.event.id = "toolbox"; - core.initThisEventInfo(); - var info = core.status.thisUIEventInfo; - var items = core.getToolboxItems("all"); - core.setPageItems(1); - var index = items.indexOf(itemId) + 1; - info.page = Math.ceil(index / info.maxItem); - info.index = index % info.maxItem || info.maxItem; - core.setIndexAndSelect("select"); - core.setPageItems(info.page); - core.drawToolbox(); - setTimeout(function () { - core.ui.closePanel(); - core.useItem(itemId, false, core.replay); - }, core.control.__replay_getTimeout()); - return true; - } - - core.control._replayAction_equip = function (action) { - if (action.indexOf("equip:") != 0) return false; - var itemId = action.substring(6); - var items = core.getToolboxItems('equips'); - var index = items.indexOf(itemId) + 1; - if (index < 1) { - core.removeFlag('__doNotCheckAutoEvents__'); - return false; - } - - var cb = function () { - var next = core.status.replay.toReplay[0] || ""; - if (!next.startsWith('equip:') && !next.startsWith('unEquip:')) { - core.removeFlag('__doNotCheckAutoEvents__'); - core.checkAutoEvents(); - } - core.replay(); - } - core.setFlag('__doNotCheckAutoEvents__', true); - - core.status.route.push(action); - if (core.material.items[itemId].hideInReplay || core.status.replay.speed == 24) { - core.loadEquip(itemId, cb); - return true; - } - core.status.event.id = "equipbox"; - core.initThisEventInfo(); - var info = core.status.thisUIEventInfo; - core.setPageItems(1); - info.page = Math.ceil(index / info.maxItem); - info.index = index % info.maxItem || info.maxItem; - core.setIndexAndSelect("select"); - core.setPageItems(info.page); - core.drawEquipbox(); - setTimeout(function () { - core.ui.closePanel(); - core.loadEquip(itemId, cb); - }, core.control.__replay_getTimeout()); - return true; - } - - core.control._replayAction_unEquip = function (action) { - if (action.indexOf("unEquip:") != 0) return false; - var equipType = parseInt(action.substring(8)); - if (!core.isset(equipType)) { - core.removeFlag('__doNotCheckAutoEvents__'); - return false; - } - - var cb = function () { - var next = core.status.replay.toReplay[0] || ""; - if (!next.startsWith('equip:') && !next.startsWith('unEquip:')) { - core.removeFlag('__doNotCheckAutoEvents__'); - core.checkAutoEvents(); - } - core.replay(); - } - core.setFlag('__doNotCheckAutoEvents__', true); - - core.status.route.push(action); - if (core.status.replay.speed == 24) { - core.unloadEquip(equipType, cb); - return true; - } - core.status.event.id = "equipbox"; - core.initThisEventInfo(); - var info = core.status.thisUIEventInfo; - core.setPageItems(1); - info.select.type = equipType; - core.setIndexAndSelect(); - core.drawEquipbox(); - setTimeout(function () { - core.ui.closePanel(); - core.unloadEquip(equipType, cb); - }, core.control.__replay_getTimeout()); - return true; - } - core.registerReplayAction("item", core.control._replayAction_item); - core.registerReplayAction("equip", core.control._replayAction_equip); - core.registerReplayAction("unEquip", core.control._replayAction_unEquip); - }, - "FloatingText": function () { + "FloatingText": function () { // 本插件定义了一些字符绘制相关效果 const { Animation, linear } = core.plugin.animate; const ctx = 'scrollingText'; if (!main.replayChecking) { - new Animation().ticker.add(() => { - core.createCanvas(ctx, 0, 0, core.__PIXELS__, core.__PIXELS__, 136); //每帧重绘该画布 - }); + // new Animation().ticker.add(() => { + // core.createCanvas(ctx, 0, 0, core.__PIXELS__, core.__PIXELS__, 136); //每帧重绘该画布 + // }); } /** @@ -3219,7 +2230,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = ani.all().then(() => { ani.ticker.destroy(); }); } }, - "Menu": function () { + "Menu": function () { // 本插件定义了一些用于绘制的基类 class ButtonBase { constructor(x, y, w, h) { @@ -3337,7 +2348,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = this.MenuBase = { ButtonBase, MenuBase, MenuPage }; }, - "scrollingText": function () { + "scrollingText": function () { // 本插件用于绘制在线留言 /** 塔的英文名 */ @@ -3525,7 +2536,1181 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = } }, - "setting": function () { + "newBackpackLook": function () { + // 注:///// *** 裹起来的区域: 该区域内参数可以随意更改调整ui绘制 不会影响总体布局 + // 请尽量修改该区域而不是其他区域 修改的时候最好可以对照现有ui修改 + + ///// *** 道具类型 + // cls对应name + var itemClsName = { + "constants": "永久道具", + "tools": "消耗道具", + } + // 一页最大放的道具数量 将把整个道具左栏分成num份 每份是一个道具项 + var itemNum = 12; + ///// *** + + // 背景设置 + this.drawBoxBackground = function (ctx) { + core.setTextAlign(ctx, "left"); + core.clearMap(ctx); + core.deleteCanvas("_selector"); + var info = core.status.thisUIEventInfo || {}; + + ///// *** 背景设置 + var max = core.__PIXELS__; + var x = 2, + y = x, + w = max - x * 2, + h = w; + var borderWidth = 2, + borderRadius = 5, // radius:圆角矩形的圆角半径 + borderStyle = "#fff"; + var backgroundColor = "gray"; + // 设置背景不透明度(0.85) + var backgroundAlpha = 0.85; + ///// *** + + var start_x = x + borderWidth / 2, + start_y = y + borderWidth / 2, + width = max - start_x * 2, + height = max - start_y * 2; + + // 渐变色背景的一个例子(黑色渐变白色): + // 有关渐变色的具体知识请网上搜索canvas createGradient了解 + /* + var grd = ctx.createLinearGradient(x, y, x + w, y); + grd.addColorStop(0, "black"); + grd.addColorStop(1, "white"); + backgroundColor = grd; + */ + // 使用图片背景要注释掉下面的strokeRect和fillRoundRect + // 图片背景的一个例子: + /* + core.drawImage(ctx, "xxx.png", x, y, w, h); + core.strokeRect(ctx, x, y, w, h, borderStyle, borderWidth); + */ + core.setAlpha(ctx, backgroundAlpha); + core.strokeRoundRect(ctx, x, y, w, h, borderRadius, borderStyle, borderWidth); + core.fillRoundRect(ctx, start_x, start_y, width, height, borderRadius, backgroundColor); + core.setAlpha(ctx, 1); + + ///// *** 左栏配置 + var leftbar_height = height; + // 左边栏宽度(width*0.6) 本身仅为坐标使用 需要与底下的rightbar_width(width*0.4)同时更改 + var leftbar_width = width * 0.6; + ///// *** + + // xxx_right参数 代表最右侧坐标 + var leftbar_right = start_x + leftbar_width - borderWidth / 2; + var leftbar_bottom = start_y + leftbar_height; + var leftbar_x = start_x; + var leftbar_y = start_y; + + ///// *** 道具栏配置 + var boxName_color = "#fff"; + var boxName_fontSize = 15; + var boxName_font = core.ui._buildFont(boxName_fontSize, true); + var arrow_x = 10 + start_x; + var arrow_y = 10 + start_y; + var arrow_width = 20; + var arrow_style = "white"; + // 暂时只能是1 否则不太行 等待新样板(2.7.3)之后对drawArrow做优化 + var arrow_lineWidth = 2; + // 右箭头 + var rightArrow_right = leftbar_right - 10; + // 道具内栏顶部坐标 本质是通过该项 控制(道具栏顶部文字和箭头)与道具内栏顶部的间隔 + var itembar_top = arrow_y + 15; + ///// *** + + var itembar_right = rightArrow_right; + var boxName = core.status.event.id == "toolbox" ? "\r[yellow]道具栏\r | 装备栏" : "道具栏 | \r[yellow]装备栏\r"; + core.drawArrow(ctx, arrow_x + arrow_width, arrow_y, arrow_x, arrow_y, arrow_style, arrow_lineWidth); + core.drawArrow(ctx, rightArrow_right - arrow_width, arrow_y, rightArrow_right, arrow_y, arrow_style, arrow_lineWidth); + core.setTextAlign(ctx, "center"); + core.setTextBaseline(ctx, "middle"); + var changeBox = function () { + var id = core.status.event.id; + core.closePanel(); + if (id == "toolbox") core.openEquipbox(); + else core.openToolbox(); + } + core.fillText(ctx, boxName, (leftbar_right + leftbar_x) / 2, arrow_y + 2, boxName_color, boxName_font); + + ///// *** 底栏按钮 + var pageBtn_radius = 8; + // xxx_left 最左侧坐标 + var pageBtn_left = leftbar_x + 3; + var pageBtn_right = leftbar_right - 3; + // xxx_bottom 最底部坐标 + var pageBtn_bottom = leftbar_bottom - 2; + var pageBtn_borderStyle = "#fff"; + var pageBtn_borderWidth = 2; + var pageText_color = "#fff"; + // 底部按钮与上面的道具内栏的间隔大小 + var bottomSpace = 8; + ///// *** + + core.drawItemListbox_setPageBtn(ctx, pageBtn_left, pageBtn_right, pageBtn_bottom, pageBtn_radius, pageBtn_borderStyle, pageBtn_borderWidth); + var page = info.page || 1; + var pageFontSize = pageBtn_radius * 2 - 4; + var pageFont = core.ui._buildFont(pageFontSize); + core.setPageItems(page); + var num = itemNum; + if (core.status.event.id == "equipbox") num -= 5; + var maxPage = info.maxPage; + var pageText = page + " / " + maxPage; + core.setTextAlign(ctx, "center"); + core.setTextBaseline(ctx, "bottom"); + core.fillText(ctx, pageText, (leftbar_x + leftbar_right) / 2, pageBtn_bottom, pageText_color, pageFont); + core.addUIEventListener(start_x, start_y, leftbar_right - start_x, arrow_y - start_y + 13, changeBox); + var itembar_height = Math.ceil(pageBtn_bottom - pageBtn_radius * 2 - pageBtn_borderWidth / 2 - bottomSpace - itembar_top); + var oneItemHeight = (itembar_height - 4) / itemNum; + return { + x: start_x, + y: start_y, + width: width, + height: height, + leftbar_right: leftbar_right, + obj: { + x: arrow_x, + y: itembar_top, + width: itembar_right - arrow_x, + height: itembar_height, + oneItemHeight: oneItemHeight + } + } + } + + this.drawItemListbox = function (ctx, obj) { + ctx = ctx || core.canvas.ui; + var itembar_x = obj.x, + itembar_y = obj.y, + itembar_width = obj.width, + itembar_height = obj.height, + itemNum = obj.itemNum, + oneItemHeight = obj.oneItemHeight; + var itembar_right = itembar_x + itembar_width; + var info = core.status.thisUIEventInfo || {}; + var obj = {}; + var page = info.page || 1, + index = info.index, + select = info.select || {}; + + ///// *** 道具栏内栏配置 + var itembar_style = "black"; + var itembar_alpha = 0.7; + // 一个竖屏下减少道具显示的例子: + // if (core.domStyle.isVertical) itemNum = 10; + // 每个道具项的上下空隙占总高度的比例 + var itembar_marginHeightRatio = 0.2; + // 左右间隔空隙 + var item_marginLeft = 2; + var item_x = itembar_x + 2, + item_y = itembar_y + 2, + item_right = itembar_right - 2, + itemName_color = "#fff"; + // 修改此项以更换闪烁光标 + var item_selector = "winskin.png"; + ///// *** + + core.setAlpha(ctx, itembar_alpha); + core.fillRect(ctx, itembar_x, itembar_y, itembar_width, itembar_height, itembar_style); + core.setAlpha(ctx, 1); + var pageItems = core.setPageItems(page); + var marginHeight = itembar_marginHeightRatio * oneItemHeight; + core.setTextBaseline(ctx, "middle"); + var originColor = itemName_color; + for (var i = 0; i < pageItems.length; i++) { + itemName_color = originColor; + var item = pageItems[i]; + // 设置某个的字体颜色的一个例子 + // if (item.id == "xxx") itemName_color = "green"; + core.drawItemListbox_drawItem(ctx, item_x, item_right, item_y, oneItemHeight, item_marginLeft, marginHeight, itemName_color, pageItems[i]); + if (index == i + 1) core.ui._drawWindowSelector(item_selector, item_x + 1, item_y - 1, item_right - item_x - 2, oneItemHeight - 2); + item_y += oneItemHeight; + } + } + + this.drawToolboxRightbar = function (ctx, obj) { + ctx = ctx || core.canvas.ui; + var info = core.status.thisUIEventInfo || {}; + var page = info.page || 1, + index = info.index || 1, + select = info.select || {}; + var start_x = obj.x, + start_y = obj.y, + width = obj.width, + height = obj.height; + var toolboxRight = start_x + width, + toolboxBottom = start_y + height; + + + ///// *** 侧边栏(rightbar)背景设置(物品介绍) + var rightbar_width = width * 0.4; + var rightbar_height = height; + var rightbar_lineWidth = 2; + var rightbar_lineStyle = "#fff"; + ///// *** + + var rightbar_x = toolboxRight - rightbar_width - rightbar_lineWidth / 2; + var rightbar_y = start_y; + core.drawLine(ctx, rightbar_x, rightbar_y, rightbar_x, rightbar_y + rightbar_height, rightbar_lineStyle, rightbar_lineWidth); + + // 获取道具id(有可能为null) + var itemId = select.id; + var item = core.material.items[itemId]; + + ///// *** 侧边栏物品Icon信息 + var iconRect_y = rightbar_y + 10; + // space:间距 + // 这里布局设定iconRect与侧边栏左边框 itemName与工具栏右边框 itemRect与itemName的间距均为space + var space = 15; + var iconRect_x = rightbar_x + space; + var iconRect_radius = 2, + iconRect_width = 32, + iconRect_height = 32, + iconRect_style = "#fff", + iconRect_lineWidth = 2; + ///// *** + + var iconRect_bottom = iconRect_y + iconRect_height, + iconRect_right = iconRect_x + iconRect_width; + + ///// *** 侧边栏各项信息 + var itemTextFontSize = 15, + itemText_x = iconRect_x - 4, + itemText_y = Math.floor(start_y + rightbar_height * 0.25), // 坐标取整防止模糊 + itemClsFontSize = 15, + itemClsFont = core.ui._buildFont(itemClsFontSize), + itemClsColor = "#fff", + itemCls_x = itemText_x - itemClsFontSize / 2, + itemCls_middle = (iconRect_bottom + itemText_y) / 2, //_middle代表文字的中心y坐标 + itemNameFontSize = 18, + itemNameColor = "#fff", + itemNameFont = core.ui._buildFont(itemNameFontSize, true); + var itemName_x = iconRect_right + space; + var itemName_middle = iconRect_y + iconRect_height / 2 + iconRect_lineWidth; + // 修改这里可以编辑未选中道具时的默认值 + var defaultItem = { + cls: "constants", + name: "未知道具", + text: "没有道具最永久" + } + var defaultEquip = { + cls: "equips", + name: "未知装备", + text: "一无所有,又何尝不是一种装备", + equip: { + type: "装备" + } + } + ///// *** + + var originItem = item; + if (core.status.event.id == "equipbox") item = item || defaultEquip; + item = item || defaultItem; + var itemCls = item.cls, + itemName = item.name, + itemText = item.text; + itemText = core.replaceText(itemText); + /* 一个根据道具id修改道具名字(右栏)的例子 + * if (item.id == "xxx") itemNameColor = "red"; + */ + var itemClsName = core.getItemClsName(item); + var itemNameMaxWidth = rightbar_width - iconRect_width - iconRect_lineWidth * 2 - space * 2; + core.strokeRoundRect(ctx, iconRect_x, iconRect_y, iconRect_width, iconRect_height, iconRect_radius, iconRect_style, iconRect_lineWidth); + if (item.id) + core.drawIcon(ctx, item.id, iconRect_x + iconRect_lineWidth / 2, iconRect_y + iconRect_lineWidth / 2, iconRect_width - iconRect_lineWidth, iconRect_height - iconRect_lineWidth); + core.setTextAlign(ctx, "left"); + core.setTextBaseline(ctx, "middle"); + core.fillText(ctx, itemName, itemName_x, itemName_middle, itemNameColor, itemNameFont, itemNameMaxWidth); + core.fillText(ctx, "【" + itemClsName + "】", itemCls_x, itemCls_middle, itemClsColor, itemClsFont); + var statusText = ""; + if (core.status.event.id == "equipbox") { + var type = item.equip.type; + if (typeof type == "string") type = core.getEquipTypeByName(type); + var compare = core.compareEquipment(item.id, core.getEquip(type)); + if (info.select.action == "unload") compare = core.compareEquipment(null, item.id); + // --- 变化值... + for (var name in core.status.hero) { + if (typeof core.status.hero[name] != 'number') continue; + var nowValue = core.getRealStatus(name); + // 查询新值 + var newValue = Math.floor((core.getStatus(name) + (compare.value[name] || 0)) * + (core.getBuff(name) * 100 + (compare.percentage[name] || 0)) / 100); + if (nowValue == newValue) continue; + var color = newValue > nowValue ? '#00FF00' : '#FF0000'; + nowValue = core.formatBigNumber(nowValue); + newValue = core.formatBigNumber(newValue); + statusText += core.getStatusLabel(name) + " " + nowValue + "->\r[" + color + "]" + newValue + "\r\n"; + } + } + itemText = statusText + itemText; + core.drawTextContent(ctx, itemText, { + left: itemText_x, + top: itemText_y, + bold: false, + color: "white", + align: "left", + fontSize: itemTextFontSize, + maxWidth: rightbar_width - (itemText_x - rightbar_x) * 2 + itemTextFontSize / 2 + }); + + ///// *** 退出按钮设置 + var btnRadius = 10; + var btnBorderWidth = 2; + var btnRight = toolboxRight - 2; + var btnBottom = toolboxBottom - 2; + var btnBorderStyle = "#fff"; + ///// *** + + // 获取圆心位置 + var btn_x = btnRight - btnRadius - btnBorderWidth / 2; + btn_y = btnBottom - btnRadius - btnBorderWidth / 2; + core.drawToolbox_setExitBtn(ctx, btn_x, btn_y, btnRadius, btnBorderStyle, btnBorderWidth); + + ///// *** 使用按钮设置 + var useBtnHeight = btnRadius * 2; + // 这里不设置useBtnWidth而是根据各项数据自动得出width + var useBtnRadius = useBtnHeight / 4; + var useBtn_x = rightbar_x + 4, + useBtn_y = btnBottom - useBtnHeight; + var useBtnBorderStyle = "#fff"; + var useBtnBorderWidth = btnBorderWidth; + const batchUseBtn_x = useBtn_x + 50; // 个人觉得,搞这么多参数还不如硬编码 + const hideBtn_y = useBtn_y - useBtnHeight - 8; + ///// *** + + core.drawToolbox_setUseBtn(ctx, useBtn_x, useBtn_y, useBtnRadius, useBtnHeight, useBtnBorderStyle, useBtnBorderWidth); + if (core.status.event.id === 'toolbox') { + drawToolbox_setBatchUseBtn(ctx, batchUseBtn_x, useBtn_y, useBtnRadius, useBtnHeight, useBtnBorderStyle, useBtnBorderWidth); + } + drawToolbox_setHideBtn(ctx, useBtn_x, hideBtn_y, useBtnRadius, useBtnHeight, useBtnBorderStyle, useBtnBorderWidth); + drawToolbox_setShowHideBtn(ctx, rightbar_x, useBtn_y, useBtnHeight, useBtnBorderStyle); + } + + this.drawEquipbox_drawOthers = function (ctx, obj) { + var info = core.status.thisUIEventInfo; + + ///// *** 装备格设置 + var equipList_lineWidth = 2; + var equipList_boxSize = 32; + var equipList_borderWidth = 2; + var equipList_borderStyle = "#fff"; + var equipList_nameColor = "#fff"; + ///// *** + + var equipList_x = obj.x + 4, + equipList_bottom = obj.obj.y - equipList_lineWidth, + equipList_y = equipList_bottom - obj.obj.oneItemHeight * reduceItem - 2, + equipList_height = equipList_bottom - equipList_y; + var equipList_right = obj.leftbar_right, + equipList_width = equipList_right - equipList_x; + core.drawLine(ctx, obj.x, equipList_bottom + equipList_lineWidth / 2, equipList_right, equipList_bottom + equipList_lineWidth / 2, equipList_borderStyle, equipList_lineWidth); + var toDrawList = core.status.globalAttribute.equipName, + len = toDrawList.length; + + ///// *** 装备格设置 + var maxItem = 4; + var box_width = 32, + box_height = 32, + box_borderStyle = "#fff", + box_selectBorderStyle = "gold", // 选中的装备格的颜色 + box_borderWidth = 2; + var boxName_fontSize = 14, + boxName_space = 2, + boxName_color = "#fff"; // 装备格名称与上面的装备格框的距离 + var maxLine = Math.ceil(len / maxItem); + ///// *** + var l = Math.sqrt(len) + if (Math.pow(l) == len && len != 4) { + if (l <= maxItem) maxItem = l; + } + maxItem = Math.min(toDrawList.length, maxItem); + info.equips = maxItem; + + var boxName_font = core.ui._buildFont(boxName_fontSize); + // 总宽高减去所有装备格宽高得到空隙大小 + var oneBoxWidth = box_width + box_borderWidth * 2; + var oneBoxHeight = box_height + boxName_fontSize + boxName_space + 2 * box_borderWidth; + var space_y = (equipList_height - maxLine * oneBoxHeight) / (1 + maxLine), + space_x = (equipList_width - maxItem * oneBoxWidth) / (1 + maxItem); + var box_x = equipList_x + space_x, + box_y = equipList_y + space_y; + for (var i = 0; i < len; i++) { + var id = core.getEquip(i), + name = toDrawList[i]; + var selectBorder = false; + if (core.status.thisUIEventInfo.select.type == i) selectBorder = true; + var borderStyle = selectBorder ? box_selectBorderStyle : box_borderStyle; + core.drawEquipbox_drawOne(ctx, name, id, box_x, box_y, box_width, box_height, boxName_space, boxName_font, boxName_color, borderStyle, box_borderWidth); + var todo = new Function("core.clickOneEquipbox('" + id + "'," + i + ")"); + core.addUIEventListener(box_x - box_borderWidth / 2, box_y - box_borderWidth / 2, oneBoxWidth, oneBoxHeight, todo); + box_x += space_x + oneBoxWidth; + if ((i + 1) % maxItem == 0) { + box_x = equipList_x + space_x; + box_y += space_y + oneBoxHeight; + } + } + } + + this.drawToolbox = function (ctx) { + ctx = ctx || core.canvas.ui; + core.status.thisEventClickArea = []; + + var info = core.drawBoxBackground(ctx); + info.itemNum = itemNum; + core.drawItemListbox(ctx, info.obj); + core.drawToolboxRightbar(ctx, info); + core.setTextBaseline(ctx, "alphabetic"); + core.setTextAlign("left"); + } + + var reduceItem = 4; + this.drawEquipbox = function (ctx) { + ctx = ctx || core.canvas.ui; + core.status.thisEventClickArea = []; + var info = core.drawBoxBackground(ctx); + info.itemNum = itemNum - reduceItem; + info.obj.y += info.obj.oneItemHeight * reduceItem; + info.obj.height -= info.obj.oneItemHeight * reduceItem; + core.drawItemListbox(ctx, info.obj); + core.drawEquipbox_drawOthers(ctx, info); + core.drawToolboxRightbar(ctx, info); + core.setTextBaseline(ctx, "alphabetic"); + core.setTextAlign("left"); + } + + + this.drawEquipbox_drawOne = function (ctx, name, id, x, y, width, height, space, font, color, style, lineWidth) { + if (id) core.drawIcon(ctx, id, x + lineWidth / 2, y + lineWidth / 2, width, height); + core.strokeRect(ctx, x, y, width + lineWidth, height + lineWidth, style, lineWidth); + core.setTextAlign(ctx, "center"); + core.setTextBaseline(ctx, "top"); + var tx = (x + x + lineWidth / 2 + width) / 2, + ty = y + height + lineWidth / 2 * 3 + space; + core.fillText(ctx, name, tx, ty, color, font); + core.setTextBaseline(ctx, "alphabetic"); + core.setTextAlign("left"); + } + + this.drawItemListbox_drawItem = function (ctx, left, right, top, height, marginLeft, marginHeight, style, id) { + var info = core.status.thisUIEventInfo; + var nowClick = info.index; + var item = core.material.items[id] || {}; + var name = item.name || "???"; + var num = core.itemCount(id) || 0; + var fontSize = Math.floor(height - marginHeight * 2); + core.setTextAlign(ctx, "right"); + var numText = "x" + num; + core.fillText(ctx, numText, right - marginLeft, top + height / 2, style, core.ui._buildFont(fontSize)); + + const hideInfo = core.getFlag('hideInfo', {}); + if (item && (hideInfo.hasOwnProperty(id) ? hideInfo[id] : item.hideInToolbox)) core.setAlpha(ctx, 0.5); + + if (name != "???") core.drawIcon(ctx, id, left + marginLeft, top + marginHeight, fontSize, fontSize); + var text_x = left + marginLeft + fontSize + 2; + var maxWidth = right - core.calWidth(ctx, numText) - text_x; + core.setTextAlign(ctx, "left"); + core.fillText(ctx, name, text_x, top + height / 2, style, core.ui._buildFont(fontSize), maxWidth); + core.setAlpha(ctx, 1); + + var todo = new Function("core.clickItemFunc('" + id + "');"); + core.addUIEventListener(left, top, right - left, height, todo); + } + + this.setPageItems = function (page) { + var num = itemNum; + if (core.status.event.id == "equipbox") num -= reduceItem; + var info = core.status.thisUIEventInfo; + if (!info) return; + page = page || info.page; + var items = core.getToolboxItems(core.status.event.id == "toolbox" ? "all" : "equips", core.getFlag('showHideItem', false)); + info.allItems = items; + var maxPage = Math.ceil(items.length / num); + info.maxPage = maxPage; + var pageItems = items.slice((page - 1) * num, page * num); + info.pageItems = pageItems; + info.maxItem = pageItems.length; + if (items.length == 0 && pageItems.length == 0) info.index = null; + if (pageItems.length == 0 && info.page > 1) { + info.page = Math.max(1, info.page - 1); + return core.setPageItems(info.page); + } + return pageItems; + } + + this.drawToolbox_setExitBtn = function (ctx, x, y, r, style, lineWidth) { + core.strokeCircle(ctx, x, y, r, style, lineWidth); + ctx.textAlign = "center"; + ctx.textBaseline = "middle"; + var textSize = Math.sqrt(2) * r; + core.fillText(ctx, "x", x, y, style, core.ui._buildFont(textSize), textSize); + core.setTextAlign(ctx, "start"); + core.setTextBaseline(ctx, "top"); + + var todo = function () { + core.closePanel(); + } + core.addUIEventListener(x - r, y - r, r * 2, r * 2, todo); + } + + this.drawToolbox_setUseBtn = function (ctx, x, y, r, h, style, lineWidth) { + core.setTextAlign(ctx, "left"); + core.setTextBaseline(ctx, "top"); + var fontSize = h - 4; + var font = core.ui._buildFont(fontSize); + var text = core.status.event.id == "toolbox" ? "使用" : "装备"; + if (core.status.thisUIEventInfo.select.action == "unload") text = "卸下"; + var w = core.calWidth(ctx, text, font) + 2 * r + lineWidth / 2; + + core.strokeRoundRect(ctx, x, y, w, h, r, style, lineWidth); + core.fillText(ctx, text, x + r, y + lineWidth / 2 + 2, style, font); + + var todo = function () { + core.useSelectItemInBox(); + } + core.addUIEventListener(x, y, w, h, todo); + } + + function getSelectedItem() { + var info = core.status.thisUIEventInfo; + if (!(info && info.select.id && core.status.event.id == "toolbox")) { + core.drawFailTip('发生了未知错误!'); + return; + } + return info.select.id; + } + + function batchUse(item,count){ + try { + const itemCount = core.itemCount(id); + if (eval(core.material.items[item].noBatchUse)) { + core.drawFailTip('该道具不能被批量使用!'); + return; + } + if (count > itemCount) count = itemCount; + core.closePanel(); + for (let i = 0; i < count; i++) { + if (core.canUseItem(item)) core.useItem(item); + else return; + } + } + catch (e) { + console.log(e); + core.drawFailTip('批量使用时出现未知错误!'); + } + } + + function drawToolbox_setBatchUseBtn(ctx, x, y, r, h, style, lineWidth) { + core.setTextAlign(ctx, "left"); + core.setTextBaseline(ctx, "top"); + var fontSize = h - 4; + var font = core.ui._buildFont(fontSize); + var text = "批量使用"; + var w = core.calWidth(ctx, text, font) + 2 * r + lineWidth / 2; + + core.strokeRoundRect(ctx, x, y, w, h, r, style, lineWidth); + core.fillText(ctx, text, x + r, y + lineWidth / 2 + 2, style, font); + + var todo = function () { + core.utils.myprompt('输入要使用该物品的次数(0~99)。 请勿对不适合重复使用的物品这么做。', null, (value) => { + + value = parseInt(value); + var id = getSelectedItem(); + + if (Number.isNaN(value) || value < 0 || value > 99) { + core.drawFailTip('输入不合法!'); + return; + } + if (!core.canUseItem(id)) { + core.drawFailTip('当前无法使用该道具!'); + return; + } + core.closePanel(); + batchUse(id, value); + }); + } + core.addUIEventListener(x, y, w, h, todo); + } + + function drawToolbox_setHideBtn(ctx, x, y, r, h, style, lineWidth) { + core.setTextAlign(ctx, "left"); + core.setTextBaseline(ctx, "top"); + var fontSize = h - 4; + var font = core.ui._buildFont(fontSize); + var text = "显示/隐藏"; + var w = core.calWidth(ctx, text, font) + 2 * r + lineWidth / 2; + + core.strokeRoundRect(ctx, x, y, w, h, r, style, lineWidth); + core.fillText(ctx, text, x + r, y + lineWidth / 2 + 2, style, font); + + var todo = function () { + var id = getSelectedItem(); + let hideInfo = core.getFlag('hideInfo', {}); + console.log(id); + if (hideInfo.hasOwnProperty(id)) { + hideInfo[id] = !hideInfo[id]; + core.setFlag('hideInfo', hideInfo); + } + else { + hideInfo[id] = !core.material.items[id].hideInToolbox; + core.setFlag('hideInfo', hideInfo); + } + core.plugin.drawToolbox(); + } + core.addUIEventListener(x, y, w, h, todo); + } + + ui.prototype.getToolboxItems = function (cls, showHide) { + let list = Object.keys(core.status.hero.items[cls] || {});; + if (cls === 'all') { + for (let name in core.status.hero.items) { + if (name == "equips") continue; + list = list.concat(Object.keys(core.status.hero.items[name])); // 获取'constants'和'tools'整体的列表 + } + if (!showHide) list = list.filter(function (id) { + const hideInfo = core.getFlag('hideInfo',{}); + //if (id === 'yellowKey') debugger; + if (hideInfo.hasOwnProperty(id)) return !hideInfo[id]; + else return !core.material.items[id].hideInToolbox; + }) + list = list.sort(); + return list; + } + + if (this.uidata.getToolboxItems) { + return this.uidata.getToolboxItems(cls, showHide); + } + if (!showHide) list = list.filter(function (id) { + return !core.material.items[id].hideInToolbox; + }) + list = list.sort(); + return list; + } + + function drawToolbox_setShowHideBtn(ctx, x, y, h, style) { + core.setTextAlign(ctx, "left"); + core.setTextBaseline(ctx, "top"); + var fontSize = h - 6; + var font = core.ui._buildFont(fontSize); + var text = "显示隐藏"; + var w = core.calWidth(ctx, text, font) + h += 4; + const squareSize = h - 6; + + x -= w + squareSize + 26; + + const border = 2; + core.fillRect(ctx, x, y, squareSize, squareSize, ' #F5F5F5'); + if (core.hasFlag('showHideItem')) { + core.fillRect(ctx, x + border, y + border, squareSize - 2 * border, squareSize - 2 * border, 'lime'); + } + // core.strokeRect(ctx, x, y, w, h, style); + core.fillText(ctx, text, x + squareSize + 2, y + 4, style, font); + + var todo = function () { + core.setFlag('showHideItem', !core.getFlag('showHideItem', false)); + core.plugin.drawToolbox(); + //core.useSelectItemInBox(); + } + core.addUIEventListener(x, y, w, h, todo); + } + + this.drawItemListbox_setPageBtn = function (ctx, left, right, bottom, r, style, lineWidth) { + var offset = lineWidth / 2 + r; + + var x = left + offset; + var y = bottom - offset; + var pos = Math.sqrt(2) / 2 * (r - lineWidth / 2); + core.fillPolygon(ctx, [ + [x - pos, y], + [x + pos - 2, y - pos], + [x + pos - 2, y + pos] + ], style); + core.strokeCircle(ctx, x, y, r, style, lineWidth); + var todo = function () { + core.addItemListboxPage(-1); + } + core.addUIEventListener(x - r - 2, y - r - 2, r * 2 + 4, r * 2 + 4, todo); + + x = right - offset; + core.fillPolygon(ctx, [ + [x + pos, y], + [x - pos + 2, y - pos], + [x - pos + 2, y + pos] + ], style); + core.strokeCircle(ctx, x, y, r, style, lineWidth); + var todo = function () { + core.addItemListboxPage(1); + } + core.addUIEventListener(x - r - 2, y - r - 2, r * 2 + 4, r * 2 + 4, todo); + } + + this.clickItemFunc = function (id) { + var info = core.status.thisUIEventInfo; + if (!info) return; + if (info.select.id == id) return core.useSelectItemInBox(); + info.select = {}; + info.select.id = id; + core.setIndexAndSelect('index'); + core.refreshBox(); + } + + this.clickOneEquipbox = function (id, type) { + var info = core.status.thisUIEventInfo; + if (!info) return; + if (info.select.id == id && info.select.type == type) core.useSelectItemInBox(); + else core.status.thisUIEventInfo.select = { + id: id, + type: type, + action: "unload" + } + return core.refreshBox(); + } + + // core.ui.getToolboxItems = function (cls) { + // var list = Object.keys(core.status.hero.items[cls] || {}); + // if (cls == "all") { + // for (var name in core.status.hero.items) { + // if (name == "equips") continue; + // list = list.concat(Object.keys(core.status.hero.items[name])); + // } + // return list.filter(function (id) { + // return !core.material.items[id].hideInToolbox; + // }).sort(); + // } + + // if (this.uidata.getToolboxItems) { + // return this.uidata.getToolboxItems(cls); + // } + // return list.filter(function (id) { + // return !core.material.items[id].hideInToolbox; + // }).sort(); + // } + + this.useSelectItemInBox = function () { + var info = core.status.thisUIEventInfo; + if (!info) return; + if (!info.select.id) return; + var id = info.select.id; + if (core.status.event.id == "toolbox") { + core.events.tryUseItem(id); + // core.closePanel(); + } else if (core.status.event.id == "equipbox") { + var action = info.select.action || "load"; + info.index = 1; + if (action == "load") { + var type = core.getEquipTypeById(id); + core.loadEquip(id, function () { + core.status.route.push("equip:" + id); + info.select.type = type; + core.setIndexAndSelect("select"); + core.drawEquipbox(); + }); + } else { + var type = info.select.type; + core.unloadEquip(type, function () { + core.status.route.push("unEquip:" + type); + info.select.type = type; + //info.select.action = 'load' + core.setIndexAndSelect("select"); + core.drawEquipbox(); + }); + } + } + } + + this.setIndexAndSelect = function (toChange) { + var info = core.status.thisUIEventInfo; + if (!info) return; + core.setPageItems(info.page); + var index = info.index || 1; + var items = info.pageItems; + if (info.select.type != null) { + var type = info.select.type; + id = core.getEquip(type); + info.index = null; + info.select = { + id: id, + action: "unload", + type: type + }; + return; + } else { + info.select.action = null; + info.select.type = null; + if (toChange == "index") info.index = items.indexOf(info.select.id) + 1; + info.select.id = items[info.index - 1]; + } + + } + + this.addItemListboxPage = function (num) { + var info = core.status.thisUIEventInfo; + if (!info) return; + var maxPage = info.maxPage || 1; + info.page = info.page || 1; + info.page += num; + if (info.page <= 0) info.page = maxPage; + if (info.page > maxPage) info.page = 1; + info.index = 1; + core.setPageItems(info.page); + core.setIndexAndSelect("select"); + core.refreshBox(); + } + + this.addItemListboxIndex = function (num) { + var info = core.status.thisUIEventInfo; + if (!info) return; + var maxItem = info.maxItem || 0; + info.index = info.index || 0; + info.index += num; + if (info.index <= 0) info.index = 1; + if (info.index > maxItem) info.index = maxItem; + core.setIndexAndSelect("select"); + core.refreshBox(); + } + + this.addEquipboxType = function (num) { + var info = core.status.thisUIEventInfo; + var type = info.select.type; + if (type == null && num > 0) info.select.type = 0; + else info.select.type = type + num; + var max = core.status.globalAttribute.equipName.length; + if (info.select.type >= max) { + info.select = {}; + core.setIndexAndSelect("select") + return core.addItemListboxPage(0); + } else { + var m = Math.abs(info.select.type); + if (info.select.type < 0) info.select.type = max - m; + core.setIndexAndSelect("select") + core.refreshBox(); + return; + } + } + + core.actions._keyDownToolbox = function (keycode) { + if (!core.status.thisEventClickArea) return; + if (keycode == 37) { // left + core.addItemListboxPage(-1); + return; + } + if (keycode == 38) { // up + core.addItemListboxIndex(-1); + return; + } + if (keycode == 39) { // right + core.addItemListboxPage(1); + return; + } + if (keycode == 40) { // down + core.addItemListboxIndex(1); + return; + } + } + + ////// 工具栏界面时,放开某个键的操作 ////// + core.actions._keyUpToolbox = function (keycode) { + if (keycode == 81) { + core.ui.closePanel(); + if (core.isReplaying()) + core.control._replay_equipbox(); + else + core.openEquipbox(); + return; + } + if (keycode == 84 || keycode == 27 || keycode == 88) { + core.closePanel(); + return; + } + if (keycode == 13 || keycode == 32 || keycode == 67) { + var info = core.status.thisUIEventInfo; + if (info.select) { + core.useSelectItemInBox(); + } + return; + } + } + + core.actions._keyDownEquipbox = function (keycode) { + if (!core.status.thisEventClickArea) return; + if (keycode == 37) { // left + var info = core.status.thisUIEventInfo; + if (info.index != null) return core.addItemListboxPage(-1); + return core.addEquipboxType(-1); + } + if (keycode == 38) { // up + var info = core.status.thisUIEventInfo; + if (info.index == 1) { + info.select.type = core.status.globalAttribute.equipName.length - 1; + core.setIndexAndSelect(); + return core.refreshBox(); + } + if (info.index) return core.addItemListboxIndex(-1); + return core.addEquipboxType(-1 * info.equips); + } + if (keycode == 39) { // right + var info = core.status.thisUIEventInfo; + if (info.index != null) return core.addItemListboxPage(1); + return core.addEquipboxType(1); + } + if (keycode == 40) { // down + var info = core.status.thisUIEventInfo; + if (info.index) return core.addItemListboxIndex(1); + return core.addEquipboxType(info.equips); + } + } + + core.actions._keyUpEquipbox = function (keycode, altKey) { + if (altKey && keycode >= 48 && keycode <= 57) { + core.items.quickSaveEquip(keycode - 48); + return; + } + if (keycode == 84) { + core.ui.closePanel(); + if (core.isReplaying()) + core.control._replay_toolbox(); + else + core.openToolbox(); + return; + } + if (keycode == 81 || keycode == 27 || keycode == 88) { + core.closePanel(); + return; + } + if (keycode == 13 || keycode == 32 || keycode == 67) { + var info = core.status.thisUIEventInfo; + if (info.select) core.useSelectItemInBox(); + return; + } + } + + core.registerAction("ondown", "inEventClickAction", function (x, y, px, py) { + if (!core.status.thisEventClickArea) return false; + var info = core.status.thisEventClickArea; + for (var i = 0; i < info.length; i++) { + var obj = info[i]; + if (px >= obj.x && px <= obj.x + obj.width && py > obj.y && py < obj.y + obj.height) { + if (obj.todo) obj.todo(); + break; + } + } + return true; + }, 51); + core.registerAction("onclick", "stopClick", function () { + if (core.status.thisEventClickArea) return true; + }, 51); + + this.addUIEventListener = function (x, y, width, height, todo) { + if (!core.status.thisEventClickArea) return; + var obj = { + x: x, + y: y, + width: width, + height: height, + todo: todo + } + core.status.thisEventClickArea.push(obj); + } + + this.initThisEventInfo = function () { + core.status.thisUIEventInfo = { + page: 1, + select: {} + }; + core.status.thisEventClickArea = []; + } + + this.refreshBox = function () { + if (!core.status.event.id) return; + if (core.status.event.id == "toolbox") core.drawToolbox(); + else core.drawEquipbox(); + } + + core.ui.closePanel = function () { + if (core.status.hero && core.status.hero.flags) { + // 清除全部临时变量 + Object.keys(core.status.hero.flags).forEach(function (name) { + if (name.startsWith("@temp@") || /^arg\d+$/.test(name)) { + delete core.status.hero.flags[name]; + } + }); + } + this.clearUI(); + core.maps.generateGroundPattern(); + core.updateStatusBar(true); + core.unlockControl(); + core.status.event.data = null; + core.status.event.id = null; + core.status.event.selection = null; + core.status.event.ui = null; + core.status.event.interval = null; + core.status.thisUIEventInfo = null; + core.status.thisEventClickArea = null + } + + this.getItemClsName = function (item) { + if (item == null) return itemClsName; + if (item.cls == "equips") { + if (typeof item.equip.type == "string") return item.equip.type; + var type = core.getEquipTypeById(item.id); + return core.status.globalAttribute.equipName[type]; + } else return itemClsName[item.cls] || item.cls; + } + + core.events.openToolbox = function (fromUserAction) { + if (core.isReplaying()) return; + if (!this._checkStatus('toolbox', fromUserAction)) return; + core.initThisEventInfo(); + let info = core.status.thisUIEventInfo + info.index = 1 + core.setIndexAndSelect('select') + core.drawToolbox(); + } + + core.events.openEquipbox = function (fromUserAction) { + if (core.isReplaying()) return; + if (!this._checkStatus('equipbox', fromUserAction)) return; + core.initThisEventInfo(); + let info = core.status.thisUIEventInfo + info.select.type = 0 + core.setIndexAndSelect('select') + core.drawEquipbox(); + } + + core.control._replay_toolbox = function () { + if (!core.isPlaying() || !core.isReplaying()) return; + if (!core.status.replay.pausing) return core.drawTip("请先暂停录像"); + if (core.isMoving() || core.status.replay.animate || core.status.event.id) + return core.drawTip("请等待当前事件的处理结束"); + + core.lockControl(); + core.status.event.id = 'toolbox'; + core.drawToolbox(); + } + + core.control._replay_equipbox = function () { + if (!core.isPlaying() || !core.isReplaying()) return; + if (!core.status.replay.pausing) return core.drawTip("请先暂停录像"); + if (core.isMoving() || core.status.replay.animate || core.status.event.id) + return core.drawTip("请等待当前事件的处理结束"); + + core.lockControl(); + core.status.event.id = 'equipbox'; + core.drawEquipbox(); + } + + core.control._replayAction_item = function (action) { + if (action.indexOf("item:") != 0) return false; + var itemId = action.substring(5); + if (!core.canUseItem(itemId)) return false; + if (core.material.items[itemId].hideInReplay || core.status.replay.speed == 24) { + core.useItem(itemId, false, core.replay); + return true; + } + core.status.event.id = "toolbox"; + core.initThisEventInfo(); + var info = core.status.thisUIEventInfo; + var items = core.getToolboxItems("all", core.getFlag('showHideItem', false)); + core.setPageItems(1); + var index = items.indexOf(itemId) + 1; + info.page = Math.ceil(index / info.maxItem); + info.index = index % info.maxItem || info.maxItem; + core.setIndexAndSelect("select"); + core.setPageItems(info.page); + core.drawToolbox(); + setTimeout(function () { + core.ui.closePanel(); + core.useItem(itemId, false, core.replay); + }, core.control.__replay_getTimeout()); + return true; + } + + core.control._replayAction_equip = function (action) { + if (action.indexOf("equip:") != 0) return false; + var itemId = action.substring(6); + var items = core.getToolboxItems('equips'); + var index = items.indexOf(itemId) + 1; + if (index < 1) { + core.removeFlag('__doNotCheckAutoEvents__'); + return false; + } + + var cb = function () { + var next = core.status.replay.toReplay[0] || ""; + if (!next.startsWith('equip:') && !next.startsWith('unEquip:')) { + core.removeFlag('__doNotCheckAutoEvents__'); + core.checkAutoEvents(); + } + core.replay(); + } + core.setFlag('__doNotCheckAutoEvents__', true); + + core.status.route.push(action); + if (core.material.items[itemId].hideInReplay || core.status.replay.speed == 24) { + core.loadEquip(itemId, cb); + return true; + } + core.status.event.id = "equipbox"; + core.initThisEventInfo(); + var info = core.status.thisUIEventInfo; + core.setPageItems(1); + info.page = Math.ceil(index / info.maxItem); + info.index = index % info.maxItem || info.maxItem; + core.setIndexAndSelect("select"); + core.setPageItems(info.page); + core.drawEquipbox(); + setTimeout(function () { + core.ui.closePanel(); + core.loadEquip(itemId, cb); + }, core.control.__replay_getTimeout()); + return true; + } + + core.control._replayAction_unEquip = function (action) { + if (action.indexOf("unEquip:") != 0) return false; + var equipType = parseInt(action.substring(8)); + if (!core.isset(equipType)) { + core.removeFlag('__doNotCheckAutoEvents__'); + return false; + } + + var cb = function () { + var next = core.status.replay.toReplay[0] || ""; + if (!next.startsWith('equip:') && !next.startsWith('unEquip:')) { + core.removeFlag('__doNotCheckAutoEvents__'); + core.checkAutoEvents(); + } + core.replay(); + } + core.setFlag('__doNotCheckAutoEvents__', true); + + core.status.route.push(action); + if (core.status.replay.speed == 24) { + core.unloadEquip(equipType, cb); + return true; + } + core.status.event.id = "equipbox"; + core.initThisEventInfo(); + var info = core.status.thisUIEventInfo; + core.setPageItems(1); + info.select.type = equipType; + core.setIndexAndSelect(); + core.drawEquipbox(); + setTimeout(function () { + core.ui.closePanel(); + core.unloadEquip(equipType, cb); + }, core.control.__replay_getTimeout()); + return true; + } + core.registerReplayAction("item", core.control._replayAction_item); + core.registerReplayAction("equip", core.control._replayAction_equip); + core.registerReplayAction("unEquip", core.control._replayAction_unEquip); +}, + "setting": function () { // 自绘设置界面 // 请保持本插件在所有插件的最下方 @@ -4535,12 +4720,352 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = // todolist 道具栏分页,可设定隐藏的道具,及自动查看显隐藏 手动hide无用道具 // todolist 内置ATRI 解决连通性问题 // todolist 血瓶宝石显示数据 解决浏览地图和楼传显示错误 引入自动配置值的块 √ - // todolist 存读档过程保存图块连通性(可选) - // todolist 清怪检测,重开杖,吸噬 × 有人需要?? + // todolist 存读档过程保存图块连通性(可选)√ + // todolist 清怪检测,重开杖,吸噬 × 有人需要??不需要 // todolist 修复已知的插件bug // todolist 添加鸽窝样板的快速读取撤回 和 优化美工 // todolist 音效连续播放的优化(与自动清有关) // todolist 新的临界计算 // todolist 微调BGM播放 + }, + "temp1": function () { + return; + // 注:///// *** 裹起来的区域: 该区域内参数可以随意更改调整ui绘制 不会影响总体布局 + // 请尽量修改该区域而不是其他区域 修改的时候最好可以对照现有ui修改 + + ///// *** 道具类型 + // cls对应name + const itemClsName = { + "constants": "永久道具", + "tools": "消耗道具", } + // 一页最大放的道具数量 将把整个道具左栏分成num份 每份是一个道具项 + const itemNum = 12; + ///// *** + + class ButtonBase { + constructor(x, y, w, h) { + this.x = x; + this.y = y; + this.w = w; + this.h = h; + this.disable = false; + + /** 所在的Menu,用于触发重绘等事件 */ + this.menu; + + this.draw = (ctx) => {}; + this.event = (x, y, px, py) => {}; + this.status; + } + } + + class MenuBase { + constructor(name) { + /** name */ + this.name = name; + /** btnList */ + this.btnList = new Map(); + /** keyEvent */ + this.keyEvent = () => {}; + /** clickEvent */ + this.clickEvent = (x, y, px, py) => { + this.btnList.forEach((btn) => { + if (btn.disable) return; + if (px >= btn.x && px <= btn.x + btn.w && py > btn.y && py <= btn.y + btn.h) { + btn.event(x, y, px, py); + } + }); + } + } + + initBtnList(arr) { + this.btnList = new Map(arr); + this.btnList.forEach((button) => { + button.menu = this; + }) + } + + drawButtonContent() { + this.btnList.forEach((button) => { + if (!button.disable) button.draw(this.name); + }) + } + + drawContent() { + core.createCanvas(this.name, 0, 0, core.__PIXELS__, core.__PIXELS__, 136); + this.drawButtonContent(this.name); + } + + beginListen() { + core.registerAction('keyDown', this.name, this.keyEvent, 100); + core.registerAction('ondown', this.name, this.clickEvent, 100); + + } + + endListen() { + core.unregisterAction('keyDown', this.name); + core.unregisterAction('ondown', this.name); + } + + clear() { + this.endListen(); + core.deleteCanvas(this.name); + } + + init() { + this.beginListen(); + this.drawContent(); + } + } + class MenuPage extends MenuBase { + constructor(pageList, currPage, ctx) { + super(ctx); + /** + * 当前页面列表 + * @type {Array} + */ + this.pageList = pageList; + /** + * 当前页的序号 + * @type {number} + */ + this.currPage = currPage | 0; + } + + initOnePage(index) { + if (!core.isset(index)) index = this.currPage; + this.pageList[index].init(); + } + + changePage(num) { + if (num !== this.currPage) { + const beforeMenu = this.pageList[this.currPage]; + beforeMenu.clear(); + } + this.currPage = num; + this.initOnePage(); + } + + pageDown() { + if (this.currPage > 0) this.changePage(this.currPage - 1); + } + + pageUp() { + if (this.currPage < this.pageList.length - 1) this.changePage(this.currPage + 1); + } + + clear() { + this.pageList.forEach((page) => page.clear()); + super.clear(); + } + } + + // 绘制道具栏的共用背景 + function drawBoxBackground(ctx) { + core.setTextAlign(ctx, "left"); + core.clearMap(ctx); + core.deleteCanvas("_selector"); ///!!!// ?这是什么? + + ///// *** 背景设置 + const max = core.__PIXELS__; + const x = 2, + y = x, + w = max - x * 2, + h = w; + const [borderWidth, borderRadius, borderStyle] = [2, 5, "#fff"]; // radius:圆角矩形的圆角半径 + const [backgroundColor, backgroundAlpha] = ["gray", 0.85]; // 设置背景不透明度(0.85) + ///// *** + const [start_x, start_y] = [x + borderWidth / 2, y + borderWidth / 2]; + const [width, height] = [max - start_x * 2, max - start_y * 2]; + + // 渐变色背景的一个例子(黑色渐变白色): + // 有关渐变色的具体知识请网上搜索canvas createGradient了解 + /* + var grd = ctx.createLinearGradient(x, y, x + w, y); + grd.addColorStop(0, "black"); + grd.addColorStop(1, "white"); + backgroundColor = grd; + */ + // 使用图片背景要注释掉下面的strokeRect和fillRoundRect + // 图片背景的一个例子: + /* + core.drawImage(ctx, "xxx.png", x, y, w, h); + core.strokeRect(ctx, x, y, w, h, borderStyle, borderWidth); + */ + + core.setAlpha(ctx, backgroundAlpha); // 不透明度暂时设为backgroundAlpha + core.strokeRoundRect(ctx, x, y, w, h, borderRadius, borderStyle, borderWidth); // 绘制大边框 + core.fillRoundRect(ctx, start_x, start_y, width, height, borderRadius, backgroundColor); // 绘制大边框中的灰色背景 + core.setAlpha(ctx, 1); // 恢复不透明度 + + ///// *** 左栏配置 + const [leftbar_height, leftbar_width] = [height, width * 0.6]; + // 左边栏宽度(width*0.6) 本身仅为坐标使用 需要与底下的rightbar_width(width*0.4)同时更改 + ///// *** + // xxx_right参数 代表最右侧坐标 + // + const [leftbar_right, leftbar_bottom, leftbar_x, leftbar_y] = [start_x + leftbar_width - borderWidth / 2, start_y + leftbar_height, start_x, start_y]; + + ///// *** 道具栏配置 + + const [boxName_color, boxName_fontSize] = ['#fff', 15]; + const boxName_font = core.ui._buildFont(boxName_fontSize, true); + + const [arrow_x, arrow_y, arrow_width, arrow_style] = [10 + start_x, 10 + start_y, 20, "white"]; + const arrow_lineWidth = 2; + const rightArrow_right = leftbar_right - 10; + // 道具内栏顶部坐标 本质是通过该项 控制(道具栏顶部文字和箭头)与道具内栏顶部的间隔 + ///// *** + + const boxName = core.status.event.id == "toolbox" ? "\r[yellow]道具栏\r | 装备栏" : "道具栏 | \r[yellow]装备栏\r"; ///!!!// + + // 绘制左右两个箭头 + core.drawArrow(ctx, arrow_x + arrow_width, arrow_y, arrow_x, arrow_y, arrow_style, arrow_lineWidth); + core.drawArrow(ctx, rightArrow_right - arrow_width, arrow_y, rightArrow_right, arrow_y, arrow_style, arrow_lineWidth); + + core.setTextAlign(ctx, "center"); + core.setTextBaseline(ctx, "middle"); + core.fillText(ctx, boxName, (leftbar_right + leftbar_x) / 2, arrow_y + 2, boxName_color, boxName_font); // 绘制道具栏?装备栏的字样 ///!!!// + + ///// *** 底栏按钮 + const [pageBtn_left, pageBtn_right, pageBtn_bottom] = [leftbar_x + 3, leftbar_right - 3, leftbar_bottom - 2]; + // xxx_bottom 最底部坐标 + const [pageBtn_radius, pageBtn_borderStyle, pageBtn_borderWidth, pageText_color] = [8, "#fff", 2, "#fff"]; + ///// *** + + return { + pageBtn_radius, pageBtn_left, pageBtn_right, pageBtn_bottom, pageBtn_borderStyle, pageBtn_borderWidth, pageText_color + }; + // 绘制底部的两个箭头(切换道具栏的左右)///!!!// + core.drawItemListbox_setPageBtn(ctx, pageBtn_left, pageBtn_right, pageBtn_bottom, pageBtn_radius, pageBtn_borderStyle, pageBtn_borderWidth); + + const pageFontSize = pageBtn_radius * 2 - 4; + const pageFont = core.ui._buildFont(pageFontSize); + + ///!!!// core.setPageItems(page); // 修改core.status.thisUIEventInfo; ///!!!// + + const pageText = this.currPage + " / " + this.pageMax; + core.setTextAlign(ctx, "center"); + core.setTextBaseline(ctx, "bottom"); + + // 添加底部"x/y"的字样 + core.fillText(ctx, pageText, (leftbar_x + leftbar_right) / 2, pageBtn_bottom, pageText_color, pageFont); + + ///!!!// core.addUIEventListener(start_x, start_y, leftbar_right - start_x, arrow_y - start_y + 13, changeBox); ///!!!//与监听有关 + // var itembar_height = Math.ceil(pageBtn_bottom - pageBtn_radius * 2 - pageBtn_borderWidth / 2 - bottomSpace - itembar_top); + // var oneItemHeight = (itembar_height - 4) / itemNum; + // return { + // x: start_x, + // y: start_y, + // width: width, + // height: height, + // leftbar_right: leftbar_right, + // obj: { + // x: arrow_x, + // y: itembar_top, + // width: itembar_right - arrow_x, + // height: itembar_height, + // oneItemHeight: oneItemHeight + // } + // } + } + + // 首先抽象一下 思考一下顶层设计 + // ItemBox类 + // 需要的属性:当前持有的Item和数量 当前的页数 + + class ArrowButton extends ButtonBase{ + constructor(ctx, left, right, bottom, r, style, lineWidth, direction){ + const [x, y, pos] = [left + offset, bottom - offset, Math.sqrt(2) / 2 * (r - lineWidth / 2)]; + super(); + this.draw = function(ctx, left, right, bottom, r, style, lineWidth){ + const offset = lineWidth / 2 + r; + + // const [x, y, pos] = [left + offset, bottom - offset, Math.sqrt(2) / 2 * (r - lineWidth / 2)]; + core.fillPolygon(ctx, [[x - pos, y], [x + pos - 2, y - pos], [x + pos - 2, y + pos]], style); + core.strokeCircle(ctx, x, y, r, style, lineWidth); + + x = right - offset; + core.fillPolygon(ctx, [ + [x + pos, y], + [x - pos + 2, y - pos], + [x - pos + 2, y + pos] + ], style); + core.strokeCircle(ctx, x, y, r, style, lineWidth); + } + } + } + + class ToolBox extends MenuBase { + constructor(name, capacity) { + super(name); + /** 当前是否要显示隐藏的道具 + * @type {boolean} + */ + this.showHideItem = core.hasFlag('showHideItem'); + /** 一页显示的道具数量 */ + this.capacity = capacity; + /** 要显示的道具列表 */ + this.itemList = core.ui.getToolboxItems('all', this.showHideItem); + /** 当前页数 + * @type {number} + */ + this.currPage = 0; + /** 最大页数 */ + this.pageMax = this.getPageCount(); + /** 当前选中的道具的序号 + * @type {number} + */ + this.selectedIndex; + /** 绘制参数 */ + this.drawInfo; + } + + drawContent(drawInfo) { + const { pageBtn_radius, pageBtn_left, pageBtn_right, pageBtn_bottom, + pageBtn_borderStyle, pageBtn_borderWidth, pageText_color } = drawInfo; + // 绘制底部的两个箭头(切换道具栏的左右)///!!!// + core.drawItemListbox_setPageBtn(ctx, pageBtn_left, pageBtn_right, pageBtn_bottom, pageBtn_radius, pageBtn_borderStyle, pageBtn_borderWidth); + + const pageFontSize = pageBtn_radius * 2 - 4; + const pageFont = core.ui._buildFont(pageFontSize); + + ///!!!// core.setPageItems(page); // 修改core.status.thisUIEventInfo; ///!!!// + + const pageText = this.currPage + " / " + this.pageMax; + core.setTextAlign(ctx, "center"); + core.setTextBaseline(ctx, "bottom"); + + // 添加底部"x/y"的字样 + core.fillText(ctx, pageText, (leftbar_x + leftbar_right) / 2, pageBtn_bottom, pageText_color, pageFont); + } + + getPageCount() { + return Math.floor(this.itemList.length / this.capacity); + } + } + + class BoxPage extends MenuPage{ + drawContent(){ + this.drawInfo = drawBoxBackground.apply(this, [this.name]); + this.pageList.forEach((page) => { + page.drawContent(this.drawInfo); + }) + } + } + + this.t = function () { + const toolBox = new ToolBox('ui', 12); + const equipBox = new ToolBox('ui', 7); + const boxMenu = new MenuPage([toolBox, equipBox], 0, 'ui'); + return boxMenu; + // boxMenu.init(); + } + + this.y = function(){ + // let boxMenu = core.t(); + } + +} } \ No newline at end of file diff --git a/runtime.d.ts b/runtime.d.ts index 7e07d4c0..e354069f 100644 --- a/runtime.d.ts +++ b/runtime.d.ts @@ -2453,8 +2453,11 @@ interface ui { /** 绘制楼层传送器 */ drawFly(page?: any): void - /** 获得所有应该在道具栏显示的某个类型道具 */ - getToolboxItems(cls: string): string[] + /** 获得所有应该在道具栏显示的某个类型道具 + * @param cls 道具类型 + * @param cls 是否显示隐藏的道具 + */ + getToolboxItems(cls: 'tools' | 'constants' | 'all', showHide: boolean): string[] /** 绘制状态栏 */ drawStatusBar(): void