diff --git a/project/plugins.js b/project/plugins.js index 5092e657..5949c7a3 100644 --- a/project/plugins.js +++ b/project/plugins.js @@ -1,6 +1,7 @@ -var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = +/// +var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = { - "init": function () { + "init": function () { console.log("插件编写测试"); @@ -18,7 +19,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = // 可以在任何地方(如afterXXX或自定义脚本事件)调用函数,方法为 core.plugin.xxx(); // 从V2.6开始,插件中用this.XXX方式定义的函数也会被转发到core中,详见文档-脚本-函数的转发。 }, - "shop": function () { + "shop": function () { // 【全局商店】相关的功能 // // 打开一个全局商店 @@ -213,7 +214,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = return false; }, 60); }, - "removeMap": function () { + "removeMap": function () { // 高层塔砍层插件,删除后不会存入存档,不可浏览地图也不可飞到。 // 推荐用法: // 对于超高层或分区域塔,当在1区时将2区以后的地图删除;1区结束时恢复2区,进二区时删除1区地图,以此类推 @@ -300,7 +301,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = }); } }, - "fiveLayers": function () { + "fiveLayers": function () { // 是否启用五图层(增加背景2层和前景2层) 将__enable置为true即会启用;启用后请保存后刷新编辑器 // 背景层2将会覆盖背景层 被事件层覆盖 前景层2将会覆盖前景层 // 另外 请注意加入两个新图层 会让大地图的性能降低一些 @@ -309,7 +310,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = if (!__enable) return; // 创建新图层 - function createCanvas (name, zIndex) { + function createCanvas(name, zIndex) { if (!name) return; var canvas = document.createElement('canvas'); canvas.id = name; @@ -454,7 +455,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = }; } }, - "itemShop": function () { + "itemShop": function () { // 道具商店相关的插件 // 可在全塔属性-全局商店中使用「道具商店」事件块进行编辑(如果找不到可以在入口方块中找) @@ -760,7 +761,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = } }, - "enemyLevel": function () { + "enemyLevel": function () { // 此插件将提供怪物手册中的怪物境界显示 // 使用此插件需要先给每个怪物定义境界,方法如下: // 点击怪物的【配置表格】,找到“【怪物】相关的表格配置”,然后在【名称】仿照增加境界定义: @@ -848,7 +849,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = }, - "multiHeros": function () { + "multiHeros": function () { // 多角色插件 // Step 1: 启用本插件 // Step 2: 定义每个新的角色各项初始数据(参见下方注释) @@ -994,7 +995,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = core.setFlag("heroId", toHeroId); // 保存切换到的角色ID } }, - "heroFourFrames": function () { + "heroFourFrames": function () { // 样板的勇士/跟随者移动时只使用2、4两帧,观感较差。本插件可以将四帧全用上。 // 是否启用本插件 @@ -1047,7 +1048,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = return false; } }, - "startCanvas": function () { + "startCanvas": function () { // 使用本插件可以将自绘的标题界面居中。仅在【标题开启事件化】后才有效。 // 由于一些技术性的原因,标题界面事件化无法应用到覆盖状态栏的整个界面。 // 这是一个较为妥协的插件,会在自绘标题界面时隐藏状态栏、工具栏和边框,并将画布进行居中。 @@ -1133,16 +1134,1287 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = _loadData.call(core.control, data, callback); } }, - "advancedAnimation": function () { - // 在此增加新插件 + "advancedAnimation": function () { + // 在此增加新插件 -}, - "drawItemDetail": function () { - // 在此增加新插件 + }, + "drawItemDetail": function () { + /* 宝石血瓶左下角显示数值 + * 需要将 变量:itemDetail改为true才可正常运行 + * 请尽量减少勇士的属性数量,否则可能会出现严重卡顿(划掉,现在你放一万个属性也不会卡) + * 注意:这里的属性必须是core.status.hero里面的,flag无法显示 + * 如果不想显示,可以core.setFlag("itemDetail", false); + * 然后再core.getItemDetail(); + * 如有bug在大群或造塔群@古祠 + */ -}, - "autoGet": function () { - // 在此增加新插件 + // 忽略的道具 + const ignore = ['superPotion']; -} + // 取消注释下面这句可以减少超大地图的判定。 + // 如果地图宝石过多,可能会略有卡顿,可以尝试取消注释下面这句话来解决。 + // core.bigmap.threshold = 256; + const origin = core.control.updateStatusBar; + core.updateStatusBar = core.control.updateStatusBar = function () { + if (core.getFlag('__statistics__')) return; + else return origin.apply(core.control, arguments); + } + + core.control.updateDamage = function (floorId, ctx) { + floorId = floorId || core.status.floorId; + if (!floorId || core.status.gameOver || main.mode != 'play') return; + const onMap = ctx == null; + + // 没有怪物手册 + if (!core.hasItem('book')) return; + core.status.damage.posX = core.bigmap.posX; + core.status.damage.posY = core.bigmap.posY; + if (!onMap) { + const width = core.floors[floorId].width, + height = core.floors[floorId].height; + // 地图过大的缩略图不绘制显伤 + if (width * height > core.bigmap.threshold) return; + } + this._updateDamage_damage(floorId, onMap); + this._updateDamage_extraDamage(floorId, onMap); + if (core.status.thisMap) core.getItemDetail(floorId); // 宝石血瓶详细信息 + this.drawDamage(ctx); + }; + // 获取宝石信息 并绘制 + this.getItemDetail = function (floorId) { + if (!core.getFlag('itemDetail')) return; + if (!core.status.thisMap) return; + floorId = floorId ?? core.status.thisMap.floorId; + const beforeRatio = core.status.thisMap.ratio; + core.status.thisMap.ratio = core.status.maps[floorId].ratio; + let diff = {}; + const before = core.status.hero; + const hero = core.clone(core.status.hero); + const handler = { + set(target, key, v) { + diff[key] = v - (target[key] || 0); + if (!diff[key]) diff[key] = void 0; + return true; + } + }; + core.status.hero = new Proxy(hero, handler); + core.status.maps[floorId].blocks.forEach(function (block) { + if ( + block.event.cls !== 'items' || + ignore.includes(block.event.id) || + block.disable + ) + return; + const x = block.x, + y = block.y; + // v2优化,只绘制范围内的部分 + if (core.bigmap.v2) { + if ( + x < core.bigmap.posX - core.bigmap.extend || + x > core.bigmap.posX + core._SIZE_ + core.bigmap.extend || + y < core.bigmap.posY - core.bigmap.extend || + y > core.bigmap.posY + core._SIZE_ + core.bigmap.extend + ) { + return; + } + } + diff = {}; + const id = block.event.id; + const item = core.material.items[id]; + if (item.cls === 'equips') { + // 装备也显示 + const diff = item.equip.value ?? {}; + const per = item.equip.percentage ?? {}; + for (const name in per) { + diff[name + 'per'] = per[name].toString() + '%'; + } + drawItemDetail(diff, x, y); + return; + } + // 跟数据统计原理一样 执行效果 前后比较 + core.setFlag('__statistics__', true); + try { + eval(item.itemEffect); + } catch (error) { } + drawItemDetail(diff, x, y); + }); + core.status.thisMap.ratio = beforeRatio; + core.status.hero = before; + window.hero = before; + window.flags = before.flags; + }; + + // 绘制 + function drawItemDetail(diff, x, y) { + const px = 32 * x + 2, + py = 32 * y + 30; + let content = ''; + // 获得数据和颜色 + let i = 0; + for (const name in diff) { + if (!diff[name]) continue; + let color = '#fff'; + + if (typeof diff[name] === 'number') + content = core.formatBigNumber(diff[name], true); + else content = diff[name]; + switch (name) { + case 'atk': + case 'atkper': + color = '#FF7A7A'; + break; + case 'def': + case 'defper': + color = '#00E6F1'; + break; + case 'mdef': + case 'mdefper': + color = '#6EFF83'; + break; + case 'hp': + color = '#A4FF00'; + break; + case 'hpmax': + case 'hpmaxper': + color = '#F9FF00'; + break; + case 'mana': + color = '#c66'; + break; + } + // 绘制 + core.status.damage.data.push({ + text: content, + px: px, + py: py - 10 * i, + color: color + }); + i++; + } + } + }, + "autoGet": 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 = 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) return false; + core.status.route.push(action); + if (core.material.items[itemId].hideInReplay || core.status.replay.speed == 24) { + core.loadEquip(itemId, core.replay); + 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, core.replay); + }, 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)) return false; + core.status.route.push(action); + if (core.status.replay.speed == 24) { + core.unloadEquip(equipType, core.replay); + 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, core.replay); + }, 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); + }, + "MenuBase": function () { + // 本插件定义了一些用于绘制的基类 + class ButtonBase { + constructor(x, y, w, h) { + this.x = x; + this.y = y; + this.w = w; + this.h = h; + this.disable = false; + + this.draw = () => { }; + this.event = (x, y, px, py) => { }; + this.status; + } + + register() { + core.registerAction('onclick', this.name, (x, y, px, py) => { + if (this.disable) return; + if (px >= this.x && px <= this.x + this.w && py > this.y && py <= this.y + this.h) + this.event(x, y, px, py); + }, 100); + } + + unregister() { + core.unregisterAction('onclick', this.name); + } + } + + class MenuBase { + constructor(name) { + this.name = name; + this.btnList = new Map(); + this.keyEvent = () => { }; + this.end = () => { core.clearMap(this.name); }; + } + + drawContent() { + this.btnList.forEach((button) => { if (!button.disable) button.draw(); }) + } + + beginListen() { + core.registerAction('keyDown', this.name, this.keyEvent, 100); + this.btnList.forEach((button) => { button.register(); }) + } + + endListen() { + core.unregisterAction('keyDown', this.name); + this.btnList.forEach((button) => { button.unregister(); }) + } + + clear() { + this.endListen(); + core.deleteCanvas(this.name); + } + + init() { + this.beginListen(); + this.drawContent(); + } + } + class MenuPage extends MenuBase { + constructor(pageMax, currPage) { + this.pageMax = pageMax; + this.currPage = currPage | 0; + this.pageList = []; + } + + initOnePage() { + this.pageList[this.currPage].init(); + } + + changePage(num) { + if (num !== this.currPage) { + const beforeMenu = this.pageList[this.currPage]; + beforeMenu.clear(); + } + this.initOnePage(this.pageList[num]); + this.currPage = num; + } + + pageDown() { + if (this.currPage > 0) this.changePage(this.currPage - 1); + } + + pageUp() { + if (this.currPage < this.pageMax - 1) this.changePage(this.currPage + 1); + } + } + + this.MenuBase = { ButtonBase, MenuBase, MenuPage }; + }, + "scrollingText": function () { + // 本插件用于绘制在线留言 + + }, + "setting": function () { + // 设置界面绘制 + // core.openSettings = ... + + this.t = function () { + const { ButtonBase, MenuBase, MenuPage } = this.MenuBase; + + const ctx = 'setting'; + + function drawSetting(ctx) { + core.createCanvas(ctx, 0, 0, core.__PIXELS__, core.__PIXELS__, 136); + core.clearMap(ctx); + core.setAlpha(ctx, 0.85); + core.strokeRoundRect(ctx, 0, 0, core.__PIXELS__, core.__PIXELS__, 5, "#fff", 2); + core.fillRoundRect(ctx, 0, 0, core.__PIXELS__, core.__PIXELS__, 5, "gray"); + core.setAlpha(ctx, 1); + core.strokeRoundRect(ctx, 20, 40, core.__PIXELS__ - 40, 70, 3, "white"); + core.fillRoundRect(ctx, 21, 41, core.__PIXELS__ - 42, 68, 3, "#555555"); + core.setTextAlign(ctx, 'center'); + core.ui.fillText(ctx, "设置", core.__PIXELS__ / 2, 25, 'white', '20px Verdana'); + } + + class SettingMenu extends MenuBase { + drawContent() { + drawSetting(ctx); + } + } + + const settingMenu = new SettingMenu(); + + settingMenu.init(); + + + + } + } } \ No newline at end of file