Compare commits

..

10 Commits

Author SHA1 Message Date
ShakeFlower
9902f22258 fix:修复物品没有描述时文本显示的问题 2026-02-13 09:47:06 +08:00
ShakeFlower
305b43e07c fix:不明原因导致_updateDamage_damage没有this 2026-02-12 17:58:39 +08:00
ShakeFlower
af127cb305 feat:地图怪物数据显示自定义 2026-02-12 09:13:40 +08:00
ShakeFlower
d6a03a8c62 chore:恢复存档文件本地化 2026-02-11 22:16:42 +08:00
ShakeFlower
50e1eb4a0c feat:地图怪物数据显示自定义 2026-02-11 22:13:41 +08:00
ShakeFlower
b4eb93c58b fix:修正翻页时选中的道具没有变的bug 2026-01-15 16:13:37 +08:00
ShakeFlower
f75a9a20ec fix:修正点击跳过剧情选项没有立即刷新的bug 2025-09-24 10:45:14 +08:00
ShakeFlower
ee9caac078 fix:修复道具栏右侧有时未正确刷新的bug 2025-09-23 14:47:08 +08:00
ShakeFlower
8037da8663 fix:录像模式下打开新装备栏关不上 2025-09-07 11:21:44 +08:00
ShakeFlower
8678241111 fix:新道具栏关闭快捷键面板时只恢复已存在的监听 2025-09-06 22:53:14 +08:00
4 changed files with 453 additions and 60 deletions

View File

@ -8,7 +8,7 @@
(function () { (function () {
// 将这一行改成 false 可以禁用本拓展 // 将这一行改成 false 可以禁用本拓展
var __enabled = false; var __enabled = true;
if (window.jsinterface || !window.fs || !__enabled) return; if (window.jsinterface || !window.fs || !__enabled) return;

View File

@ -1340,13 +1340,76 @@ control.prototype.updateDamage = function (floorId, ctx) {
this.drawDamage(ctx); this.drawDamage(ctx);
} }
control.prototype.getEnemyValueString = function(name, blockId, x, y, floorId) {
if (name == null) return { text: null, color: null };
const colorMap = {
hp: '#55ff55', atk: '#ff5555',
def: '#5555ff', money: '#ffff55', exp: '#ffaa33',
criticalDamage: '#B22222', defDamage: '#1E90FF'
}
switch (name) {
case "damage":
if (core.flags.displayEnemyDamage) {
const damageString = core.enemys.getDamageString(blockId, x, y, floorId);
return { text: damageString.damage, color: damageString.color };
}
break;
case "critical":
if (core.flags.displayCritical) {
const critical = core.enemys.nextCriticals(blockId, 1, x, y, floorId);
const criticalString = core.formatBigNumber((critical[0] || [])[0], true);
return { text: criticalString == '???' ? '?' : criticalString, color: '#FFFFFF' };
}
break;
case "hp":
case "atk":
case "def":
case "money":
case "exp":
const value = core.enemys.getEnemyValue(blockId, name, x, y, floorId);
const valueString = core.utils.formatBigNumber(value, 5);
return { text: valueString, color: colorMap[name] };
case "criticalDamage":
let criticalDamage = 0;
const criticals = core.enemys.nextCriticals(blockId, 1, x, y, floorId);
if (criticals && criticals.length > 0) {
criticalDamage = criticals[0][1];
criticalDamage = core.formatBigNumber(criticalDamage, 5);
}
return { text: criticalDamage, color: colorMap.criticalDamage };
case "defDamage":
const defDamage = core.enemys.getDefDamage(blockId, 1, x, y, floorId);
return { text: defDamage, color: colorMap.defDamage };
case "special":
const specialData = core.getLocalStorage('specialIconData', {});
const special = core.enemys.getEnemyValue(blockId, 'special', x, y, floorId);
const specialArr = core.utils.parseSpecial(special);
let text = '';
for (const s of specialArr) {
if (specialData[s]) {
text += specialData[s];
}
}
return { text, color: '#FFFFFF' };
}
}
control.prototype.pushDamageData = function(name, px, py, blockId, x, y, floorId) {
if (name == null) return;
const { text, color } = this.getEnemyValueString(name, blockId, x, y, floorId);
core.status.damage.data.push({ text, px, py, color });
}
control.prototype._updateDamage_damage = function (floorId, onMap) { control.prototype._updateDamage_damage = function (floorId, onMap) {
core.status.damage.data = []; core.status.damage.data = [];
if (!core.flags.displayEnemyDamage && !core.flags.displayExtraDamage) return; if (!core.flags.displayEnemyDamage && !core.flags.displayExtraDamage) return;
core.extractBlocks(floorId); core.extractBlocks(floorId);
core.status.maps[floorId].blocks.forEach(function (block) { core.status.maps[floorId].blocks.forEach(function (block) {
var x = block.x, y = block.y; const x = block.x,
y = block.y,
blockId = block.event.id;
// v2优化只绘制范围内的部分 // v2优化只绘制范围内的部分
if (onMap && core.bigmap.v2) { if (onMap && core.bigmap.v2) {
@ -1357,16 +1420,15 @@ control.prototype._updateDamage_damage = function (floorId, onMap) {
} }
if (!block.disable && block.event.cls.indexOf('enemy') == 0 && block.event.displayDamage !== false) { if (!block.disable && block.event.cls.indexOf('enemy') == 0 && block.event.displayDamage !== false) {
if (core.flags.displayEnemyDamage) { const defaultData = { leftdown: { 1: 'damage', 2: 'critical' }, rightup: {} };
var damageString = core.enemys.getDamageString(block.event.id, x, y, floorId); const data = core.getLocalStorage('displayData', defaultData);
core.status.damage.data.push({ text: damageString.damage, px: 32 * x + 1, py: 32 * (y + 1) - 1, color: damageString.color });
} core.control.pushDamageData(data.leftdown[1], 32 * x + 1, 32 * (y + 1) - 1, blockId, x, y, floorId);
if (core.flags.displayCritical) { core.control.pushDamageData(data.leftdown[2], 32 * x + 1, 32 * (y + 1) - 11, blockId, x, y, floorId);
var critical = core.enemys.nextCriticals(block.event.id, 1, x, y, floorId); core.control.pushDamageData(data.leftdown[3], 32 * x + 1, 32 * (y + 1) - 21, blockId, x, y, floorId);
critical = core.formatBigNumber((critical[0] || [])[0], true); core.control.pushDamageData(data.rightup[1], 32 * x + 16, 32 * (y + 1) - 21, blockId, x, y, floorId);
if (critical == '???') critical = '?'; core.control.pushDamageData(data.rightup[2], 32 * x + 16, 32 * (y + 1) - 11, blockId, x, y, floorId);
core.status.damage.data.push({ text: critical, px: 32 * x + 1, py: 32 * (y + 1) - 11, color: '#FFFFFF' }); core.control.pushDamageData(data.rightup[3], 32 * x + 16, 32 * (y + 1) - 1, blockId, x, y, floorId);
}
} }
}); });
} }

View File

@ -80,20 +80,32 @@ enemys.prototype.getSpecials = function () {
return this.enemydata.getSpecials(); return this.enemydata.getSpecials();
} }
enemys.prototype.getSpecialIndexMap = function () {
const specials = this.getSpecials();
const map = {};
if (!specials) return map;
specials.forEach(special => {
const index = special[0];
map[index] = special;
});
return map;
}
////// 获得所有特殊属性的名称 ////// ////// 获得所有特殊属性的名称 //////
enemys.prototype.getSpecialText = function (enemy) { enemys.prototype.getSpecialText = function (enemy) {
if (typeof enemy == 'string') enemy = core.material.enemys[enemy]; if (typeof enemy == 'string') enemy = core.material.enemys[enemy];
if (!enemy) return []; if (!enemy) return [];
var special = enemy.special; const special = enemy.special;
var text = []; const text = [];
const specialArr = core.utils.parseSpecial(special);
var specials = this.getSpecials(); const specialIndexMap = this.getSpecialIndexMap();
if (specials) { specialArr.forEach(specialNum => {
for (var i = 0; i < specials.length; i++) { const specialInfo = specialIndexMap[specialNum];
if (this.hasSpecial(special, specials[i][0])) if (specialInfo) {
text.push(this._calSpecialContent(enemy, specials[i][1])); text.push(this._calSpecialContent(enemy, specialInfo[1]));
} }
} });
return text; return text;
} }
@ -101,18 +113,18 @@ enemys.prototype.getSpecialText = function (enemy) {
enemys.prototype.getSpecialColor = function (enemy) { enemys.prototype.getSpecialColor = function (enemy) {
if (typeof enemy == 'string') enemy = core.material.enemys[enemy]; if (typeof enemy == 'string') enemy = core.material.enemys[enemy];
if (!enemy) return []; if (!enemy) return [];
var special = enemy.special; const special = enemy.special;
var colors = []; const colors = [];
var specials = this.getSpecials(); const specialArr = core.utils.parseSpecial(special);
if (specials) { const specialIndexMap = this.getSpecialIndexMap();
for (var i = 0; i < specials.length; i++) { specialArr.forEach(specialNum => {
if (this.hasSpecial(special, specials[i][0])) const specialInfo = specialIndexMap[specialNum];
colors.push(specials[i][3] || null); if (specialInfo) {
colors.push(specialInfo[3] || null);
} }
} });
return colors; return colors;
} }
////// 获得所有特殊属性的额外标记 ////// ////// 获得所有特殊属性的额外标记 //////
@ -133,10 +145,10 @@ enemys.prototype.getSpecialFlag = function (enemy) {
} }
////// 获得每个特殊属性的说明 ////// ////// 获得每个特殊属性的说明 //////
enemys.prototype.getSpecialHint = function (enemy, special) { enemys.prototype.getSpecialHint = function (enemy, specialNum) {
var specials = this.getSpecials(); var specials = this.getSpecials();
if (special == null) { if (specialNum == null) {
if (specials == null) return []; if (specials == null) return [];
var hints = []; var hints = [];
for (var i = 0; i < specials.length; i++) { for (var i = 0; i < specials.length; i++) {
@ -149,7 +161,7 @@ enemys.prototype.getSpecialHint = function (enemy, special) {
if (specials == null) return ""; if (specials == null) return "";
for (var i = 0; i < specials.length; i++) { for (var i = 0; i < specials.length; i++) {
if (special == specials[i][0]) if (specialNum == specials[i][0])
return "\r[#FF6A6A]\\d" + this._calSpecialContent(enemy, specials[i][1]) + "\\d\r[]" + this._calSpecialContent(enemy, specials[i][2]); return "\r[#FF6A6A]\\d" + this._calSpecialContent(enemy, specials[i][1]) + "\\d\r[]" + this._calSpecialContent(enemy, specials[i][2]);
} }
return ""; return "";

View File

@ -2861,7 +2861,40 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 =
core.drawLine(ctx, x + lineOffsetX, y + h - lineOffsetX, x + w - lineOffsetX, y + lineOffsetX, lineStyle, lineWidthX); core.drawLine(ctx, x + lineOffsetX, y + h - lineOffsetX, x + w - lineOffsetX, y + lineOffsetX, lineStyle, lineWidthX);
} }
} }
this.uiBase = { ButtonBase, RoundBtn, IconBtn, ExitBtn, MenuBase, Pagination, KeyCodeEnum };
class ArrowBtn extends ButtonBase {
constructor(x, y, w, h, dir, config) {
super(x, y, w, h);
this.config = config || {};
/** @type {'left'|'right'} */
this.dir = dir;
}
draw() {
const {
marginLeft = 6, marginTop = 5, marginRight = 4,
backStyle = 'gray', arrowStyle = 'black'
} = this.config || {};
const { x, y, w, h, ctx } = this;
core.fillRoundRect(ctx, x, y, w, h, 3, backStyle);
if (this.dir === 'left')
core.fillPolygon(ctx, [
[x + w - marginLeft, y + marginTop],
[x + w - marginLeft, y + h - marginTop],
[x + marginRight, y + h / 2]
], arrowStyle);
else if (this.dir === 'right')
core.fillPolygon(ctx, [
[x + marginLeft, y + marginTop],
[x + marginLeft, y + h - marginTop],
[x + w - marginRight, y + h / 2]
], arrowStyle);
}
}
this.uiBase = {
ButtonBase, RoundBtn, IconBtn, ExitBtn,
ArrowBtn, MenuBase, Pagination, KeyCodeEnum
};
}, },
"newBackpackLook": function () { "newBackpackLook": function () {
// 本插件定义了一些用于绘制的基类 // 本插件定义了一些用于绘制的基类
@ -2877,6 +2910,15 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 =
core.actions._keyDownToolbox = core.actions._keyDownEquipbox = function (keyCode) { return true; }.bind(core.actions); core.actions._keyDownToolbox = core.actions._keyDownEquipbox = function (keyCode) { return true; }.bind(core.actions);
core.actions._clickToolbox = core.actions._clickEquipbox = function (x, y, px, py) { return true; }.bind(core.actions); core.actions._clickToolbox = core.actions._clickEquipbox = function (x, y, px, py) { return true; }.bind(core.actions);
core.actions._keyUpToolbox = core.actions._keyUpEquipbox = function (keyCode) { return true; }.bind(core.actions); core.actions._keyUpToolbox = core.actions._keyUpEquipbox = function (keyCode) { return true; }.bind(core.actions);
// 暂不考虑修改core.status.event.id该变量牵涉太多作用不完全清楚
// 录像模式下下列函数会进行检测,不处于特定模式时,阻止自定义监听事件
core.actions._checkReplaying = function () {
if (core.isReplaying() && !UI._back?.onDraw &&
['save', 'book', 'book-detail', 'viewMaps', 'toolbox', 'equipbox', 'text'].indexOf(core.status.event.id) < 0) {
return true;
}
return false;
}.bind(core.actions);
const oriClosePanel = core.ui.closePanel; const oriClosePanel = core.ui.closePanel;
core.ui.closePanel = function () { core.ui.closePanel = function () {
@ -3349,6 +3391,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 =
if (!this.canPageUp()) return; if (!this.canPageUp()) return;
this.page++; this.page++;
this.updateItemList(); this.updateItemList();
this.setIndex(Math.min(this.index, this.currItemList.length - 1));
this.drawContent(); this.drawContent();
} }
@ -3357,6 +3400,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 =
if (!this.canPageDown()) return; if (!this.canPageDown()) return;
this.page--; this.page--;
this.updateItemList(); this.updateItemList();
this.setIndex(this.index);
this.drawContent(); this.drawContent();
} }
} }
@ -3677,8 +3721,8 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 =
const itemsUsedCount = core.getFlag('itemsUsedCount', {}); const itemsUsedCount = core.getFlag('itemsUsedCount', {});
core.fillText(ctx, itemsUsedCount[itemId] || 0, 80, 113, 'rgb(47, 49, 54)', '14px Verdana'); core.fillText(ctx, itemsUsedCount[itemId] || 0, 80, 113, 'rgb(47, 49, 54)', '14px Verdana');
} }
const rawItemText = core.replaceText(item.text) ?? "";
const itemText = core.replaceText(item.text) + ((UI.type === "equips") ? this.getEquipCompareInfo(item) : ""); // 物品描述信息 const itemText = rawItemText + ((UI.type === "equips") ? this.getEquipCompareInfo(item) : ""); // 物品描述信息
core.drawTextContent(ctx, itemText, { core.drawTextContent(ctx, itemText, {
left: 20, left: 20,
top: 125, top: 125,
@ -3792,7 +3836,9 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 =
clear() { clear() {
super.clear(); super.clear();
const { back, itemInv, equipSlots, itemInfo } = UI; const { back, itemInv, equipSlots, itemInfo } = UI;
[back, itemInv, equipSlots, itemInfo].forEach((menu) => { menu.beginListen(); }); [back, itemInv, equipSlots, itemInfo].forEach(menu => {
if (menu.onDraw) menu.beginListen(); // 注意本来就没在绘制的则不监听
});
UI.itemInfo.drawContent(); // 快捷键图标会发生变化 UI.itemInfo.drawContent(); // 快捷键图标会发生变化
} }
} }
@ -3952,6 +3998,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 =
this.itemInv.updateItemList(); this.itemInv.updateItemList();
this.itemInv.setIndex(this.itemInv.index); this.itemInv.setIndex(this.itemInv.index);
this.itemInv.drawContent(); this.itemInv.drawContent();
this.itemInfo.drawContent(); // 这里不论选中物品是否变化itemInfo必定要重绘因为按钮图案会变
}); });
const setHotkeyBtn = new IconBtn(145, 60, 24, 24, 'keyboard'); const setHotkeyBtn = new IconBtn(145, 60, 24, 24, 'keyboard');
this.itemInfo.registerBtn('setHotkeyBtn', setHotkeyBtn, () => { this.itemInfo.registerBtn('setHotkeyBtn', setHotkeyBtn, () => {
@ -4035,7 +4082,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 =
/** @param {'all'|'equips'} currType */ /** @param {'all'|'equips'} currType */
function drawItemBox(currType) { function drawItemBox(currType) {
UI.clearAll(); UI.clearAll();
if (UI._toolInv && UI._toolInv.onDraw && currType === UI.type) return; if (UI._toolInv && UI._toolInv?.onDraw && currType === UI.type) return;
core.lockControl(); core.lockControl();
UI.type = currType; UI.type = currType;
UI.itemInv.updateItemList(); UI.itemInv.updateItemList();
@ -4456,7 +4503,8 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 =
// #endregion // #endregion
// #region 按钮类 // #region 按钮类
const { ButtonBase, RoundBtn, IconBtn, ExitBtn, MenuBase, Pagination, KeyCodeEnum } = core.plugin.uiBase; const { ButtonBase, RoundBtn, IconBtn, ExitBtn,
ArrowBtn, MenuBase, Pagination, KeyCodeEnum } = core.plugin.uiBase;
class TextButton extends ButtonBase { class TextButton extends ButtonBase {
constructor(x, y, w, h, text) { constructor(x, y, w, h, text) {
@ -4488,6 +4536,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 =
const setting = this.setting; const setting = this.setting;
// 取消注释下面这一句将显示所有按钮的判定框 // 取消注释下面这一句将显示所有按钮的判定框
// core.strokeRect(ctx, this.x, this.y, this.w, this.h, 'yellow'); // core.strokeRect(ctx, this.x, this.y, this.w, this.h, 'yellow');
core.setTextAlign(ctx, 'start');
core.ui.fillText(ctx, setting.getName(), x, y + h / 2 + 5, 'white', '16px Verdana'); core.ui.fillText(ctx, setting.getName(), x, y + h / 2 + 5, 'white', '16px Verdana');
const drawFunc = setting.draw; const drawFunc = setting.draw;
if (this.status === 'selected') { if (this.status === 'selected') {
@ -4618,7 +4667,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 =
* @param {SettingButton} btn * @param {SettingButton} btn
* @param {...(string|number)} eventArgs * @param {...(string|number)} eventArgs
*/ */
registerBtn(pos, key, btn, ...eventArgs) { registerSettingBtn(pos, key, btn, ...eventArgs) {
super.registerBtn(pos, btn, { super.registerBtn(pos, btn, {
'ondown': () => { 'ondown': () => {
if (this.selectedBtn === btn) this.execEffect(btn, key, ...eventArgs); if (this.selectedBtn === btn) this.execEffect(btn, key, ...eventArgs);
@ -4631,10 +4680,10 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 =
btn.setting = this.settingData[key]; btn.setting = this.settingData[key];
} }
registerBtns(arr) { registerSettingBtns(arr) {
arr.forEach(ele => { arr.forEach(ele => {
const [key, btn, event, ...eventArgs] = ele; const [key, btn, event, ...eventArgs] = ele;
this.registerBtn(key, btn, event, ...eventArgs); this.registerSettingBtn(key, btn, event, ...eventArgs);
}); });
} }
} }
@ -4793,13 +4842,19 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 =
}, },
skipText: { skipText: {
getName: () => '跳过剧情:' + (core.getLocalStorage('skipText', false) ? '开' : '关'), getName: () => '跳过剧情:' + (core.getLocalStorage('skipText', false) ? '开' : '关'),
effect: () => { invertLocalStorage('skipText'); }, effect: () => {
invertLocalStorage('skipText');
checkSkipFuncs();
},
text: '跳过全部文字对话。初见请勿开启此选项。', text: '跳过全部文字对话。初见请勿开启此选项。',
replay: false, replay: false,
}, },
skipPeform: { skipPeform: {
getName: () => '跳过演出:' + (core.getLocalStorage('skipPerform', false) ? '开' : '关'), getName: () => '跳过演出:' + (core.getLocalStorage('skipPerform', false) ? '开' : '关'),
effect: () => { invertLocalStorage('skipPerform'); }, effect: () => {
invertLocalStorage('skipPerform');
checkSkipFuncs();
},
text: '加速等待、播放动画等常见演出效果。', text: '加速等待、播放动画等常见演出效果。',
replay: false, replay: false,
}, },
@ -4852,7 +4907,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 =
function gamePlayFactory() { function gamePlayFactory() {
const gamePlayMenu = new GamePlay(); const gamePlayMenu = new GamePlay();
gamePlayMenu.registerBtns([ gamePlayMenu.registerSettingBtns([
['1,1', 'autoGet', new SettingButton(40, 180, 150, 30)], ['1,1', 'autoGet', new SettingButton(40, 180, 150, 30)],
['2,1', 'autoBattle', new SettingButton(220, 180, 150, 30)], ['2,1', 'autoBattle', new SettingButton(220, 180, 150, 30)],
['1,2', 'clickMove', new SettingButton(40, 230, 150, 30)], ['1,2', 'clickMove', new SettingButton(40, 230, 150, 30)],
@ -4912,13 +4967,13 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 =
displayEnemyDamage: { displayEnemyDamage: {
getName: () => '怪物显伤:' + (core.flags.displayEnemyDamage ? '开' : '关'), getName: () => '怪物显伤:' + (core.flags.displayEnemyDamage ? '开' : '关'),
effect: core.actions._clickSwitchs_display_enemyDamage, effect: core.actions._clickSwitchs_display_enemyDamage,
text: '怪物显伤', text: '地图上显示怪物的伤害。',
replay: false, replay: false,
}, },
displayCritical: { displayCritical: {
getName: () => '临界显伤:' + (core.flags.displayCritical ? '开' : '关'), getName: () => '临界显伤:' + (core.flags.displayCritical ? '开' : '关'),
effect: core.actions._clickSwitchs_display_critical, effect: core.actions._clickSwitchs_display_critical,
text: '临界显伤', text: '地图上显示怪物的临界值',
replay: false, replay: false,
}, },
displayExtraDamage: { displayExtraDamage: {
@ -4982,21 +5037,38 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 =
function gameViewFactory() { function gameViewFactory() {
const gameViewMenu = new GameView(); const gameViewMenu = new GameView();
gameViewMenu.registerBtns([ const advanceDisplayBtn = new RoundBtn(300, 280, 32, 18, "高级", {
font: '12px Verdana', fillStyle: "SlateGray", radius: 1, fontStyle: "yellow",
strokeStyle: "black"
});
gameViewMenu.registerBtn('openAdvanceDisplay', advanceDisplayBtn, () => {
const settingMenu = core.plugin.settingMenu;
if (settingMenu) {
settingMenu.endListen();
// 隐藏大菜单的按钮是为了避免视觉上的干扰
settingMenu.btnMap.forEach(btn => { btn.disable = true });
settingMenu.pageList[settingMenu.currPage].endListen();
settingMenu.drawContent();
}
core.ui.clearUIEventSelector(0);
const advanceDisplayMenu = advanceDisplayFactory();
advanceDisplayMenu.init();
});
gameViewMenu.registerSettingBtns([
['1,1', 'itemDetail', new SettingButton(40, 180, 150, 25)], ['1,1', 'itemDetail', new SettingButton(40, 180, 150, 25)],
['1,2', 'HDCanvas', new SettingButton(40, 205, 150, 25)], ['1,2', 'displayEnemyDamage', new SettingButton(40, 205, 150, 25)],
['1,3', 'displayEnemyDamage', new SettingButton(40, 230, 150, 25)], ['1,3', 'displayExtraDamage', new SettingButton(40, 230, 150, 25)],
['1,4', 'displayExtraDamage', new SettingButton(40, 255, 150, 25)], ['1,4', 'autoScale', new SettingButton(40, 255, 150, 25)],
['1,5', 'extraDamageType', new SettingButton(40, 280, 150, 25)], ['1,5', 'HDCanvas', new SettingButton(40, 280, 150, 25)],
['1,6', 'bgm', new SettingButton(40, 325, 150, 25)], ['1,6', 'bgm', new SettingButton(40, 325, 150, 25)],
['1,7', 'decreaseVolume', new SettingButton(40, 350, 25, 25)], ['1,7', 'decreaseVolume', new SettingButton(40, 350, 25, 25)],
['2,7', 'increaseVolume', new SettingButton(140, 350, 25, 25)], ['2,7', 'increaseVolume', new SettingButton(140, 350, 25, 25)],
['2,1', 'zoomIn', new SettingButton(220, 180, 25, 25)], ['2,1', 'displayEnemyDamage', new SettingButton(220, 180, 150, 25)],
['3,1', 'zoomOut', new SettingButton(330, 180, 25, 25)], ['2,2', 'displayCritical', new SettingButton(220, 205, 150, 25)],
['2,2', 'autoScale', new SettingButton(220, 205, 150, 25)], ['2,3', 'extraDamageType', new SettingButton(220, 230, 150, 25)],
['2,3', 'enableEnemyPoint', new SettingButton(220, 230, 150, 25)], ['2,4', 'zoomIn', new SettingButton(220, 255, 25, 25)],
['2,4', 'displayCritical', new SettingButton(220, 255, 150, 25)], ['3,4', 'zoomOut', new SettingButton(330, 255, 25, 25)],
['2,6', 'se', new SettingButton(220, 325, 150, 25)] ['2,6', 'se', new SettingButton(220, 325, 150, 25)],
]); ]);
return gameViewMenu; return gameViewMenu;
} }
@ -5104,7 +5176,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 =
function keyMenuFactory() { function keyMenuFactory() {
const keyMenu = new KeyMenu(); const keyMenu = new KeyMenu();
keyMenu.registerBtns([ keyMenu.registerSettingBtns([
['1,1', 'leftHand', new SettingButton(40, 160, 150, 25)], ['1,1', 'leftHand', new SettingButton(40, 160, 150, 25)],
['1,2', 'setHotKey', new SettingButton(40, 220, 150, 25, '1'), 1], ['1,2', 'setHotKey', new SettingButton(40, 220, 150, 25, '1'), 1],
['2,2', 'setHotKey', new SettingButton(220, 220, 150, 25, '2'), 2], ['2,2', 'setHotKey', new SettingButton(220, 220, 150, 25, '2'), 2],
@ -5558,7 +5630,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 =
function consoleMenuFactory() { function consoleMenuFactory() {
const consoleMenu = new ConsoleMenu(); const consoleMenu = new ConsoleMenu();
consoleMenu.registerBtns([ consoleMenu.registerSettingBtns([
['1,1', 'debug_wallHacking', new SettingButton(40, 220, 150, 25)], ['1,1', 'debug_wallHacking', new SettingButton(40, 220, 150, 25)],
['1,2', 'debug_statusName', new SettingButton(80, 250, 80, 20)], ['1,2', 'debug_statusName', new SettingButton(80, 250, 80, 20)],
['2,2', 'debug_statusValue', new SettingButton(210, 250, 80, 20)], ['2,2', 'debug_statusValue', new SettingButton(210, 250, 80, 20)],
@ -5573,6 +5645,253 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 =
return consoleMenu; return consoleMenu;
} }
// #endregion // #endregion
// #region 敌人信息显示调节界面
const infoNameMap = {
'damage': '伤害', 'critical': '临界', 'hp': core.control.getStatusLabel('hp'),
'atk': core.control.getStatusLabel('atk'), 'def': core.control.getStatusLabel('def'),
'money': core.control.getStatusLabel('money'), 'exp': core.control.getStatusLabel('exp'),
'criticalDamage': '临界减伤', 'defDamage': '1防减伤', 'special': '特殊属性',
}
class DisplayInfoBtn extends RoundBtn {
constructor(x, y, w, h, pos, index) {
super(x, y, w, h);
this.pos = pos;
this.index = index;
}
draw() {
super.draw();
const isEmpty = !this.infoName;
const ctx = this.ctx;
const { x, y, w, h } = this;
const [x0, y0, r, offset] = [x + w + 15, y + h / 2, h / 2 - 2, 2];
core.fillCircle(ctx, x0, y0, r, isEmpty ? 'lime' : 'red');
core.drawLine(ctx, x0 - r + offset, y0, x0 + r - offset, y0, 'white', 2);
if (isEmpty) core.drawLine(ctx, x0, y0 - r + offset, x0, y0 + r - offset, 'white', 2);
}
inRange(px, py) { // 实际的点击判定区是右边的圆形
const { x, y, w, h } = this;
return px >= x + w + 15 - h / 2 && px <= x + w + 15 + h / 2 && py >= y && py <= y + h;
}
}
class SpecialIconBtn extends RoundBtn {}
class AdvanceDisplayMenu extends MenuBase {
constructor() {
super('advanceDisplay', ['ondown']);
this.selectedBtn = null;
this.getData();
this.getAllSpecials();
this.getSpecialIconData();
this.specialIconPage = 0;
}
drawContent() {
const ctx = this.createCanvas();
core.setTextAlign(ctx, 'center');
core.setTextBaseline(ctx, 'alphabetic');
core.fillRoundRect(ctx, 20, 70, core.__PIXELS__ - 40, 320, 5, "rgba(50,50,50,1)");
core.fillText(ctx, "设定敌人左下角显示的数据", 110, 90, 'white', '14px Verdana');
core.fillText(ctx, "设定敌人右上角显示的数据", 110, 190, 'white', '14px Verdana');
core.fillText(ctx, "设定特殊属性的代表字符", 110, 290, 'white', '14px Verdana');
this.getData();
this.setInfoName();
this.getSpecialIconData();
super.drawContent(ctx);
}
clear() {
super.clear();
const settingMenu = core.plugin.settingMenu;
if (settingMenu) {
settingMenu.beginListen();
settingMenu.pageList[settingMenu.currPage].beginListen();
}
}
getData() {
const defaultData = { leftdown: { 1: 'damage', 2: 'critical' }, rightup: {} };
this.data = core.getLocalStorage('displayData', defaultData);
}
setData(pos, index, infoName) {
this.data[pos][index] = infoName;
core.setLocalStorage('displayData', this.data);
this.setInfoName();
}
setInfoName() {
this.btnMap.forEach(btn => {
if (!(btn instanceof DisplayInfoBtn)) return;
const pos = btn.pos;
const index = btn.index;
const infoName = this.data[pos][index];
if (infoName) {
btn.infoName = infoName;
const name = infoNameMap[infoName];
btn.text = name;
}
else {
btn.infoName = null;
btn.text = '';
}
});
}
getAllSpecials() { // allSpecials是所有用到了的特殊属性的数组
let allSpecialsSet = new Set();
Object.values(core.material.enemys).forEach(enemy => {
const special = core.utils.parseSpecial(enemy.special);
allSpecialsSet = new Set([...allSpecialsSet, ...special]);
})
this.allSpecials = [...allSpecialsSet].sort((a, b) => a - b);
}
getSpecialIconData() {
const specialData = core.getLocalStorage('specialIconData', {});
this.specialIconData = specialData;
}
getCurrSpecialIconList(){
return this.allSpecials.slice(this.specialIconPage * 6,
this.specialIconPage * 6 + 6);
}
/** 更新每个按钮对应的文本,在翻页和修改内容时需要手动调用 */
setSpecialIconBtnText() {
const specialIconList = this.getCurrSpecialIconList();
for (let i = 0; i <= 5; i++) {
const key = 's' + (i + 1);
const btn = this.btnMap.get(key);
const index = this.specialIconPage * 6 + i;
if (index >= this.allSpecials.length) {
btn.text = '';
}
else {
const specialNum = this.allSpecials[index];
const specialIndexMap = core.enemys.getSpecialIndexMap();
const [key, name] = specialIndexMap[specialNum];
const icon = this.specialIconData[specialNum] || "无";
btn.text = `${key}:${name} ${icon}`;
}
}
}
setSpecialIconData(index) {
const specialIconList = this.getCurrSpecialIconList();
const specialNum = specialIconList[index];
if (!specialNum) return;
core.utils.myprompt('输入该特殊属性的代表字符', null, (value) => {
if (value.length > 1) value = value[0]; // 最多保留一位字符
this.specialIconData[specialNum] = value;
core.setLocalStorage('specialIconData', this.specialIconData);
this.setSpecialIconBtnText();
this.drawContent();
});
}
pageUp(){
if (this.specialIconPage * 6 + 6 < this.allSpecials.length) {
this.specialIconPage++;
this.setSpecialIconBtnText();
this.drawContent();
}
}
pageDown(){
if (this.specialIconPage > 0) {
this.specialIconPage--;
this.setSpecialIconBtnText();
this.drawContent();
}
}
}
function advanceDisplayFactory() {
const advanceDisplayMenu = new AdvanceDisplayMenu();
const exitBtn = new ExitBtn(370, 80, 16, 16, { radius: 1, lineOffsetX: 2, lineWidthX: 2 })
advanceDisplayMenu.registerBtn('exitBtn', exitBtn, () => {
advanceDisplayMenu.clear();
const settingMenu = core.plugin.settingMenu;
settingMenu.btnMap.forEach(btn => { btn.disable = false });
settingMenu.drawContent();
});
const btn1 = new DisplayInfoBtn(50, 100, 75, 20, 'leftdown', 1),
btn2 = new DisplayInfoBtn(50, 125, 75, 20, 'leftdown', 2),
btn3 = new DisplayInfoBtn(50, 150, 75, 20, 'leftdown', 3),
btn4 = new DisplayInfoBtn(50, 200, 75, 20, 'rightup', 1),
btn5 = new DisplayInfoBtn(50, 225, 75, 20, 'rightup', 2),
btn6 = new DisplayInfoBtn(50, 250, 75, 20, 'rightup', 3);
const infoNameList = Object.keys(infoNameMap);
const l = infoNameList.length;
const setNewInfo = function (infoName) {
return function () {
const btn = advanceDisplayMenu.selectedBtn;
if (!btn) return;
advanceDisplayMenu.setData(btn.pos, btn.index, infoName);
advanceDisplayMenu.btnMap.forEach((btn, key) => {
if (btn.key.startsWith("temp")) btn.disable = true;
});
advanceDisplayMenu.selectedBtn = null;
advanceDisplayMenu.drawContent();
}
}
for (let i = 0; i < 5; i++) {
const tempBtn = new RoundBtn(200, 100 + i * 25, 80, 20, infoNameMap[infoNameList[i]], { fillStyle: 'Azure' });
tempBtn.disable = true;
advanceDisplayMenu.registerBtn('temp' + i, tempBtn, setNewInfo(infoNameList[i]));
}
for (let i = 5; i < l; i++) {
const tempBtn = new RoundBtn(300, 100 + (i - 5) * 25, 80, 20, infoNameMap[infoNameList[i]], { fillStyle: 'Azure' });
tempBtn.disable = true;
advanceDisplayMenu.registerBtn('temp' + i, tempBtn, setNewInfo(infoNameList[i]));
}
const change = function (btn) {
return function () {
if (btn.infoName) {
advanceDisplayMenu.setData(btn.pos, btn.index, null);
}
else {
if (advanceDisplayMenu.selectedBtn && advanceDisplayMenu.selectedBtn === btn) {
// 点击左边刚点过的按钮会收起展开菜单
advanceDisplayMenu.btnMap.forEach((btn, key) => {
if (btn.key.startsWith("temp")) btn.disable = true;
});
advanceDisplayMenu.selectedBtn = null;
advanceDisplayMenu.drawContent();
} else {
advanceDisplayMenu.selectedBtn = btn;
advanceDisplayMenu.btnMap.forEach((btn, key) => {
if (btn.key.startsWith("temp")) btn.disable = false;
});
}
}
advanceDisplayMenu.drawContent();
}
}
advanceDisplayMenu.registerBtns([
['1', btn1, change(btn1)], ['2', btn2, change(btn2)], ['3', btn3, change(btn3)],
['4', btn4, change(btn4)], ['5', btn5, change(btn5)], ['6', btn6, change(btn6)],
]);
const config = { "font": "12px Verdana" };
advanceDisplayMenu.registerBtn('s1', new SpecialIconBtn(50, 300, 80, 20, "", config), advanceDisplayMenu.setSpecialIconData.bind(advanceDisplayMenu, 0));
advanceDisplayMenu.registerBtn('s2', new SpecialIconBtn(150, 300, 80, 20, "", config), advanceDisplayMenu.setSpecialIconData.bind(advanceDisplayMenu, 1));
advanceDisplayMenu.registerBtn('s3', new SpecialIconBtn(250, 300, 80, 20, "", config), advanceDisplayMenu.setSpecialIconData.bind(advanceDisplayMenu, 2));
advanceDisplayMenu.registerBtn('s4', new SpecialIconBtn(50, 330, 80, 20, "", config), advanceDisplayMenu.setSpecialIconData.bind(advanceDisplayMenu, 3));
advanceDisplayMenu.registerBtn('s5', new SpecialIconBtn(150, 330, 80, 20, "", config), advanceDisplayMenu.setSpecialIconData.bind(advanceDisplayMenu, 4));
advanceDisplayMenu.registerBtn('s6', new SpecialIconBtn(250, 330, 80, 20, "", config), advanceDisplayMenu.setSpecialIconData.bind(advanceDisplayMenu, 5));
advanceDisplayMenu.registerBtn('pageDown', new ArrowBtn(50, 360, 16, 16, 'left'),
advanceDisplayMenu.pageDown.bind(advanceDisplayMenu));
advanceDisplayMenu.registerBtn('pageUp', new ArrowBtn(320, 360, 16, 16, 'right'),
advanceDisplayMenu.pageUp.bind(advanceDisplayMenu));
advanceDisplayMenu.setSpecialIconBtnText();
return advanceDisplayMenu;
}
// #endregion
class PageChangeBtn extends RoundBtn { class PageChangeBtn extends RoundBtn {
constructor(x, y, w, h, text) { constructor(x, y, w, h, text) {