mirror of
https://github.com/unanmed/HumanBreak.git
synced 2025-01-18 20:09:27 +08:00
插件转为es模块
This commit is contained in:
parent
d56e54135a
commit
81f6815429
4
idea.md
4
idea.md
@ -28,14 +28,14 @@
|
||||
|
||||
#### 技能
|
||||
|
||||
闪避:每 M 回合闪避一次,减少 N%的伤害
|
||||
闪避:每 M 回合闪避一次,减少 N% 的伤害
|
||||
|
||||
## 机制
|
||||
|
||||
### 通用
|
||||
|
||||
- 实时天气
|
||||
- 成就系统
|
||||
- 成就系统(完成)
|
||||
- 装备合成、装备(孔)强化
|
||||
- 宝石目标设定
|
||||
- 自动宝物规划,选中两个或更多宝物后自动在本地图中规划出最优拾取路线,原则是尽量减少其余宝物的捡拾,自动切换主动技能,怪物造成的伤害最低的路线
|
||||
|
@ -5,9 +5,9 @@
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vue-tsc && vite build && ts-node-esm script/compress.ts",
|
||||
"build-gh": "vue-tsc && vite build --base=/HumanBreak/ && ts-node-esm script/compress.ts",
|
||||
"build-local": "vue-tsc && vite build --base=/ && ts-node-esm script/compress.ts",
|
||||
"build": "vue-tsc && vite build && ts-node-esm script/build.ts",
|
||||
"build-gh": "vue-tsc && vite build --base=/HumanBreak/ && ts-node-esm script/build.ts",
|
||||
"build-local": "vue-tsc && vite build --base=/ && ts-node-esm script/build.ts",
|
||||
"preview": "vite preview",
|
||||
"preview-node": "cd dist && node server.cjs",
|
||||
"update": "ts-node-esm script/update.ts",
|
||||
@ -42,6 +42,7 @@
|
||||
"form-data": "^4.0.0",
|
||||
"fs-extra": "^10.1.0",
|
||||
"less": "^4.1.3",
|
||||
"rollup": "^3.20.2",
|
||||
"terser": "^5.16.9",
|
||||
"ts-node": "^10.9.1",
|
||||
"typescript": "^4.9.5",
|
||||
|
@ -24,6 +24,7 @@ specifiers:
|
||||
lodash: ^4.17.21
|
||||
lz-string: ^1.5.0
|
||||
mutate-animate: ^1.1.1
|
||||
rollup: ^3.20.2
|
||||
terser: ^5.16.9
|
||||
three: ^0.149.0
|
||||
ts-node: ^10.9.1
|
||||
@ -61,10 +62,11 @@ devDependencies:
|
||||
form-data: 4.0.0
|
||||
fs-extra: 10.1.0
|
||||
less: 4.1.3
|
||||
rollup: 3.20.2
|
||||
terser: 5.16.9
|
||||
ts-node: 10.9.1_o6avl3oodj6mwqsx3rm2wfkgv4
|
||||
typescript: 4.9.5
|
||||
unplugin-vue-components: 0.22.12_vue@3.2.47
|
||||
unplugin-vue-components: 0.22.12_rollup@3.20.2+vue@3.2.47
|
||||
vite: 4.2.1_lu7yuwtv4qfbkrotoux232iypi
|
||||
vue-tsc: 1.2.0_typescript@4.9.5
|
||||
|
||||
@ -1620,7 +1622,7 @@ packages:
|
||||
rimraf: 3.0.2
|
||||
dev: true
|
||||
|
||||
/@rollup/pluginutils/5.0.2:
|
||||
/@rollup/pluginutils/5.0.2_rollup@3.20.2:
|
||||
resolution: {integrity: sha512-pTd9rIsP92h+B6wWwFbW8RkZv4hiR/xKsqre4SIuAOaOEQRxi0lqLke9k2/7WegC85GgUs9pjmOjCUi3In4vwA==}
|
||||
engines: {node: '>=14.0.0'}
|
||||
peerDependencies:
|
||||
@ -1632,6 +1634,7 @@ packages:
|
||||
'@types/estree': 1.0.0
|
||||
estree-walker: 2.0.2
|
||||
picomatch: 2.3.1
|
||||
rollup: 3.20.2
|
||||
dev: true
|
||||
|
||||
/@simonwep/pickr/1.8.2:
|
||||
@ -4399,7 +4402,7 @@ packages:
|
||||
engines: {node: '>= 10.0.0'}
|
||||
dev: true
|
||||
|
||||
/unplugin-vue-components/0.22.12_vue@3.2.47:
|
||||
/unplugin-vue-components/0.22.12_rollup@3.20.2+vue@3.2.47:
|
||||
resolution: {integrity: sha512-FxyzsuBvMCYPIk+8cgscGBQ345tvwVu+qY5IhE++eorkyvA4Z1TiD/HCiim+Kbqozl10i4K+z+NCa2WO2jexRA==}
|
||||
engines: {node: '>=14'}
|
||||
peerDependencies:
|
||||
@ -4410,7 +4413,7 @@ packages:
|
||||
optional: true
|
||||
dependencies:
|
||||
'@antfu/utils': 0.7.2
|
||||
'@rollup/pluginutils': 5.0.2
|
||||
'@rollup/pluginutils': 5.0.2_rollup@3.20.2
|
||||
chokidar: 3.5.3
|
||||
debug: 4.3.4
|
||||
fast-glob: 3.2.12
|
||||
|
@ -1,208 +1,198 @@
|
||||
///<reference path="../../../src/types/core.d.ts" />
|
||||
'use strict';
|
||||
export {};
|
||||
|
||||
(function () {
|
||||
// 创建新图层
|
||||
function createCanvas(name, zIndex) {
|
||||
if (!name) return;
|
||||
var canvas = document.createElement('canvas');
|
||||
canvas.id = name;
|
||||
canvas.className = 'gameCanvas';
|
||||
// 编辑器模式下设置zIndex会导致加入的图层覆盖优先级过高
|
||||
if (main.mode != 'editor') canvas.style.zIndex = zIndex || 0;
|
||||
// 将图层插入进游戏内容
|
||||
document.getElementById('gameDraw').appendChild(canvas);
|
||||
var ctx = canvas.getContext('2d');
|
||||
core.canvas[name] = ctx;
|
||||
// 创建新图层
|
||||
function createCanvas(name, zIndex) {
|
||||
if (!name) return;
|
||||
var canvas = document.createElement('canvas');
|
||||
canvas.id = name;
|
||||
canvas.className = 'gameCanvas';
|
||||
// 编辑器模式下设置zIndex会导致加入的图层覆盖优先级过高
|
||||
if (main.mode != 'editor') canvas.style.zIndex = zIndex || 0;
|
||||
// 将图层插入进游戏内容
|
||||
document.getElementById('gameDraw').appendChild(canvas);
|
||||
var ctx = canvas.getContext('2d');
|
||||
core.canvas[name] = ctx;
|
||||
|
||||
return canvas;
|
||||
return canvas;
|
||||
}
|
||||
|
||||
var bg2Canvas = createCanvas('bg2', 20);
|
||||
var fg2Canvas = createCanvas('fg2', 63);
|
||||
// 大地图适配
|
||||
core.bigmap.canvas = ['bg2', 'fg2', 'bg', 'event', 'event2', 'fg', 'damage'];
|
||||
core.initStatus.bg2maps = {};
|
||||
core.initStatus.fg2maps = {};
|
||||
|
||||
if (main.mode == 'editor') {
|
||||
/*插入编辑器的图层 不做此步新增图层无法在编辑器显示*/
|
||||
// 编辑器图层覆盖优先级 eui > efg > fg(前景层) > event2(48*32图块的事件层) > event(事件层) > bg(背景层)
|
||||
// 背景层2(bg2) 插入事件层(event)之前(即bg与event之间)
|
||||
document
|
||||
.getElementById('mapEdit')
|
||||
.insertBefore(bg2Canvas, document.getElementById('event'));
|
||||
// 前景层2(fg2) 插入编辑器前景(efg)之前(即fg之后)
|
||||
document
|
||||
.getElementById('mapEdit')
|
||||
.insertBefore(fg2Canvas, document.getElementById('ebm'));
|
||||
// 原本有三个图层 从4开始添加
|
||||
var num = 4;
|
||||
// 新增图层存入editor.dom中
|
||||
editor.dom.bg2c = core.canvas.bg2.canvas;
|
||||
editor.dom.bg2Ctx = core.canvas.bg2;
|
||||
editor.dom.fg2c = core.canvas.fg2.canvas;
|
||||
editor.dom.fg2Ctx = core.canvas.fg2;
|
||||
editor.dom.maps.push('bg2map', 'fg2map');
|
||||
editor.dom.canvas.push('bg2', 'fg2');
|
||||
|
||||
// 创建编辑器上的按钮
|
||||
var createCanvasBtn = name => {
|
||||
// 电脑端创建按钮
|
||||
var input = document.createElement('input');
|
||||
// layerMod4/layerMod5
|
||||
var id = 'layerMod' + num++;
|
||||
// bg2map/fg2map
|
||||
var value = name + 'map';
|
||||
input.type = 'radio';
|
||||
input.name = 'layerMod';
|
||||
input.id = id;
|
||||
input.value = value;
|
||||
editor.dom[id] = input;
|
||||
input.onchange = () => {
|
||||
editor.uifunctions.setLayerMod(value);
|
||||
};
|
||||
return input;
|
||||
};
|
||||
|
||||
var createCanvasBtn_mobile = name => {
|
||||
// 手机端往选择列表中添加子选项
|
||||
var input = document.createElement('option');
|
||||
var id = 'layerMod' + num++;
|
||||
var value = name + 'map';
|
||||
input.name = 'layerMod';
|
||||
input.value = value;
|
||||
editor.dom[id] = input;
|
||||
return input;
|
||||
};
|
||||
if (!editor.isMobile) {
|
||||
var input = createCanvasBtn('bg2');
|
||||
var input2 = createCanvasBtn('fg2');
|
||||
// 获取事件层及其父节点
|
||||
var child = document.getElementById('layerMod'),
|
||||
parent = child.parentNode;
|
||||
// 背景层2插入事件层前
|
||||
parent.insertBefore(input, child);
|
||||
// 不能直接更改背景层2的innerText 所以创建文本节点
|
||||
var txt = document.createTextNode('背2');
|
||||
// 插入事件层前(即新插入的背景层2前)
|
||||
parent.insertBefore(txt, child);
|
||||
// 向最后插入前景层2(即插入前景层后)
|
||||
parent.appendChild(input2);
|
||||
var txt2 = document.createTextNode('前2');
|
||||
parent.appendChild(txt2);
|
||||
} else {
|
||||
var input = createCanvasBtn_mobile('bg2');
|
||||
var input2 = createCanvasBtn_mobile('fg2');
|
||||
// 手机端因为是选项 所以可以直接改innerText
|
||||
input.innerText = '背景2';
|
||||
input2.innerText = '前景2';
|
||||
var parent = document.getElementById('layerMod');
|
||||
parent.insertBefore(input, parent.children[1]);
|
||||
parent.appendChild(input2);
|
||||
}
|
||||
|
||||
var bg2Canvas = createCanvas('bg2', 20);
|
||||
var fg2Canvas = createCanvas('fg2', 63);
|
||||
// 大地图适配
|
||||
core.bigmap.canvas = [
|
||||
'bg2',
|
||||
'fg2',
|
||||
'bg',
|
||||
'event',
|
||||
'event2',
|
||||
'fg',
|
||||
'damage'
|
||||
}
|
||||
core.maps._loadFloor_doNotCopy = function () {
|
||||
return [
|
||||
'firstArrive',
|
||||
'eachArrive',
|
||||
'blocks',
|
||||
'parallelDo',
|
||||
'map',
|
||||
'bgmap',
|
||||
'fgmap',
|
||||
'bg2map',
|
||||
'fg2map',
|
||||
'events',
|
||||
'changeFloor',
|
||||
'afterBattle',
|
||||
'afterGetItem',
|
||||
'afterOpenDoor',
|
||||
'cannotMove'
|
||||
];
|
||||
core.initStatus.bg2maps = {};
|
||||
core.initStatus.fg2maps = {};
|
||||
|
||||
if (main.mode == 'editor') {
|
||||
/*插入编辑器的图层 不做此步新增图层无法在编辑器显示*/
|
||||
// 编辑器图层覆盖优先级 eui > efg > fg(前景层) > event2(48*32图块的事件层) > event(事件层) > bg(背景层)
|
||||
// 背景层2(bg2) 插入事件层(event)之前(即bg与event之间)
|
||||
document
|
||||
.getElementById('mapEdit')
|
||||
.insertBefore(bg2Canvas, document.getElementById('event'));
|
||||
// 前景层2(fg2) 插入编辑器前景(efg)之前(即fg之后)
|
||||
document
|
||||
.getElementById('mapEdit')
|
||||
.insertBefore(fg2Canvas, document.getElementById('ebm'));
|
||||
// 原本有三个图层 从4开始添加
|
||||
var num = 4;
|
||||
// 新增图层存入editor.dom中
|
||||
editor.dom.bg2c = core.canvas.bg2.canvas;
|
||||
editor.dom.bg2Ctx = core.canvas.bg2;
|
||||
editor.dom.fg2c = core.canvas.fg2.canvas;
|
||||
editor.dom.fg2Ctx = core.canvas.fg2;
|
||||
editor.dom.maps.push('bg2map', 'fg2map');
|
||||
editor.dom.canvas.push('bg2', 'fg2');
|
||||
|
||||
// 创建编辑器上的按钮
|
||||
var createCanvasBtn = name => {
|
||||
// 电脑端创建按钮
|
||||
var input = document.createElement('input');
|
||||
// layerMod4/layerMod5
|
||||
var id = 'layerMod' + num++;
|
||||
// bg2map/fg2map
|
||||
var value = name + 'map';
|
||||
input.type = 'radio';
|
||||
input.name = 'layerMod';
|
||||
input.id = id;
|
||||
input.value = value;
|
||||
editor.dom[id] = input;
|
||||
input.onchange = () => {
|
||||
editor.uifunctions.setLayerMod(value);
|
||||
};
|
||||
return input;
|
||||
};
|
||||
|
||||
var createCanvasBtn_mobile = name => {
|
||||
// 手机端往选择列表中添加子选项
|
||||
var input = document.createElement('option');
|
||||
var id = 'layerMod' + num++;
|
||||
var value = name + 'map';
|
||||
input.name = 'layerMod';
|
||||
input.value = value;
|
||||
editor.dom[id] = input;
|
||||
return input;
|
||||
};
|
||||
if (!editor.isMobile) {
|
||||
var input = createCanvasBtn('bg2');
|
||||
var input2 = createCanvasBtn('fg2');
|
||||
// 获取事件层及其父节点
|
||||
var child = document.getElementById('layerMod'),
|
||||
parent = child.parentNode;
|
||||
// 背景层2插入事件层前
|
||||
parent.insertBefore(input, child);
|
||||
// 不能直接更改背景层2的innerText 所以创建文本节点
|
||||
var txt = document.createTextNode('背2');
|
||||
// 插入事件层前(即新插入的背景层2前)
|
||||
parent.insertBefore(txt, child);
|
||||
// 向最后插入前景层2(即插入前景层后)
|
||||
parent.appendChild(input2);
|
||||
var txt2 = document.createTextNode('前2');
|
||||
parent.appendChild(txt2);
|
||||
} else {
|
||||
var input = createCanvasBtn_mobile('bg2');
|
||||
var input2 = createCanvasBtn_mobile('fg2');
|
||||
// 手机端因为是选项 所以可以直接改innerText
|
||||
input.innerText = '背景2';
|
||||
input2.innerText = '前景2';
|
||||
var parent = document.getElementById('layerMod');
|
||||
parent.insertBefore(input, parent.children[1]);
|
||||
parent.appendChild(input2);
|
||||
}
|
||||
};
|
||||
////// 绘制背景和前景层 //////
|
||||
core.maps._drawBg_draw = function (floorId, toDrawCtx, cacheCtx, config) {
|
||||
config.ctx = cacheCtx;
|
||||
core.maps._drawBg_drawBackground(floorId, config);
|
||||
// ------ 调整这两行的顺序来控制是先绘制贴图还是先绘制背景图块;后绘制的覆盖先绘制的。
|
||||
core.maps._drawFloorImages(
|
||||
floorId,
|
||||
config.ctx,
|
||||
'bg',
|
||||
null,
|
||||
null,
|
||||
config.onMap
|
||||
);
|
||||
core.maps._drawBgFgMap(floorId, 'bg', config);
|
||||
if (config.onMap) {
|
||||
core.drawImage(
|
||||
toDrawCtx,
|
||||
cacheCtx.canvas,
|
||||
core.bigmap.v2 ? -32 : 0,
|
||||
core.bigmap.v2 ? -32 : 0
|
||||
);
|
||||
core.clearMap('bg2');
|
||||
core.clearMap(cacheCtx);
|
||||
}
|
||||
core.maps._loadFloor_doNotCopy = function () {
|
||||
return [
|
||||
'firstArrive',
|
||||
'eachArrive',
|
||||
'blocks',
|
||||
'parallelDo',
|
||||
'map',
|
||||
'bgmap',
|
||||
'fgmap',
|
||||
'bg2map',
|
||||
'fg2map',
|
||||
'events',
|
||||
'changeFloor',
|
||||
'afterBattle',
|
||||
'afterGetItem',
|
||||
'afterOpenDoor',
|
||||
'cannotMove'
|
||||
];
|
||||
};
|
||||
////// 绘制背景和前景层 //////
|
||||
core.maps._drawBg_draw = function (floorId, toDrawCtx, cacheCtx, config) {
|
||||
config.ctx = cacheCtx;
|
||||
core.maps._drawBg_drawBackground(floorId, config);
|
||||
// ------ 调整这两行的顺序来控制是先绘制贴图还是先绘制背景图块;后绘制的覆盖先绘制的。
|
||||
core.maps._drawFloorImages(
|
||||
floorId,
|
||||
config.ctx,
|
||||
'bg',
|
||||
null,
|
||||
null,
|
||||
config.onMap
|
||||
core.maps._drawBgFgMap(floorId, 'bg2', config);
|
||||
if (config.onMap)
|
||||
core.drawImage(
|
||||
'bg2',
|
||||
cacheCtx.canvas,
|
||||
core.bigmap.v2 ? -32 : 0,
|
||||
core.bigmap.v2 ? -32 : 0
|
||||
);
|
||||
core.maps._drawBgFgMap(floorId, 'bg', config);
|
||||
if (config.onMap) {
|
||||
core.drawImage(
|
||||
toDrawCtx,
|
||||
cacheCtx.canvas,
|
||||
core.bigmap.v2 ? -32 : 0,
|
||||
core.bigmap.v2 ? -32 : 0
|
||||
);
|
||||
core.clearMap('bg2');
|
||||
core.clearMap(cacheCtx);
|
||||
}
|
||||
core.maps._drawBgFgMap(floorId, 'bg2', config);
|
||||
if (config.onMap)
|
||||
core.drawImage(
|
||||
'bg2',
|
||||
cacheCtx.canvas,
|
||||
core.bigmap.v2 ? -32 : 0,
|
||||
core.bigmap.v2 ? -32 : 0
|
||||
);
|
||||
config.ctx = toDrawCtx;
|
||||
};
|
||||
core.maps._drawFg_draw = function (floorId, toDrawCtx, cacheCtx, config) {
|
||||
config.ctx = cacheCtx;
|
||||
// ------ 调整这两行的顺序来控制是先绘制贴图还是先绘制前景图块;后绘制的覆盖先绘制的。
|
||||
core.maps._drawFloorImages(
|
||||
floorId,
|
||||
config.ctx,
|
||||
'fg',
|
||||
null,
|
||||
null,
|
||||
config.onMap
|
||||
config.ctx = toDrawCtx;
|
||||
};
|
||||
core.maps._drawFg_draw = function (floorId, toDrawCtx, cacheCtx, config) {
|
||||
config.ctx = cacheCtx;
|
||||
// ------ 调整这两行的顺序来控制是先绘制贴图还是先绘制前景图块;后绘制的覆盖先绘制的。
|
||||
core.maps._drawFloorImages(
|
||||
floorId,
|
||||
config.ctx,
|
||||
'fg',
|
||||
null,
|
||||
null,
|
||||
config.onMap
|
||||
);
|
||||
core.maps._drawBgFgMap(floorId, 'fg', config);
|
||||
if (config.onMap) {
|
||||
core.drawImage(
|
||||
toDrawCtx,
|
||||
cacheCtx.canvas,
|
||||
core.bigmap.v2 ? -32 : 0,
|
||||
core.bigmap.v2 ? -32 : 0
|
||||
);
|
||||
core.maps._drawBgFgMap(floorId, 'fg', config);
|
||||
if (config.onMap) {
|
||||
core.drawImage(
|
||||
toDrawCtx,
|
||||
cacheCtx.canvas,
|
||||
core.bigmap.v2 ? -32 : 0,
|
||||
core.bigmap.v2 ? -32 : 0
|
||||
);
|
||||
core.clearMap('fg2');
|
||||
core.clearMap(cacheCtx);
|
||||
}
|
||||
core.maps._drawBgFgMap(floorId, 'fg2', config);
|
||||
if (config.onMap)
|
||||
core.drawImage(
|
||||
'fg2',
|
||||
cacheCtx.canvas,
|
||||
core.bigmap.v2 ? -32 : 0,
|
||||
core.bigmap.v2 ? -32 : 0
|
||||
);
|
||||
config.ctx = toDrawCtx;
|
||||
core.clearMap('fg2');
|
||||
core.clearMap(cacheCtx);
|
||||
}
|
||||
core.maps._drawBgFgMap(floorId, 'fg2', config);
|
||||
if (config.onMap)
|
||||
core.drawImage(
|
||||
'fg2',
|
||||
cacheCtx.canvas,
|
||||
core.bigmap.v2 ? -32 : 0,
|
||||
core.bigmap.v2 ? -32 : 0
|
||||
);
|
||||
config.ctx = toDrawCtx;
|
||||
};
|
||||
////// 移动判定 //////
|
||||
core.maps._generateMovableArray_arrays = function (floorId) {
|
||||
return {
|
||||
bgArray: this.getBgMapArray(floorId),
|
||||
fgArray: this.getFgMapArray(floorId),
|
||||
eventArray: this.getMapArray(floorId),
|
||||
bg2Array: this._getBgFgMapArray('bg2', floorId),
|
||||
fg2Array: this._getBgFgMapArray('fg2', floorId)
|
||||
};
|
||||
////// 移动判定 //////
|
||||
core.maps._generateMovableArray_arrays = function (floorId) {
|
||||
return {
|
||||
bgArray: this.getBgMapArray(floorId),
|
||||
fgArray: this.getFgMapArray(floorId),
|
||||
eventArray: this.getMapArray(floorId),
|
||||
bg2Array: this._getBgFgMapArray('bg2', floorId),
|
||||
fg2Array: this._getBgFgMapArray('fg2', floorId)
|
||||
};
|
||||
};
|
||||
})();
|
||||
};
|
||||
|
@ -1,57 +1,54 @@
|
||||
///<reference path="../../../src/types/core.d.ts" />
|
||||
'use strict';
|
||||
|
||||
(function () {
|
||||
/**
|
||||
* 绘制光环范围
|
||||
* @param {CanvasRenderingContext2D} ctx
|
||||
* @param {boolean} onMap
|
||||
*/
|
||||
function drawHalo(ctx, onMap) {
|
||||
if (main.replayChecking) return;
|
||||
if (!core.getLocalStorage('showHalo', true)) return;
|
||||
const halo = core.status.checkBlock.halo;
|
||||
ctx.save();
|
||||
for (const [loc, range] of Object.entries(halo)) {
|
||||
const [x, y] = loc.split(',').map(v => parseInt(v));
|
||||
for (const r of range) {
|
||||
const [type, value, color, border] = r.split(':');
|
||||
if (type === 'square') {
|
||||
// 正方形光环
|
||||
const n = parseInt(value);
|
||||
const r = Math.floor(n / 2);
|
||||
let left = x - r,
|
||||
right = x + r,
|
||||
top = y - r,
|
||||
bottom = y + r;
|
||||
if (onMap && core.bigmap.v2) {
|
||||
left -= core.bigmap.posX;
|
||||
top -= core.bigmap.posY;
|
||||
right -= core.bigmap.posX;
|
||||
bottom -= core.bigmap.posY;
|
||||
if (
|
||||
right < -1 ||
|
||||
left > core._PX_ / 32 + 1 ||
|
||||
top < -1 ||
|
||||
bottom > core._PY_ / 32 + 1
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
/**
|
||||
* 绘制光环范围
|
||||
* @param {CanvasRenderingContext2D} ctx
|
||||
* @param {boolean} onMap
|
||||
*/
|
||||
export function drawHalo(ctx, onMap) {
|
||||
if (main.replayChecking) return;
|
||||
if (!core.getLocalStorage('showHalo', true)) return;
|
||||
const halo = core.status.checkBlock.halo;
|
||||
ctx.save();
|
||||
for (const [loc, range] of Object.entries(halo)) {
|
||||
const [x, y] = loc.split(',').map(v => parseInt(v));
|
||||
for (const r of range) {
|
||||
const [type, value, color, border] = r.split(':');
|
||||
if (type === 'square') {
|
||||
// 正方形光环
|
||||
const n = parseInt(value);
|
||||
const r = Math.floor(n / 2);
|
||||
let left = x - r,
|
||||
right = x + r,
|
||||
top = y - r,
|
||||
bottom = y + r;
|
||||
if (onMap && core.bigmap.v2) {
|
||||
left -= core.bigmap.posX;
|
||||
top -= core.bigmap.posY;
|
||||
right -= core.bigmap.posX;
|
||||
bottom -= core.bigmap.posY;
|
||||
if (
|
||||
right < -1 ||
|
||||
left > core._PX_ / 32 + 1 ||
|
||||
top < -1 ||
|
||||
bottom > core._PY_ / 32 + 1
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
ctx.fillStyle = color;
|
||||
ctx.strokeStyle = border ?? color;
|
||||
ctx.lineWidth = 1;
|
||||
ctx.globalAlpha = 0.1;
|
||||
ctx.fillRect(left * 32, top * 32, n * 32, n * 32);
|
||||
ctx.globalAlpha = 0.6;
|
||||
ctx.strokeRect(left * 32, top * 32, n * 32, n * 32);
|
||||
}
|
||||
ctx.fillStyle = color;
|
||||
ctx.strokeStyle = border ?? color;
|
||||
ctx.lineWidth = 1;
|
||||
ctx.globalAlpha = 0.1;
|
||||
ctx.fillRect(left * 32, top * 32, n * 32, n * 32);
|
||||
ctx.globalAlpha = 0.6;
|
||||
ctx.strokeRect(left * 32, top * 32, n * 32, n * 32);
|
||||
}
|
||||
}
|
||||
ctx.restore();
|
||||
}
|
||||
ctx.restore();
|
||||
}
|
||||
|
||||
core.plugin.halo = {
|
||||
drawHalo
|
||||
};
|
||||
})();
|
||||
core.plugin.halo = {
|
||||
drawHalo
|
||||
};
|
||||
|
@ -1,87 +1,84 @@
|
||||
///<reference path="../../../src/types/core.d.ts" />
|
||||
'use strict';
|
||||
|
||||
(function () {
|
||||
/**
|
||||
* 获取勇士在某一点的属性
|
||||
* @param {keyof HeroStatus | 'all'} name
|
||||
* @param {number} x
|
||||
* @param {number} y
|
||||
* @param {FloorIds} floorId
|
||||
*/
|
||||
function getHeroStatusOn(name, x, y, floorId) {
|
||||
return getRealStatusOf(core.status.hero, name, x, y, floorId);
|
||||
/**
|
||||
* 获取勇士在某一点的属性
|
||||
* @param {keyof HeroStatus | 'all'} name
|
||||
* @param {number} x
|
||||
* @param {number} y
|
||||
* @param {FloorIds} floorId
|
||||
*/
|
||||
export function getHeroStatusOn(name, x, y, floorId) {
|
||||
return getHeroStatusOf(core.status.hero, name, x, y, floorId);
|
||||
}
|
||||
|
||||
export function getHeroStatusOf(status, name, x, y, floorId) {
|
||||
return getRealStatus(status, name, x, y, floorId);
|
||||
}
|
||||
|
||||
function getRealStatus(status, name, x, y, floorId) {
|
||||
if (name instanceof Array) {
|
||||
return Object.fromEntries(
|
||||
name.map(v => [
|
||||
v,
|
||||
v !== 'all' && getRealStatus(status, v, x, y, floorId)
|
||||
])
|
||||
);
|
||||
}
|
||||
|
||||
function getHeroStatusOf(status, name, x, y, floorId) {
|
||||
return getRealStatus(status, name, x, y, floorId);
|
||||
if (name === 'all') {
|
||||
return Object.fromEntries(
|
||||
Object.keys(core.status.hero).map(v => [
|
||||
v,
|
||||
v !== 'all' && getRealStatus(status, v, x, y, floorId)
|
||||
])
|
||||
);
|
||||
}
|
||||
|
||||
function getRealStatus(status, name, x, y, floorId) {
|
||||
if (name instanceof Array) {
|
||||
return Object.fromEntries(
|
||||
name.map(v => [
|
||||
v,
|
||||
v !== 'all' && getRealStatus(status, v, x, y, floorId)
|
||||
])
|
||||
);
|
||||
}
|
||||
|
||||
if (name === 'all') {
|
||||
return Object.fromEntries(
|
||||
Object.keys(core.status.hero).map(v => [
|
||||
v,
|
||||
v !== 'all' && getRealStatus(status, v, x, y, floorId)
|
||||
])
|
||||
);
|
||||
}
|
||||
|
||||
let s = status?.[name] ?? core.status.hero[name];
|
||||
if (s === null || s === void 0) {
|
||||
throw new ReferenceError(
|
||||
`Wrong hero status property name is delivered: ${name}`
|
||||
);
|
||||
}
|
||||
|
||||
x ??= core.status.hero.loc.x;
|
||||
y ??= core.status.hero.loc.y;
|
||||
floorId ??= core.status.floorId;
|
||||
|
||||
// 永夜、极昼
|
||||
if (name === 'atk' || name === 'def') {
|
||||
s += window.flags?.[`night_${floorId}`] ?? 0;
|
||||
}
|
||||
|
||||
// 技能
|
||||
if (flags.bladeOn && flags.blade) {
|
||||
const level = core.plugin.skillTree.getSkillLevel(2);
|
||||
if (name === 'atk') {
|
||||
s *= 1 + 0.1 * level;
|
||||
}
|
||||
if (name === 'def') {
|
||||
s *= 1 - 0.1 * level;
|
||||
}
|
||||
}
|
||||
if (flags.shield && flags.shieldOn) {
|
||||
const level = core.plugin.skillTree.getSkillLevel(10);
|
||||
if (name === 'atk') {
|
||||
s *= 1 - 0.1 * level;
|
||||
}
|
||||
if (name === 'def') {
|
||||
s *= 1 + 0.1 * level;
|
||||
}
|
||||
}
|
||||
|
||||
// buff
|
||||
if (typeof s === 'number') s *= core.getBuff(name);
|
||||
|
||||
// 取整
|
||||
if (typeof s === 'number') s = Math.floor(s);
|
||||
return s;
|
||||
let s = status?.[name] ?? core.status.hero[name];
|
||||
if (s === null || s === void 0) {
|
||||
throw new ReferenceError(
|
||||
`Wrong hero status property name is delivered: ${name}`
|
||||
);
|
||||
}
|
||||
|
||||
core.plugin.hero = {
|
||||
getHeroStatusOf,
|
||||
getHeroStatusOn
|
||||
};
|
||||
})();
|
||||
x ??= core.status.hero.loc.x;
|
||||
y ??= core.status.hero.loc.y;
|
||||
floorId ??= core.status.floorId;
|
||||
|
||||
// 永夜、极昼
|
||||
if (name === 'atk' || name === 'def') {
|
||||
s += window.flags?.[`night_${floorId}`] ?? 0;
|
||||
}
|
||||
|
||||
// 技能
|
||||
if (flags.bladeOn && flags.blade) {
|
||||
const level = core.plugin.skillTree.getSkillLevel(2);
|
||||
if (name === 'atk') {
|
||||
s *= 1 + 0.1 * level;
|
||||
}
|
||||
if (name === 'def') {
|
||||
s *= 1 - 0.1 * level;
|
||||
}
|
||||
}
|
||||
if (flags.shield && flags.shieldOn) {
|
||||
const level = core.plugin.skillTree.getSkillLevel(10);
|
||||
if (name === 'atk') {
|
||||
s *= 1 - 0.1 * level;
|
||||
}
|
||||
if (name === 'def') {
|
||||
s *= 1 + 0.1 * level;
|
||||
}
|
||||
}
|
||||
|
||||
// buff
|
||||
if (typeof s === 'number') s *= core.getBuff(name);
|
||||
|
||||
// 取整
|
||||
if (typeof s === 'number') s = Math.floor(s);
|
||||
return s;
|
||||
}
|
||||
|
||||
core.plugin.hero = {
|
||||
getHeroStatusOf,
|
||||
getHeroStatusOn
|
||||
};
|
||||
|
@ -1,60 +1,58 @@
|
||||
///<reference path="../../../src/types/core.d.ts" />
|
||||
'use strict';
|
||||
export {};
|
||||
|
||||
(function () {
|
||||
['up', 'down', 'left', 'right'].forEach(one => {
|
||||
// 指定中间帧动画
|
||||
core.material.icons.hero[one].midFoot = 2;
|
||||
});
|
||||
['up', 'down', 'left', 'right'].forEach(one => {
|
||||
// 指定中间帧动画
|
||||
core.material.icons.hero[one].midFoot = 2;
|
||||
});
|
||||
|
||||
var heroMoving = timestamp => {
|
||||
if (core.status.heroMoving <= 0) return;
|
||||
if (timestamp - core.animateFrame.moveTime > core.values.moveSpeed) {
|
||||
core.animateFrame.leftLeg++;
|
||||
core.animateFrame.moveTime = timestamp;
|
||||
}
|
||||
core.drawHero(
|
||||
['stop', 'leftFoot', 'midFoot', 'rightFoot'][
|
||||
core.animateFrame.leftLeg % 4
|
||||
],
|
||||
4 * core.status.heroMoving
|
||||
);
|
||||
};
|
||||
core.registerAnimationFrame('heroMoving', true, heroMoving);
|
||||
var heroMoving = timestamp => {
|
||||
if (core.status.heroMoving <= 0) return;
|
||||
if (timestamp - core.animateFrame.moveTime > core.values.moveSpeed) {
|
||||
core.animateFrame.leftLeg++;
|
||||
core.animateFrame.moveTime = timestamp;
|
||||
}
|
||||
core.drawHero(
|
||||
['stop', 'leftFoot', 'midFoot', 'rightFoot'][
|
||||
core.animateFrame.leftLeg % 4
|
||||
],
|
||||
4 * core.status.heroMoving
|
||||
);
|
||||
};
|
||||
core.registerAnimationFrame('heroMoving', true, heroMoving);
|
||||
|
||||
core.events._eventMoveHero_moving = function (step, moveSteps) {
|
||||
var curr = moveSteps[0];
|
||||
var direction = curr[0],
|
||||
x = core.getHeroLoc('x'),
|
||||
y = core.getHeroLoc('y');
|
||||
// ------ 前进/后退
|
||||
var o = direction == 'backward' ? -1 : 1;
|
||||
if (direction == 'forward' || direction == 'backward')
|
||||
direction = core.getHeroLoc('direction');
|
||||
var faceDirection = direction;
|
||||
if (direction == 'leftup' || direction == 'leftdown')
|
||||
faceDirection = 'left';
|
||||
if (direction == 'rightup' || direction == 'rightdown')
|
||||
faceDirection = 'right';
|
||||
core.setHeroLoc('direction', direction);
|
||||
if (curr[1] <= 0) {
|
||||
core.setHeroLoc('direction', faceDirection);
|
||||
moveSteps.shift();
|
||||
return true;
|
||||
}
|
||||
if (step <= 4) core.drawHero('stop', 4 * o * step);
|
||||
else if (step <= 8) core.drawHero('leftFoot', 4 * o * step);
|
||||
else if (step <= 12) core.drawHero('midFoot', 4 * o * (step - 8));
|
||||
else if (step <= 16) core.drawHero('rightFoot', 4 * o * (step - 8)); // if (step == 8) {
|
||||
if (step == 8 || step == 16) {
|
||||
core.setHeroLoc('x', x + o * core.utils.scan2[direction].x, true);
|
||||
core.setHeroLoc('y', y + o * core.utils.scan2[direction].y, true);
|
||||
core.updateFollowers();
|
||||
curr[1]--;
|
||||
if (curr[1] <= 0) moveSteps.shift();
|
||||
core.setHeroLoc('direction', faceDirection);
|
||||
return step == 16;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
})();
|
||||
core.events._eventMoveHero_moving = function (step, moveSteps) {
|
||||
var curr = moveSteps[0];
|
||||
var direction = curr[0],
|
||||
x = core.getHeroLoc('x'),
|
||||
y = core.getHeroLoc('y');
|
||||
// ------ 前进/后退
|
||||
var o = direction == 'backward' ? -1 : 1;
|
||||
if (direction == 'forward' || direction == 'backward')
|
||||
direction = core.getHeroLoc('direction');
|
||||
var faceDirection = direction;
|
||||
if (direction == 'leftup' || direction == 'leftdown')
|
||||
faceDirection = 'left';
|
||||
if (direction == 'rightup' || direction == 'rightdown')
|
||||
faceDirection = 'right';
|
||||
core.setHeroLoc('direction', direction);
|
||||
if (curr[1] <= 0) {
|
||||
core.setHeroLoc('direction', faceDirection);
|
||||
moveSteps.shift();
|
||||
return true;
|
||||
}
|
||||
if (step <= 4) core.drawHero('stop', 4 * o * step);
|
||||
else if (step <= 8) core.drawHero('leftFoot', 4 * o * step);
|
||||
else if (step <= 12) core.drawHero('midFoot', 4 * o * (step - 8));
|
||||
else if (step <= 16) core.drawHero('rightFoot', 4 * o * (step - 8)); // if (step == 8) {
|
||||
if (step == 8 || step == 16) {
|
||||
core.setHeroLoc('x', x + o * core.utils.scan2[direction].x, true);
|
||||
core.setHeroLoc('y', y + o * core.utils.scan2[direction].y, true);
|
||||
core.updateFollowers();
|
||||
curr[1]--;
|
||||
if (curr[1] <= 0) moveSteps.shift();
|
||||
core.setHeroLoc('direction', faceDirection);
|
||||
return step == 16;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
@ -1,5 +1,5 @@
|
||||
///<reference path="../../../src/types/core.d.ts" />
|
||||
'use strict';
|
||||
export {};
|
||||
|
||||
(function () {
|
||||
if (main.mode !== 'play' || main.replayChecking) return;
|
||||
|
32
public/project/plugin/index.js
Normal file
32
public/project/plugin/index.js
Normal file
@ -0,0 +1,32 @@
|
||||
import './fiveLayer';
|
||||
import './heroFourFrames';
|
||||
import './hotReload';
|
||||
import './itemDetail';
|
||||
import './popup';
|
||||
import './replay';
|
||||
import './ui';
|
||||
import * as halo from './halo';
|
||||
import * as hero from './hero';
|
||||
import * as loopMap from './loopMap';
|
||||
import * as remainEnemy from './remainEnemy';
|
||||
import * as removeMap from './removeMap';
|
||||
import * as shop from './shop';
|
||||
import * as skill from './skills';
|
||||
import * as skillTree from './skillTree';
|
||||
import * as study from './study';
|
||||
import * as towerBoss from './towerBoss';
|
||||
import * as utils from './utils';
|
||||
|
||||
export {
|
||||
halo,
|
||||
hero,
|
||||
loopMap,
|
||||
remainEnemy,
|
||||
removeMap,
|
||||
shop,
|
||||
skill,
|
||||
skillTree,
|
||||
study,
|
||||
towerBoss,
|
||||
utils
|
||||
};
|
@ -1,130 +1,128 @@
|
||||
///<reference path="../../../src/types/core.d.ts" />
|
||||
'use strict';
|
||||
export {};
|
||||
|
||||
(function () {
|
||||
core.control.updateDamage = function (floorId, ctx) {
|
||||
floorId = floorId || core.status.floorId;
|
||||
if (!floorId || core.status.gameOver || main.mode != 'play') return;
|
||||
const onMap = ctx == null;
|
||||
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;
|
||||
// 没有怪物手册
|
||||
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);
|
||||
getItemDetail(floorId, onMap); // 宝石血瓶详细信息
|
||||
this.drawDamage(ctx);
|
||||
};
|
||||
|
||||
// 获取宝石信息 并绘制
|
||||
function getItemDetail(floorId, onMap) {
|
||||
if (!core.getFlag('itemDetail')) return;
|
||||
floorId ??= core.status.thisMap.floorId;
|
||||
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;
|
||||
}
|
||||
this._updateDamage_damage(floorId, onMap);
|
||||
this._updateDamage_extraDamage(floorId, onMap);
|
||||
getItemDetail(floorId, onMap); // 宝石血瓶详细信息
|
||||
this.drawDamage(ctx);
|
||||
};
|
||||
core.status.hero = new Proxy(hero, handler);
|
||||
|
||||
// 获取宝石信息 并绘制
|
||||
function getItemDetail(floorId, onMap) {
|
||||
if (!core.getFlag('itemDetail')) return;
|
||||
floorId ??= core.status.thisMap.floorId;
|
||||
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' || block.disable) return;
|
||||
const x = block.x,
|
||||
y = block.y;
|
||||
// v2优化,只绘制范围内的部分
|
||||
if (onMap && core.bigmap.v2) {
|
||||
if (
|
||||
x < core.bigmap.posX - core.bigmap.extend ||
|
||||
x > core.bigmap.posX + core._PX_ + core.bigmap.extend ||
|
||||
y < core.bigmap.posY - core.bigmap.extend ||
|
||||
y > core.bigmap.posY + core._PY_ + core.bigmap.extend
|
||||
) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
diff = {};
|
||||
const id = block.event.id;
|
||||
const item = core.material.items[id];
|
||||
if (item.cls === 'equips') {
|
||||
// 装备也显示
|
||||
const diff = core.clone(item.equip.value ?? {});
|
||||
const per = item.equip.percentage ?? {};
|
||||
for (const name in per) {
|
||||
diff[name + 'per'] = per[name].toString() + '%';
|
||||
}
|
||||
drawItemDetail(diff, x, y);
|
||||
core.status.maps[floorId].blocks.forEach(function (block) {
|
||||
if (block.event.cls !== 'items' || block.disable) return;
|
||||
const x = block.x,
|
||||
y = block.y;
|
||||
// v2优化,只绘制范围内的部分
|
||||
if (onMap && core.bigmap.v2) {
|
||||
if (
|
||||
x < core.bigmap.posX - core.bigmap.extend ||
|
||||
x > core.bigmap.posX + core._PX_ + core.bigmap.extend ||
|
||||
y < core.bigmap.posY - core.bigmap.extend ||
|
||||
y > core.bigmap.posY + core._PY_ + core.bigmap.extend
|
||||
) {
|
||||
return;
|
||||
}
|
||||
// 跟数据统计原理一样 执行效果 前后比较
|
||||
core.setFlag('__statistics__', true);
|
||||
try {
|
||||
eval(item.itemEffect);
|
||||
} catch (error) {}
|
||||
drawItemDetail(diff, x, y);
|
||||
});
|
||||
core.status.hero = before;
|
||||
window.hero = before;
|
||||
window.flags = before.flags;
|
||||
}
|
||||
|
||||
// 绘制
|
||||
function drawItemDetail(diff, x, y) {
|
||||
const px = 32 * x + 2,
|
||||
py = 32 * y + 31;
|
||||
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++;
|
||||
}
|
||||
diff = {};
|
||||
const id = block.event.id;
|
||||
const item = core.material.items[id];
|
||||
if (item.cls === 'equips') {
|
||||
// 装备也显示
|
||||
const diff = core.clone(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.hero = before;
|
||||
window.hero = before;
|
||||
window.flags = before.flags;
|
||||
}
|
||||
|
||||
// 绘制
|
||||
function drawItemDetail(diff, x, y) {
|
||||
const px = 32 * x + 2,
|
||||
py = 32 * y + 31;
|
||||
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++;
|
||||
}
|
||||
})();
|
||||
}
|
||||
|
@ -1,240 +1,230 @@
|
||||
///<reference path="../../../src/types/core.d.ts" />
|
||||
'use strict';
|
||||
import { slide } from './utils';
|
||||
|
||||
(function () {
|
||||
const { slide } = core.plugin.utils;
|
||||
const list = ['tower6'];
|
||||
const list = ['tower6'];
|
||||
|
||||
/**
|
||||
* 设置循环地图的偏移量
|
||||
* @param {number} offset 横向偏移量
|
||||
* @param {FloorIds} floorId
|
||||
*/
|
||||
function setLoopMap(offset, floorId) {
|
||||
const floor = core.status.maps[floorId];
|
||||
if (offset < 9) {
|
||||
moveMap(floor.width - 17, floorId);
|
||||
}
|
||||
if (offset > floor.width - 9) {
|
||||
moveMap(17 - floor.width, floorId);
|
||||
/**
|
||||
* 设置循环地图的偏移量
|
||||
* @param {number} offset 横向偏移量
|
||||
* @param {FloorIds} floorId
|
||||
*/
|
||||
function setLoopMap(offset, floorId) {
|
||||
const floor = core.status.maps[floorId];
|
||||
if (offset < 9) {
|
||||
moveMap(floor.width - 17, floorId);
|
||||
}
|
||||
if (offset > floor.width - 9) {
|
||||
moveMap(17 - floor.width, floorId);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 当勇士移动时自动设置循环地图
|
||||
* @param {FloorIds} floorId
|
||||
*/
|
||||
function autoSetLoopMap(floorId) {
|
||||
setLoopMap(core.status.hero.loc.x, floorId);
|
||||
}
|
||||
|
||||
export function checkLoopMap() {
|
||||
if (isLoopMap(core.status.floorId)) {
|
||||
autoSetLoopMap(core.status.floorId);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 移动地图
|
||||
* @param {number} delta
|
||||
* @param {FloorIds} floorId
|
||||
*/
|
||||
function moveMap(delta, floorId) {
|
||||
core.extractBlocks(floorId);
|
||||
const floor = core.status.maps[floorId];
|
||||
core.setHeroLoc('x', core.status.hero.loc.x + delta);
|
||||
flags[`loop_${floorId}`] += delta;
|
||||
flags[`loop_${floorId}`] %= floor.width;
|
||||
const origin = floor.blocks.slice();
|
||||
for (let i = 0; i < origin.length; i++) {
|
||||
core.removeBlockByIndex(0, floorId);
|
||||
core.removeGlobalAnimate(origin[i].x, origin[i].y);
|
||||
}
|
||||
origin.forEach(v => {
|
||||
let to = v.x + delta;
|
||||
if (to >= floor.width) to -= floor.width;
|
||||
if (to < 0) to += floor.width;
|
||||
core.setBlock(v.id, to, v.y, floorId, true);
|
||||
core.setMapBlockDisabled(floorId, to, v.y, false);
|
||||
});
|
||||
core.drawMap();
|
||||
core.drawHero();
|
||||
}
|
||||
|
||||
function isLoopMap(floorId) {
|
||||
return list.includes(floorId);
|
||||
}
|
||||
|
||||
events.prototype._sys_changeFloor = function (data, callback) {
|
||||
data = data.event.data;
|
||||
let heroLoc = {};
|
||||
if (isLoopMap(data.floorId)) {
|
||||
const floor = core.status.maps[data.floorId];
|
||||
flags[`loop_${data.floorId}`] ??= 0;
|
||||
let tx = data.loc[0] + flags[`loop_${data.floorId}`];
|
||||
tx %= floor.width;
|
||||
if (tx < 0) tx += floor.width;
|
||||
heroLoc = {
|
||||
x: tx,
|
||||
y: data.loc[1]
|
||||
};
|
||||
} else if (data.loc) heroLoc = { x: data.loc[0], y: data.loc[1] };
|
||||
if (data.direction) heroLoc.direction = data.direction;
|
||||
if (core.status.event.id != 'action') core.status.event.id = null;
|
||||
core.changeFloor(data.floorId, data.stair, heroLoc, data.time, function () {
|
||||
core.replay();
|
||||
if (callback) callback();
|
||||
});
|
||||
};
|
||||
|
||||
events.prototype.trigger = function (x, y, callback) {
|
||||
var _executeCallback = function () {
|
||||
// 因为trigger之后还有可能触发其他同步脚本(比如阻激夹域检测)
|
||||
// 所以这里强制callback被异步触发
|
||||
if (callback) {
|
||||
setTimeout(callback, 1); // +1是为了录像检测系统
|
||||
}
|
||||
return;
|
||||
};
|
||||
if (core.status.gameOver) return _executeCallback();
|
||||
if (core.status.event.id == 'action') {
|
||||
core.insertAction(
|
||||
{
|
||||
type: 'function',
|
||||
function:
|
||||
'function () { core.events._trigger_inAction(' +
|
||||
x +
|
||||
',' +
|
||||
y +
|
||||
'); }',
|
||||
async: true
|
||||
},
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
true
|
||||
);
|
||||
return _executeCallback();
|
||||
}
|
||||
if (core.status.event.id) return _executeCallback();
|
||||
|
||||
/**
|
||||
* 当勇士移动时自动设置循环地图
|
||||
* @param {FloorIds} floorId
|
||||
*/
|
||||
function autoSetLoopMap(floorId) {
|
||||
setLoopMap(core.status.hero.loc.x, floorId);
|
||||
}
|
||||
|
||||
function checkLoopMap() {
|
||||
if (isLoopMap(core.status.floorId)) {
|
||||
autoSetLoopMap(core.status.floorId);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 移动地图
|
||||
* @param {number} delta
|
||||
* @param {FloorIds} floorId
|
||||
*/
|
||||
function moveMap(delta, floorId) {
|
||||
core.extractBlocks(floorId);
|
||||
const floor = core.status.maps[floorId];
|
||||
core.setHeroLoc('x', core.status.hero.loc.x + delta);
|
||||
flags[`loop_${floorId}`] += delta;
|
||||
flags[`loop_${floorId}`] %= floor.width;
|
||||
const origin = floor.blocks.slice();
|
||||
for (let i = 0; i < origin.length; i++) {
|
||||
core.removeBlockByIndex(0, floorId);
|
||||
core.removeGlobalAnimate(origin[i].x, origin[i].y);
|
||||
}
|
||||
origin.forEach(v => {
|
||||
let to = v.x + delta;
|
||||
if (to >= floor.width) to -= floor.width;
|
||||
if (to < 0) to += floor.width;
|
||||
core.setBlock(v.id, to, v.y, floorId, true);
|
||||
core.setMapBlockDisabled(floorId, to, v.y, false);
|
||||
});
|
||||
core.drawMap();
|
||||
core.drawHero();
|
||||
}
|
||||
|
||||
function isLoopMap(floorId) {
|
||||
return list.includes(floorId);
|
||||
}
|
||||
|
||||
events.prototype._sys_changeFloor = function (data, callback) {
|
||||
data = data.event.data;
|
||||
let heroLoc = {};
|
||||
if (isLoopMap(data.floorId)) {
|
||||
const floor = core.status.maps[data.floorId];
|
||||
flags[`loop_${data.floorId}`] ??= 0;
|
||||
let tx = data.loc[0] + flags[`loop_${data.floorId}`];
|
||||
let block = core.getBlock(x, y);
|
||||
const id = core.status.floorId;
|
||||
const loop = isLoopMap(id);
|
||||
if (loop && flags[`loop_${id}`] !== 0) {
|
||||
if (block && block.event.trigger === 'changeFloor') {
|
||||
delete block.event.trigger;
|
||||
core.maps._addInfo(block);
|
||||
} else {
|
||||
const floor = core.status.maps[id];
|
||||
let tx = x - flags[`loop_${id}`];
|
||||
tx %= floor.width;
|
||||
if (tx < 0) tx += floor.width;
|
||||
heroLoc = {
|
||||
x: tx,
|
||||
y: data.loc[1]
|
||||
};
|
||||
} else if (data.loc) heroLoc = { x: data.loc[0], y: data.loc[1] };
|
||||
if (data.direction) heroLoc.direction = data.direction;
|
||||
if (core.status.event.id != 'action') core.status.event.id = null;
|
||||
core.changeFloor(
|
||||
data.floorId,
|
||||
data.stair,
|
||||
heroLoc,
|
||||
data.time,
|
||||
function () {
|
||||
core.replay();
|
||||
if (callback) callback();
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
events.prototype.trigger = function (x, y, callback) {
|
||||
var _executeCallback = function () {
|
||||
// 因为trigger之后还有可能触发其他同步脚本(比如阻激夹域检测)
|
||||
// 所以这里强制callback被异步触发
|
||||
if (callback) {
|
||||
setTimeout(callback, 1); // +1是为了录像检测系统
|
||||
}
|
||||
return;
|
||||
};
|
||||
if (core.status.gameOver) return _executeCallback();
|
||||
if (core.status.event.id == 'action') {
|
||||
core.insertAction(
|
||||
{
|
||||
type: 'function',
|
||||
function:
|
||||
'function () { core.events._trigger_inAction(' +
|
||||
x +
|
||||
',' +
|
||||
y +
|
||||
'); }',
|
||||
async: true
|
||||
},
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
true
|
||||
);
|
||||
return _executeCallback();
|
||||
}
|
||||
if (core.status.event.id) return _executeCallback();
|
||||
|
||||
let block = core.getBlock(x, y);
|
||||
const id = core.status.floorId;
|
||||
const loop = isLoopMap(id);
|
||||
if (loop && flags[`loop_${id}`] !== 0) {
|
||||
if (block && block.event.trigger === 'changeFloor') {
|
||||
delete block.event.trigger;
|
||||
core.maps._addInfo(block);
|
||||
} else {
|
||||
const floor = core.status.maps[id];
|
||||
let tx = x - flags[`loop_${id}`];
|
||||
tx %= floor.width;
|
||||
if (tx < 0) tx += floor.width;
|
||||
const c = core.floors[id].changeFloor[`${tx},${y}`];
|
||||
if (c) {
|
||||
const b = { event: {}, x: tx, y };
|
||||
b.event.data = c;
|
||||
b.event.trigger = 'changeFloor';
|
||||
block = b;
|
||||
}
|
||||
const c = core.floors[id].changeFloor[`${tx},${y}`];
|
||||
if (c) {
|
||||
const b = { event: {}, x: tx, y };
|
||||
b.event.data = c;
|
||||
b.event.trigger = 'changeFloor';
|
||||
block = b;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (block == null) return _executeCallback();
|
||||
if (block == null) return _executeCallback();
|
||||
|
||||
// 执行该点的脚本
|
||||
if (block.event.script) {
|
||||
core.clearRouteFolding();
|
||||
try {
|
||||
eval(block.event.script);
|
||||
} catch (ee) {
|
||||
console.error(ee);
|
||||
}
|
||||
// 执行该点的脚本
|
||||
if (block.event.script) {
|
||||
core.clearRouteFolding();
|
||||
try {
|
||||
eval(block.event.script);
|
||||
} catch (ee) {
|
||||
console.error(ee);
|
||||
}
|
||||
}
|
||||
|
||||
// 碰触事件
|
||||
if (block.event.event) {
|
||||
core.clearRouteFolding();
|
||||
core.insertAction(block.event.event, block.x, block.y);
|
||||
// 不再执行该点的系统事件
|
||||
return _executeCallback();
|
||||
}
|
||||
|
||||
if (block.event.trigger && block.event.trigger != 'null') {
|
||||
var noPass = block.event.noPass,
|
||||
trigger = block.event.trigger;
|
||||
if (noPass) core.clearAutomaticRouteNode(x, y);
|
||||
|
||||
// 转换楼层能否穿透
|
||||
if (
|
||||
trigger == 'changeFloor' &&
|
||||
!noPass &&
|
||||
this._trigger_ignoreChangeFloor(block) &&
|
||||
!loop
|
||||
)
|
||||
return _executeCallback();
|
||||
core.status.automaticRoute.moveDirectly = false;
|
||||
this.doSystemEvent(trigger, block);
|
||||
}
|
||||
// 碰触事件
|
||||
if (block.event.event) {
|
||||
core.clearRouteFolding();
|
||||
core.insertAction(block.event.event, block.x, block.y);
|
||||
// 不再执行该点的系统事件
|
||||
return _executeCallback();
|
||||
};
|
||||
}
|
||||
|
||||
maps.prototype._getBgFgMapArray = function (name, floorId, noCache) {
|
||||
floorId = floorId || core.status.floorId;
|
||||
if (!floorId) return [];
|
||||
var width = core.floors[floorId].width;
|
||||
var height = core.floors[floorId].height;
|
||||
if (block.event.trigger && block.event.trigger != 'null') {
|
||||
var noPass = block.event.noPass,
|
||||
trigger = block.event.trigger;
|
||||
if (noPass) core.clearAutomaticRouteNode(x, y);
|
||||
|
||||
if (!noCache && core.status[name + 'maps'][floorId])
|
||||
return core.status[name + 'maps'][floorId];
|
||||
// 转换楼层能否穿透
|
||||
if (
|
||||
trigger == 'changeFloor' &&
|
||||
!noPass &&
|
||||
this._trigger_ignoreChangeFloor(block) &&
|
||||
!loop
|
||||
)
|
||||
return _executeCallback();
|
||||
core.status.automaticRoute.moveDirectly = false;
|
||||
this.doSystemEvent(trigger, block);
|
||||
}
|
||||
return _executeCallback();
|
||||
};
|
||||
|
||||
var arr =
|
||||
main.mode == 'editor' &&
|
||||
!(window.editor && editor.uievent && editor.uievent.isOpen)
|
||||
? core.cloneArray(editor[name + 'map'])
|
||||
: null;
|
||||
if (arr == null)
|
||||
arr = core.cloneArray(core.floors[floorId][name + 'map'] || []);
|
||||
maps.prototype._getBgFgMapArray = function (name, floorId, noCache) {
|
||||
floorId = floorId || core.status.floorId;
|
||||
if (!floorId) return [];
|
||||
var width = core.floors[floorId].width;
|
||||
var height = core.floors[floorId].height;
|
||||
|
||||
if (isLoopMap(floorId) && window.flags) {
|
||||
flags[`loop_${floorId}`] ??= 0;
|
||||
arr.forEach(v => {
|
||||
slide(v, flags[`loop_${floorId}`] % width);
|
||||
});
|
||||
}
|
||||
if (!noCache && core.status[name + 'maps'][floorId])
|
||||
return core.status[name + 'maps'][floorId];
|
||||
|
||||
for (var y = 0; y < height; ++y) {
|
||||
if (arr[y] == null) arr[y] = Array(width).fill(0);
|
||||
}
|
||||
(core.getFlag('__' + name + 'v__', {})[floorId] || []).forEach(
|
||||
function (one) {
|
||||
arr[one[1]][one[0]] = one[2] || 0;
|
||||
}
|
||||
);
|
||||
(core.getFlag('__' + name + 'd__', {})[floorId] || []).forEach(
|
||||
function (one) {
|
||||
arr[one[1]][one[0]] = 0;
|
||||
}
|
||||
);
|
||||
if (main.mode == 'editor') {
|
||||
for (var x = 0; x < width; x++) {
|
||||
for (var y = 0; y < height; y++) {
|
||||
arr[y][x] = arr[y][x].idnum || arr[y][x] || 0;
|
||||
}
|
||||
var arr =
|
||||
main.mode == 'editor' &&
|
||||
!(window.editor && editor.uievent && editor.uievent.isOpen)
|
||||
? core.cloneArray(editor[name + 'map'])
|
||||
: null;
|
||||
if (arr == null)
|
||||
arr = core.cloneArray(core.floors[floorId][name + 'map'] || []);
|
||||
|
||||
if (isLoopMap(floorId) && window.flags) {
|
||||
flags[`loop_${floorId}`] ??= 0;
|
||||
arr.forEach(v => {
|
||||
slide(v, flags[`loop_${floorId}`] % width);
|
||||
});
|
||||
}
|
||||
|
||||
for (var y = 0; y < height; ++y) {
|
||||
if (arr[y] == null) arr[y] = Array(width).fill(0);
|
||||
}
|
||||
(core.getFlag('__' + name + 'v__', {})[floorId] || []).forEach(function (
|
||||
one
|
||||
) {
|
||||
arr[one[1]][one[0]] = one[2] || 0;
|
||||
});
|
||||
(core.getFlag('__' + name + 'd__', {})[floorId] || []).forEach(function (
|
||||
one
|
||||
) {
|
||||
arr[one[1]][one[0]] = 0;
|
||||
});
|
||||
if (main.mode == 'editor') {
|
||||
for (var x = 0; x < width; x++) {
|
||||
for (var y = 0; y < height; y++) {
|
||||
arr[y][x] = arr[y][x].idnum || arr[y][x] || 0;
|
||||
}
|
||||
}
|
||||
if (core.status[name + 'maps'])
|
||||
core.status[name + 'maps'][floorId] = arr;
|
||||
return arr;
|
||||
};
|
||||
}
|
||||
if (core.status[name + 'maps']) core.status[name + 'maps'][floorId] = arr;
|
||||
return arr;
|
||||
};
|
||||
|
||||
core.plugin.loopMap = {
|
||||
checkLoopMap
|
||||
};
|
||||
})();
|
||||
core.plugin.loopMap = {
|
||||
checkLoopMap
|
||||
};
|
||||
|
@ -1,124 +1,120 @@
|
||||
///<reference path="../../../src/types/core.d.ts" />
|
||||
'use strict';
|
||||
export {};
|
||||
|
||||
(function () {
|
||||
// 伤害弹出
|
||||
// 复写阻激夹域检测
|
||||
control.prototype.checkBlock = function (forceMockery) {
|
||||
var x = core.getHeroLoc('x'),
|
||||
y = core.getHeroLoc('y'),
|
||||
loc = x + ',' + y;
|
||||
var damage = core.status.checkBlock.damage[loc];
|
||||
if (damage) {
|
||||
if (!main.replayChecking)
|
||||
core.addPop(
|
||||
(x - core.bigmap.offsetX / 32) * 32 + 12,
|
||||
(y - core.bigmap.offsetY / 32) * 32 + 20,
|
||||
-damage.toString()
|
||||
);
|
||||
core.status.hero.hp -= damage;
|
||||
var text =
|
||||
Object.keys(core.status.checkBlock.type[loc] || {}).join(
|
||||
','
|
||||
) || '伤害';
|
||||
core.drawTip('受到' + text + damage + '点');
|
||||
core.drawHeroAnimate('zone');
|
||||
this._checkBlock_disableQuickShop();
|
||||
core.status.hero.statistics.extraDamage += damage;
|
||||
if (core.status.hero.hp <= 0) {
|
||||
core.status.hero.hp = 0;
|
||||
core.updateStatusBar();
|
||||
core.events.lose();
|
||||
return;
|
||||
} else {
|
||||
core.updateStatusBar();
|
||||
}
|
||||
}
|
||||
this._checkBlock_repulse(core.status.checkBlock.repulse[loc]);
|
||||
checkMockery(loc, forceMockery);
|
||||
};
|
||||
|
||||
control.prototype.moveHero = function (direction, callback) {
|
||||
// 如果正在移动,直接return
|
||||
if (core.status.heroMoving != 0) return;
|
||||
if (core.isset(direction)) core.setHeroLoc('direction', direction);
|
||||
|
||||
const nx = core.nextX();
|
||||
const ny = core.nextY();
|
||||
if (core.status.checkBlock.mockery[`${nx},${ny}`]) {
|
||||
core.autosave();
|
||||
}
|
||||
|
||||
if (callback) return this.moveAction(callback);
|
||||
this._moveHero_moving();
|
||||
};
|
||||
|
||||
/**
|
||||
* 电摇嘲讽
|
||||
* @param {LocString} loc
|
||||
* @param {boolean} force
|
||||
*/
|
||||
function checkMockery(loc, force) {
|
||||
if (core.status.lockControl && !force) return;
|
||||
const mockery = core.status.checkBlock.mockery[loc];
|
||||
if (mockery) {
|
||||
mockery.sort((a, b) => (a[0] === b[0] ? a[1] - b[1] : a[0] - b[0]));
|
||||
const action = [];
|
||||
const [tx, ty] = mockery[0];
|
||||
let { x, y } = core.status.hero.loc;
|
||||
const dir =
|
||||
x > tx ? 'left' : x < tx ? 'right' : y > ty ? 'up' : 'down';
|
||||
const { x: dx, y: dy } = core.utils.scan[dir];
|
||||
|
||||
action.push({ type: 'changePos', direction: dir });
|
||||
const blocks = core.getMapBlocksObj();
|
||||
while (1) {
|
||||
x += dx;
|
||||
y += dy;
|
||||
const block = blocks[`${x},${y}`];
|
||||
if (block) {
|
||||
block.event.cls === '';
|
||||
if (
|
||||
[
|
||||
'animates',
|
||||
'autotile',
|
||||
'tileset',
|
||||
'npcs',
|
||||
'npc48'
|
||||
].includes(block.event.cls)
|
||||
) {
|
||||
action.push(
|
||||
{
|
||||
type: 'hide',
|
||||
loc: [[x, y]],
|
||||
remove: true,
|
||||
time: 0
|
||||
},
|
||||
{
|
||||
type: 'function',
|
||||
function: `function() { core.removeGlobalAnimate(${x}, ${y}) }`
|
||||
},
|
||||
{
|
||||
type: 'animate',
|
||||
name: 'hand',
|
||||
loc: [x, y],
|
||||
async: true
|
||||
}
|
||||
);
|
||||
}
|
||||
if (block.event.cls.startsWith('enemy')) {
|
||||
action.push({ type: 'moveAction' });
|
||||
}
|
||||
}
|
||||
action.push({ type: 'moveAction' });
|
||||
if (x === tx && y === ty) break;
|
||||
}
|
||||
action.push({
|
||||
type: 'function',
|
||||
function: `function() { core.checkBlock(true); }`
|
||||
});
|
||||
action.push({ type: 'stopAsync' });
|
||||
core.insertAction(action);
|
||||
// 伤害弹出
|
||||
// 复写阻激夹域检测
|
||||
control.prototype.checkBlock = function (forceMockery) {
|
||||
var x = core.getHeroLoc('x'),
|
||||
y = core.getHeroLoc('y'),
|
||||
loc = x + ',' + y;
|
||||
var damage = core.status.checkBlock.damage[loc];
|
||||
if (damage) {
|
||||
if (!main.replayChecking)
|
||||
core.addPop(
|
||||
(x - core.bigmap.offsetX / 32) * 32 + 12,
|
||||
(y - core.bigmap.offsetY / 32) * 32 + 20,
|
||||
-damage.toString()
|
||||
);
|
||||
core.status.hero.hp -= damage;
|
||||
var text =
|
||||
Object.keys(core.status.checkBlock.type[loc] || {}).join(',') ||
|
||||
'伤害';
|
||||
core.drawTip('受到' + text + damage + '点');
|
||||
core.drawHeroAnimate('zone');
|
||||
this._checkBlock_disableQuickShop();
|
||||
core.status.hero.statistics.extraDamage += damage;
|
||||
if (core.status.hero.hp <= 0) {
|
||||
core.status.hero.hp = 0;
|
||||
core.updateStatusBar();
|
||||
core.events.lose();
|
||||
return;
|
||||
} else {
|
||||
core.updateStatusBar();
|
||||
}
|
||||
}
|
||||
})();
|
||||
this._checkBlock_repulse(core.status.checkBlock.repulse[loc]);
|
||||
checkMockery(loc, forceMockery);
|
||||
};
|
||||
|
||||
control.prototype.moveHero = function (direction, callback) {
|
||||
// 如果正在移动,直接return
|
||||
if (core.status.heroMoving != 0) return;
|
||||
if (core.isset(direction)) core.setHeroLoc('direction', direction);
|
||||
|
||||
const nx = core.nextX();
|
||||
const ny = core.nextY();
|
||||
if (core.status.checkBlock.mockery[`${nx},${ny}`]) {
|
||||
core.autosave();
|
||||
}
|
||||
|
||||
if (callback) return this.moveAction(callback);
|
||||
this._moveHero_moving();
|
||||
};
|
||||
|
||||
/**
|
||||
* 电摇嘲讽
|
||||
* @param {LocString} loc
|
||||
* @param {boolean} force
|
||||
*/
|
||||
function checkMockery(loc, force) {
|
||||
if (core.status.lockControl && !force) return;
|
||||
const mockery = core.status.checkBlock.mockery[loc];
|
||||
if (mockery) {
|
||||
mockery.sort((a, b) => (a[0] === b[0] ? a[1] - b[1] : a[0] - b[0]));
|
||||
const action = [];
|
||||
const [tx, ty] = mockery[0];
|
||||
let { x, y } = core.status.hero.loc;
|
||||
const dir = x > tx ? 'left' : x < tx ? 'right' : y > ty ? 'up' : 'down';
|
||||
const { x: dx, y: dy } = core.utils.scan[dir];
|
||||
|
||||
action.push({ type: 'changePos', direction: dir });
|
||||
const blocks = core.getMapBlocksObj();
|
||||
while (1) {
|
||||
x += dx;
|
||||
y += dy;
|
||||
const block = blocks[`${x},${y}`];
|
||||
if (block) {
|
||||
block.event.cls === '';
|
||||
if (
|
||||
[
|
||||
'animates',
|
||||
'autotile',
|
||||
'tileset',
|
||||
'npcs',
|
||||
'npc48'
|
||||
].includes(block.event.cls)
|
||||
) {
|
||||
action.push(
|
||||
{
|
||||
type: 'hide',
|
||||
loc: [[x, y]],
|
||||
remove: true,
|
||||
time: 0
|
||||
},
|
||||
{
|
||||
type: 'function',
|
||||
function: `function() { core.removeGlobalAnimate(${x}, ${y}) }`
|
||||
},
|
||||
{
|
||||
type: 'animate',
|
||||
name: 'hand',
|
||||
loc: [x, y],
|
||||
async: true
|
||||
}
|
||||
);
|
||||
}
|
||||
if (block.event.cls.startsWith('enemy')) {
|
||||
action.push({ type: 'moveAction' });
|
||||
}
|
||||
}
|
||||
action.push({ type: 'moveAction' });
|
||||
if (x === tx && y === ty) break;
|
||||
}
|
||||
action.push({
|
||||
type: 'function',
|
||||
function: `function() { core.checkBlock(true); }`
|
||||
});
|
||||
action.push({ type: 'stopAsync' });
|
||||
core.insertAction(action);
|
||||
}
|
||||
}
|
||||
|
@ -1,76 +1,72 @@
|
||||
///<reference path="../../../src/types/core.d.ts" />
|
||||
'use strict';
|
||||
|
||||
(function () {
|
||||
/**
|
||||
* 检查漏怪
|
||||
* @param {FloorIds[]} floorIds
|
||||
*/
|
||||
export function checkRemainEnemy(floorIds) {
|
||||
/**
|
||||
* 检查漏怪
|
||||
* @param {FloorIds[]} floorIds
|
||||
* @type {Record<FloorIds, {loc: LocArr, id: EnemyIds}[]>}
|
||||
*/
|
||||
function checkRemainEnemy(floorIds) {
|
||||
/**
|
||||
* @type {Record<FloorIds, {loc: LocArr, id: EnemyIds}[]>}
|
||||
*/
|
||||
const enemy = {};
|
||||
floorIds.forEach(v => {
|
||||
core.extractBlocks(v);
|
||||
const blocks = core.status.maps[v].blocks;
|
||||
blocks.forEach(block => {
|
||||
if (!block.event.cls.startsWith('enemy') || block.disable)
|
||||
return;
|
||||
/**
|
||||
* @type {EnemyIds}
|
||||
*/
|
||||
const id = block.event.id;
|
||||
enemy[v] ??= [];
|
||||
const info = enemy[v];
|
||||
info.push({ loc: [block.x, block.y], id });
|
||||
});
|
||||
const enemy = {};
|
||||
floorIds.forEach(v => {
|
||||
core.extractBlocks(v);
|
||||
const blocks = core.status.maps[v].blocks;
|
||||
blocks.forEach(block => {
|
||||
if (!block.event.cls.startsWith('enemy') || block.disable) return;
|
||||
/**
|
||||
* @type {EnemyIds}
|
||||
*/
|
||||
const id = block.event.id;
|
||||
enemy[v] ??= [];
|
||||
const info = enemy[v];
|
||||
info.push({ loc: [block.x, block.y], id });
|
||||
});
|
||||
return enemy;
|
||||
}
|
||||
});
|
||||
return enemy;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取剩余怪物字符串
|
||||
* @param {FloorIds[]} floorIds
|
||||
*/
|
||||
function getRemainEnemyString(floorIds) {
|
||||
const enemy = checkRemainEnemy(floorIds);
|
||||
const str = [];
|
||||
let now = [];
|
||||
for (const floor in enemy) {
|
||||
/**
|
||||
* @type {{loc: LocArr, id: EnemyIds}[]}
|
||||
*/
|
||||
const all = enemy[floor];
|
||||
/**
|
||||
* @type {Record<EnemyIds, number>}
|
||||
*/
|
||||
const remain = {};
|
||||
all.forEach(v => {
|
||||
const id = v.id;
|
||||
remain[id] ??= 0;
|
||||
remain[id]++;
|
||||
});
|
||||
const title = core.status.maps[floor].title;
|
||||
for (const id in remain) {
|
||||
const name = core.material.enemys[id].name;
|
||||
now.push(`${title}(${floor}): ${name} * ${remain[id]}`);
|
||||
if (now.length === 10) {
|
||||
str.push(now.join('\n'));
|
||||
now = [];
|
||||
}
|
||||
/**
|
||||
* 获取剩余怪物字符串
|
||||
* @param {FloorIds[]} floorIds
|
||||
*/
|
||||
export function getRemainEnemyString(floorIds) {
|
||||
const enemy = checkRemainEnemy(floorIds);
|
||||
const str = [];
|
||||
let now = [];
|
||||
for (const floor in enemy) {
|
||||
/**
|
||||
* @type {{loc: LocArr, id: EnemyIds}[]}
|
||||
*/
|
||||
const all = enemy[floor];
|
||||
/**
|
||||
* @type {Record<EnemyIds, number>}
|
||||
*/
|
||||
const remain = {};
|
||||
all.forEach(v => {
|
||||
const id = v.id;
|
||||
remain[id] ??= 0;
|
||||
remain[id]++;
|
||||
});
|
||||
const title = core.status.maps[floor].title;
|
||||
for (const id in remain) {
|
||||
const name = core.material.enemys[id].name;
|
||||
now.push(`${title}(${floor}): ${name} * ${remain[id]}`);
|
||||
if (now.length === 10) {
|
||||
str.push(now.join('\n'));
|
||||
now = [];
|
||||
}
|
||||
}
|
||||
if (now.length > 0) {
|
||||
str.push(now.join('\n'));
|
||||
str[0] = `当前剩余怪物:\n${str[0]}`;
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
if (now.length > 0) {
|
||||
str.push(now.join('\n'));
|
||||
str[0] = `当前剩余怪物:\n${str[0]}`;
|
||||
}
|
||||
|
||||
core.plugin.remainEnemy = {
|
||||
checkRemainEnemy,
|
||||
getRemainEnemyString
|
||||
};
|
||||
})();
|
||||
return str;
|
||||
}
|
||||
|
||||
core.plugin.remainEnemy = {
|
||||
checkRemainEnemy,
|
||||
getRemainEnemyString
|
||||
};
|
||||
|
@ -1,118 +1,115 @@
|
||||
///<reference path="../../../src/types/core.d.ts" />
|
||||
'use strict';
|
||||
|
||||
(function () {
|
||||
function removeMaps(fromId, toId, force) {
|
||||
toId = toId || fromId;
|
||||
var fromIndex = core.floorIds.indexOf(fromId),
|
||||
toIndex = core.floorIds.indexOf(toId);
|
||||
if (toIndex < 0) toIndex = core.floorIds.length - 1;
|
||||
flags.__visited__ = flags.__visited__ || {};
|
||||
flags.__removed__ = flags.__removed__ || [];
|
||||
flags.__disabled__ = flags.__disabled__ || {};
|
||||
flags.__leaveLoc__ = flags.__leaveLoc__ || {};
|
||||
flags.__forceDelete__ ??= {};
|
||||
let deleted = false;
|
||||
for (var i = fromIndex; i <= toIndex; ++i) {
|
||||
var floorId = core.floorIds[i];
|
||||
if (core.status.maps[floorId].deleted) continue;
|
||||
delete flags.__visited__[floorId];
|
||||
flags.__removed__.push(floorId);
|
||||
delete flags.__disabled__[floorId];
|
||||
delete flags.__leaveLoc__[floorId];
|
||||
(core.status.autoEvents || []).forEach(event => {
|
||||
if (event.floorId == floorId && event.currentFloor) {
|
||||
core.autoEventExecuting(event.symbol, false);
|
||||
core.autoEventExecuted(event.symbol, false);
|
||||
}
|
||||
});
|
||||
core.status.maps[floorId].deleted = true;
|
||||
core.status.maps[floorId].canFlyTo = false;
|
||||
core.status.maps[floorId].canFlyFrom = false;
|
||||
core.status.maps[floorId].cannotViewMap = true;
|
||||
if (force) {
|
||||
core.status.maps[floorId].forceDelete = true;
|
||||
flags.__forceDelete__[floorId] = true;
|
||||
}
|
||||
deleteFlags(floorId);
|
||||
deleted = true;
|
||||
}
|
||||
if (deleted && !main.replayChecking) {
|
||||
core.splitArea();
|
||||
}
|
||||
}
|
||||
|
||||
function deleteFlags(floorId) {
|
||||
delete flags[`jump_${floorId}`];
|
||||
delete flags[`inte_${floorId}`];
|
||||
delete flags[`loop_${floorId}`];
|
||||
delete flags[`melt_${floorId}`];
|
||||
delete flags[`night_${floorId}`];
|
||||
}
|
||||
|
||||
// 恢复楼层
|
||||
// core.plugin.removeMap.resumeMaps("MT1", "MT300") 恢复MT1~MT300之间的全部层
|
||||
// core.plugin.removeMap.resumeMaps("MT10") 只恢复MT10层
|
||||
function resumeMaps(fromId, toId) {
|
||||
toId = toId || fromId;
|
||||
var fromIndex = core.floorIds.indexOf(fromId),
|
||||
toIndex = core.floorIds.indexOf(toId);
|
||||
if (toIndex < 0) toIndex = core.floorIds.length - 1;
|
||||
flags.__removed__ = flags.__removed__ || [];
|
||||
for (var i = fromIndex; i <= toIndex; ++i) {
|
||||
var floorId = core.floorIds[i];
|
||||
if (!core.status.maps[floorId].deleted) continue;
|
||||
if (
|
||||
core.status.maps[floorId].forceDelete ||
|
||||
flags.__forceDelete__[floorId]
|
||||
)
|
||||
continue;
|
||||
flags.__removed__ = flags.__removed__.filter(f => {
|
||||
return f != floorId;
|
||||
});
|
||||
core.status.maps[floorId] = core.loadFloor(floorId);
|
||||
}
|
||||
}
|
||||
|
||||
// 分区砍层相关
|
||||
var inAnyPartition = floorId => {
|
||||
var inPartition = false;
|
||||
(core.floorPartitions || []).forEach(floor => {
|
||||
var fromIndex = core.floorIds.indexOf(floor[0]);
|
||||
var toIndex = core.floorIds.indexOf(floor[1]);
|
||||
var index = core.floorIds.indexOf(floorId);
|
||||
if (fromIndex < 0 || index < 0) return;
|
||||
if (toIndex < 0) toIndex = core.floorIds.length - 1;
|
||||
if (index >= fromIndex && index <= toIndex) inPartition = true;
|
||||
});
|
||||
return inPartition;
|
||||
};
|
||||
|
||||
// 分区砍层
|
||||
function autoRemoveMaps(floorId) {
|
||||
if (main.mode != 'play' || !inAnyPartition(floorId)) return;
|
||||
// 根据分区信息自动砍层与恢复
|
||||
(core.floorPartitions || []).forEach(floor => {
|
||||
var fromIndex = core.floorIds.indexOf(floor[0]);
|
||||
var toIndex = core.floorIds.indexOf(floor[1]);
|
||||
var index = core.floorIds.indexOf(floorId);
|
||||
if (fromIndex < 0 || index < 0) return;
|
||||
if (toIndex < 0) toIndex = core.floorIds.length - 1;
|
||||
if (index >= fromIndex && index <= toIndex) {
|
||||
core.plugin.removeMap.resumeMaps(
|
||||
core.floorIds[fromIndex],
|
||||
core.floorIds[toIndex]
|
||||
);
|
||||
} else {
|
||||
removeMaps(core.floorIds[fromIndex], core.floorIds[toIndex]);
|
||||
export function removeMaps(fromId, toId, force) {
|
||||
toId = toId || fromId;
|
||||
var fromIndex = core.floorIds.indexOf(fromId),
|
||||
toIndex = core.floorIds.indexOf(toId);
|
||||
if (toIndex < 0) toIndex = core.floorIds.length - 1;
|
||||
flags.__visited__ = flags.__visited__ || {};
|
||||
flags.__removed__ = flags.__removed__ || [];
|
||||
flags.__disabled__ = flags.__disabled__ || {};
|
||||
flags.__leaveLoc__ = flags.__leaveLoc__ || {};
|
||||
flags.__forceDelete__ ??= {};
|
||||
let deleted = false;
|
||||
for (var i = fromIndex; i <= toIndex; ++i) {
|
||||
var floorId = core.floorIds[i];
|
||||
if (core.status.maps[floorId].deleted) continue;
|
||||
delete flags.__visited__[floorId];
|
||||
flags.__removed__.push(floorId);
|
||||
delete flags.__disabled__[floorId];
|
||||
delete flags.__leaveLoc__[floorId];
|
||||
(core.status.autoEvents || []).forEach(event => {
|
||||
if (event.floorId == floorId && event.currentFloor) {
|
||||
core.autoEventExecuting(event.symbol, false);
|
||||
core.autoEventExecuted(event.symbol, false);
|
||||
}
|
||||
});
|
||||
core.status.maps[floorId].deleted = true;
|
||||
core.status.maps[floorId].canFlyTo = false;
|
||||
core.status.maps[floorId].canFlyFrom = false;
|
||||
core.status.maps[floorId].cannotViewMap = true;
|
||||
if (force) {
|
||||
core.status.maps[floorId].forceDelete = true;
|
||||
flags.__forceDelete__[floorId] = true;
|
||||
}
|
||||
deleteFlags(floorId);
|
||||
deleted = true;
|
||||
}
|
||||
if (deleted && !main.replayChecking) {
|
||||
core.splitArea();
|
||||
}
|
||||
}
|
||||
|
||||
core.plugin.removeMap = {
|
||||
removeMaps,
|
||||
deleteFlags,
|
||||
resumeMaps,
|
||||
autoRemoveMaps
|
||||
};
|
||||
})();
|
||||
export function deleteFlags(floorId) {
|
||||
delete flags[`jump_${floorId}`];
|
||||
delete flags[`inte_${floorId}`];
|
||||
delete flags[`loop_${floorId}`];
|
||||
delete flags[`melt_${floorId}`];
|
||||
delete flags[`night_${floorId}`];
|
||||
}
|
||||
|
||||
// 恢复楼层
|
||||
// core.plugin.removeMap.resumeMaps("MT1", "MT300") 恢复MT1~MT300之间的全部层
|
||||
// core.plugin.removeMap.resumeMaps("MT10") 只恢复MT10层
|
||||
export function resumeMaps(fromId, toId) {
|
||||
toId = toId || fromId;
|
||||
var fromIndex = core.floorIds.indexOf(fromId),
|
||||
toIndex = core.floorIds.indexOf(toId);
|
||||
if (toIndex < 0) toIndex = core.floorIds.length - 1;
|
||||
flags.__removed__ = flags.__removed__ || [];
|
||||
for (var i = fromIndex; i <= toIndex; ++i) {
|
||||
var floorId = core.floorIds[i];
|
||||
if (!core.status.maps[floorId].deleted) continue;
|
||||
if (
|
||||
core.status.maps[floorId].forceDelete ||
|
||||
flags.__forceDelete__[floorId]
|
||||
)
|
||||
continue;
|
||||
flags.__removed__ = flags.__removed__.filter(f => {
|
||||
return f != floorId;
|
||||
});
|
||||
core.status.maps[floorId] = core.loadFloor(floorId);
|
||||
}
|
||||
}
|
||||
|
||||
// 分区砍层相关
|
||||
var inAnyPartition = floorId => {
|
||||
var inPartition = false;
|
||||
(core.floorPartitions || []).forEach(floor => {
|
||||
var fromIndex = core.floorIds.indexOf(floor[0]);
|
||||
var toIndex = core.floorIds.indexOf(floor[1]);
|
||||
var index = core.floorIds.indexOf(floorId);
|
||||
if (fromIndex < 0 || index < 0) return;
|
||||
if (toIndex < 0) toIndex = core.floorIds.length - 1;
|
||||
if (index >= fromIndex && index <= toIndex) inPartition = true;
|
||||
});
|
||||
return inPartition;
|
||||
};
|
||||
|
||||
// 分区砍层
|
||||
export function autoRemoveMaps(floorId) {
|
||||
if (main.mode != 'play' || !inAnyPartition(floorId)) return;
|
||||
// 根据分区信息自动砍层与恢复
|
||||
(core.floorPartitions || []).forEach(floor => {
|
||||
var fromIndex = core.floorIds.indexOf(floor[0]);
|
||||
var toIndex = core.floorIds.indexOf(floor[1]);
|
||||
var index = core.floorIds.indexOf(floorId);
|
||||
if (fromIndex < 0 || index < 0) return;
|
||||
if (toIndex < 0) toIndex = core.floorIds.length - 1;
|
||||
if (index >= fromIndex && index <= toIndex) {
|
||||
core.plugin.removeMap.resumeMaps(
|
||||
core.floorIds[fromIndex],
|
||||
core.floorIds[toIndex]
|
||||
);
|
||||
} else {
|
||||
removeMaps(core.floorIds[fromIndex], core.floorIds[toIndex]);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
core.plugin.removeMap = {
|
||||
removeMaps,
|
||||
deleteFlags,
|
||||
resumeMaps,
|
||||
autoRemoveMaps
|
||||
};
|
||||
|
@ -1,91 +1,89 @@
|
||||
///<reference path="../../../src/types/core.d.ts" />
|
||||
'use strict';
|
||||
|
||||
(function () {
|
||||
const { studySkill, canStudySkill } = core.plugin.study;
|
||||
const replayableSettings = ['autoSkill'];
|
||||
import { studySkill, canStudySkill } from './study';
|
||||
|
||||
// 注册修改设置的录像操作
|
||||
core.registerReplayAction('settings', name => {
|
||||
if (!name.startsWith('set:')) return false;
|
||||
const [, setting, value] = name.split(':');
|
||||
const v = eval(value);
|
||||
if (typeof v !== 'boolean') return false;
|
||||
if (!replayableSettings.includes(setting)) return false;
|
||||
flags[setting] = v;
|
||||
core.replay();
|
||||
return true;
|
||||
});
|
||||
const replayableSettings = ['autoSkill'];
|
||||
|
||||
core.registerReplayAction('upgradeSkill', name => {
|
||||
if (!name.startsWith('skill:')) return false;
|
||||
const skill = parseInt(name.slice(6));
|
||||
core.plugin.skillTree.upgradeSkill(skill);
|
||||
core.replay();
|
||||
return true;
|
||||
});
|
||||
// 注册修改设置的录像操作
|
||||
core.registerReplayAction('settings', name => {
|
||||
if (!name.startsWith('set:')) return false;
|
||||
const [, setting, value] = name.split(':');
|
||||
const v = eval(value);
|
||||
if (typeof v !== 'boolean') return false;
|
||||
if (!replayableSettings.includes(setting)) return false;
|
||||
flags[setting] = v;
|
||||
core.replay();
|
||||
return true;
|
||||
});
|
||||
|
||||
core.registerReplayAction('study', name => {
|
||||
if (!name.startsWith('study:')) return false;
|
||||
const [num, x, y] = name
|
||||
.slice(6)
|
||||
.split(',')
|
||||
.map(v => parseInt(v));
|
||||
if (!canStudySkill(num)) return false;
|
||||
const id = core.getBlockId(x, y);
|
||||
const enemy = core.getEnemyInfo(id, void 0, x, y);
|
||||
if (!enemy.special.includes(num)) return false;
|
||||
studySkill(enemy, num);
|
||||
core.replay();
|
||||
return true;
|
||||
});
|
||||
core.registerReplayAction('upgradeSkill', name => {
|
||||
if (!name.startsWith('skill:')) return false;
|
||||
const skill = parseInt(name.slice(6));
|
||||
core.plugin.skillTree.upgradeSkill(skill);
|
||||
core.replay();
|
||||
return true;
|
||||
});
|
||||
|
||||
// 商店
|
||||
let shopOpened = false;
|
||||
let openedShopId = '';
|
||||
core.registerReplayAction('openShop', name => {
|
||||
if (!name.startsWith('openShop:')) return false;
|
||||
openedShopId = name.slice(9);
|
||||
shopOpened = true;
|
||||
core.replay();
|
||||
return true;
|
||||
});
|
||||
core.registerReplayAction('study', name => {
|
||||
if (!name.startsWith('study:')) return false;
|
||||
const [num, x, y] = name
|
||||
.slice(6)
|
||||
.split(',')
|
||||
.map(v => parseInt(v));
|
||||
if (!canStudySkill(num)) return false;
|
||||
const id = core.getBlockId(x, y);
|
||||
const enemy = core.getEnemyInfo(id, void 0, x, y);
|
||||
if (!enemy.special.includes(num)) return false;
|
||||
studySkill(enemy, num);
|
||||
core.replay();
|
||||
return true;
|
||||
});
|
||||
|
||||
core.registerReplayAction('buy', name => {
|
||||
if (!name.startsWith('buy:') && !name.startsWith('sell:')) return false;
|
||||
if (!shopOpened) return false;
|
||||
if (!openedShopId) return false;
|
||||
const [type, id, num] = name
|
||||
.split(':')
|
||||
.map(v => (/^\d+$/.test(v) ? parseInt(v) : v));
|
||||
const shop = core.status.shops[id];
|
||||
const item = shop.choices.find(v => v.id === id);
|
||||
if (!item) return false;
|
||||
flags.itemShop ??= {};
|
||||
flags.itemShop[openedShopId] ??= {};
|
||||
flags.itemShop[openedShopId][id] ??= 0;
|
||||
if (num > item.number - flags.itemShop[openedShopId][id]) {
|
||||
return false;
|
||||
}
|
||||
let cost = 0;
|
||||
if (type === 'buy') {
|
||||
cost = item.money * num;
|
||||
} else {
|
||||
cost = -item.sell * num;
|
||||
}
|
||||
if (cost > core.status.hero.money) return false;
|
||||
core.status.hero.money -= cost;
|
||||
flags.itemShop[openedShopId][id] += type === 'buy' ? num : -num;
|
||||
core.replay();
|
||||
return true;
|
||||
});
|
||||
// 商店
|
||||
let shopOpened = false;
|
||||
let openedShopId = '';
|
||||
core.registerReplayAction('openShop', name => {
|
||||
if (!name.startsWith('openShop:')) return false;
|
||||
openedShopId = name.slice(9);
|
||||
shopOpened = true;
|
||||
core.replay();
|
||||
return true;
|
||||
});
|
||||
|
||||
core.registerReplayAction('closeShop', name => {
|
||||
if (name !== 'closeShop') return false;
|
||||
if (!shopOpened) return false;
|
||||
shopOpened = false;
|
||||
openedShopId = '';
|
||||
core.replay();
|
||||
return true;
|
||||
});
|
||||
})();
|
||||
core.registerReplayAction('buy', name => {
|
||||
if (!name.startsWith('buy:') && !name.startsWith('sell:')) return false;
|
||||
if (!shopOpened) return false;
|
||||
if (!openedShopId) return false;
|
||||
const [type, id, num] = name
|
||||
.split(':')
|
||||
.map(v => (/^\d+$/.test(v) ? parseInt(v) : v));
|
||||
const shop = core.status.shops[id];
|
||||
const item = shop.choices.find(v => v.id === id);
|
||||
if (!item) return false;
|
||||
flags.itemShop ??= {};
|
||||
flags.itemShop[openedShopId] ??= {};
|
||||
flags.itemShop[openedShopId][id] ??= 0;
|
||||
if (num > item.number - flags.itemShop[openedShopId][id]) {
|
||||
return false;
|
||||
}
|
||||
let cost = 0;
|
||||
if (type === 'buy') {
|
||||
cost = item.money * num;
|
||||
} else {
|
||||
cost = -item.sell * num;
|
||||
}
|
||||
if (cost > core.status.hero.money) return false;
|
||||
core.status.hero.money -= cost;
|
||||
flags.itemShop[openedShopId][id] += type === 'buy' ? num : -num;
|
||||
core.replay();
|
||||
return true;
|
||||
});
|
||||
|
||||
core.registerReplayAction('closeShop', name => {
|
||||
if (name !== 'closeShop') return false;
|
||||
if (!shopOpened) return false;
|
||||
shopOpened = false;
|
||||
openedShopId = '';
|
||||
core.replay();
|
||||
return true;
|
||||
});
|
||||
|
@ -1,77 +1,74 @@
|
||||
///<reference path="../../../src/types/core.d.ts" />
|
||||
'use strict';
|
||||
|
||||
(function () {
|
||||
const { openItemShop } = core.plugin.gameUi;
|
||||
const { openItemShop } = core.plugin.gameUi;
|
||||
|
||||
function openShop(shopId, noRoute) {
|
||||
var shop = core.status.shops[shopId];
|
||||
// Step 1: 检查能否打开此商店
|
||||
if (!this.canOpenShop(shopId)) {
|
||||
core.drawTip('该商店尚未开启');
|
||||
return false;
|
||||
}
|
||||
|
||||
// Step 3: 检查道具商店 or 公共事件
|
||||
if (shop.item) {
|
||||
if (openItemShop) openItemShop(shopId);
|
||||
return;
|
||||
}
|
||||
return true;
|
||||
export function openShop(shopId, noRoute) {
|
||||
var shop = core.status.shops[shopId];
|
||||
// Step 1: 检查能否打开此商店
|
||||
if (!this.canOpenShop(shopId)) {
|
||||
core.drawTip('该商店尚未开启');
|
||||
return false;
|
||||
}
|
||||
|
||||
/// 是否访问过某个快捷商店
|
||||
function isShopVisited(id) {
|
||||
flags.__shops__ ??= {};
|
||||
var shops = core.getFlag('__shops__');
|
||||
if (!shops[id]) shops[id] = {};
|
||||
return shops[id].visited;
|
||||
// Step 3: 检查道具商店 or 公共事件
|
||||
if (shop.item) {
|
||||
if (openItemShop) openItemShop(shopId);
|
||||
return;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// 当前应当显示的快捷商店列表
|
||||
function listShopIds() {
|
||||
return Object.keys(core.status.shops).filter(id => {
|
||||
return (
|
||||
core.plugin.shop.isShopVisited(id) ||
|
||||
!core.status.shops[id].mustEnable
|
||||
);
|
||||
});
|
||||
}
|
||||
/// 是否访问过某个快捷商店
|
||||
export function isShopVisited(id) {
|
||||
flags.__shops__ ??= {};
|
||||
var shops = core.getFlag('__shops__');
|
||||
if (!shops[id]) shops[id] = {};
|
||||
return shops[id].visited;
|
||||
}
|
||||
|
||||
/// 是否能够打开某个商店
|
||||
function canOpenShop(id) {
|
||||
if (this.isShopVisited(id)) return true;
|
||||
var shop = core.status.shops[id];
|
||||
if (shop.item || shop.commonEvent || shop.mustEnable) return false;
|
||||
return true;
|
||||
}
|
||||
/// 当前应当显示的快捷商店列表
|
||||
export function listShopIds() {
|
||||
return Object.keys(core.status.shops).filter(id => {
|
||||
return (
|
||||
core.plugin.shop.isShopVisited(id) ||
|
||||
!core.status.shops[id].mustEnable
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/// 启用或禁用某个快捷商店
|
||||
function setShopVisited(id, visited) {
|
||||
if (!core.hasFlag('__shops__')) core.setFlag('__shops__', {});
|
||||
var shops = core.getFlag('__shops__');
|
||||
if (!shops[id]) shops[id] = {};
|
||||
if (visited) shops[id].visited = true;
|
||||
else delete shops[id].visited;
|
||||
}
|
||||
/// 是否能够打开某个商店
|
||||
export function canOpenShop(id) {
|
||||
if (this.isShopVisited(id)) return true;
|
||||
var shop = core.status.shops[id];
|
||||
if (shop.item || shop.commonEvent || shop.mustEnable) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// 能否使用快捷商店
|
||||
function canUseQuickShop() {
|
||||
// 如果返回一个字符串,表示不能,字符串为不能使用的提示
|
||||
// 返回null代表可以使用
|
||||
/// 启用或禁用某个快捷商店
|
||||
export function setShopVisited(id, visited) {
|
||||
if (!core.hasFlag('__shops__')) core.setFlag('__shops__', {});
|
||||
var shops = core.getFlag('__shops__');
|
||||
if (!shops[id]) shops[id] = {};
|
||||
if (visited) shops[id].visited = true;
|
||||
else delete shops[id].visited;
|
||||
}
|
||||
|
||||
// 检查当前楼层的canUseQuickShop选项是否为false
|
||||
if (core.status.thisMap.canUseQuickShop === false)
|
||||
return '当前楼层不能使用快捷商店。';
|
||||
return null;
|
||||
}
|
||||
/// 能否使用快捷商店
|
||||
export function canUseQuickShop() {
|
||||
// 如果返回一个字符串,表示不能,字符串为不能使用的提示
|
||||
// 返回null代表可以使用
|
||||
|
||||
core.plugin.shop = {
|
||||
openShop,
|
||||
isShopVisited,
|
||||
listShopIds,
|
||||
canOpenShop,
|
||||
setShopVisited,
|
||||
canUseQuickShop
|
||||
};
|
||||
})();
|
||||
// 检查当前楼层的canUseQuickShop选项是否为false
|
||||
if (core.status.thisMap.canUseQuickShop === false)
|
||||
return '当前楼层不能使用快捷商店。';
|
||||
return null;
|
||||
}
|
||||
|
||||
core.plugin.shop = {
|
||||
openShop,
|
||||
isShopVisited,
|
||||
listShopIds,
|
||||
canOpenShop,
|
||||
setShopVisited,
|
||||
canUseQuickShop
|
||||
};
|
||||
|
@ -1,320 +1,316 @@
|
||||
///<reference path="../../../src/types/core.d.ts" />
|
||||
'use strict';
|
||||
|
||||
(function () {
|
||||
/**
|
||||
* @type {number[]}
|
||||
*/
|
||||
let levels = [];
|
||||
/**
|
||||
* @type {number[]}
|
||||
*/
|
||||
let levels = [];
|
||||
|
||||
/**
|
||||
* @type {Record<Chapter, Skill[]>}
|
||||
*/
|
||||
const skills = {
|
||||
chapter1: [
|
||||
{
|
||||
index: 0,
|
||||
title: '力量',
|
||||
desc: ['力量就是根本!可以通过智慧增加力量,每级增加2点攻击。'],
|
||||
consume: '10 * level + 10',
|
||||
front: [],
|
||||
loc: [1, 2],
|
||||
max: 10,
|
||||
effect: ['攻击 + ${level * 2}']
|
||||
},
|
||||
{
|
||||
index: 1,
|
||||
title: '致命一击',
|
||||
desc: ['爆发出全部力量攻击敌人,每级增加5点额外攻击。'],
|
||||
consume: '30 * level + 30',
|
||||
front: [[0, 5]],
|
||||
loc: [2, 1],
|
||||
max: 10,
|
||||
effect: ['额外攻击 + ${level * 5}']
|
||||
},
|
||||
{
|
||||
index: 2,
|
||||
title: '断灭之刃',
|
||||
desc: [
|
||||
'<span style="color: gold">主动技能,快捷键1</span>,',
|
||||
'开启后会在战斗时会额外增加一定量的攻击,但同时减少一定量的防御。'
|
||||
],
|
||||
consume: '200 * level + 400',
|
||||
front: [[1, 5]],
|
||||
loc: [4, 1],
|
||||
max: 5,
|
||||
effect: ['增加${level * 10}%攻击,减少${level * 10}%防御']
|
||||
},
|
||||
{
|
||||
index: 3,
|
||||
title: '坚韧',
|
||||
desc: ['由智慧转化出坚韧!每级增加2点防御'],
|
||||
consume: '10 * level + 10',
|
||||
front: [],
|
||||
loc: [1, 4],
|
||||
max: 10,
|
||||
effect: ['防御 + ${level * 2}']
|
||||
},
|
||||
{
|
||||
index: 4,
|
||||
title: '回春',
|
||||
desc: ['让智慧化为治愈之泉水!每级增加1点生命回复'],
|
||||
consume: '20 * level + 20',
|
||||
front: [[3, 5]],
|
||||
loc: [2, 5],
|
||||
max: 25,
|
||||
effect: ['生命回复 + ${level}']
|
||||
},
|
||||
{
|
||||
index: 5,
|
||||
title: '治愈之泉',
|
||||
desc: [
|
||||
'让生命变得更多一些吧!每吃50瓶血瓶就增加当前生命回复10%的生命回复'
|
||||
],
|
||||
consume: '1500',
|
||||
front: [[4, 25]],
|
||||
loc: [4, 5],
|
||||
max: 1,
|
||||
effect: ['50瓶血10%生命回复']
|
||||
},
|
||||
{
|
||||
index: 6,
|
||||
title: '坚固之盾',
|
||||
desc: ['让护甲更加坚硬一些吧!每级增加10点防御'],
|
||||
consume: '50 + level * 50',
|
||||
front: [[3, 5]],
|
||||
loc: [2, 3],
|
||||
max: 10,
|
||||
effect: ['防御 + ${level * 10}']
|
||||
},
|
||||
{
|
||||
index: 7,
|
||||
title: '无上之盾',
|
||||
desc: [
|
||||
'<span style="color: #dd4">第一章终极技能</span>,战斗时智慧会充当等量护盾'
|
||||
],
|
||||
consume: '2500',
|
||||
front: [
|
||||
[6, 10],
|
||||
[5, 1],
|
||||
[2, 2]
|
||||
],
|
||||
loc: [5, 3],
|
||||
max: 1,
|
||||
effect: ['战斗时智慧会充当护盾']
|
||||
/**
|
||||
* @type {Record<Chapter, Skill[]>}
|
||||
*/
|
||||
const skills = {
|
||||
chapter1: [
|
||||
{
|
||||
index: 0,
|
||||
title: '力量',
|
||||
desc: ['力量就是根本!可以通过智慧增加力量,每级增加2点攻击。'],
|
||||
consume: '10 * level + 10',
|
||||
front: [],
|
||||
loc: [1, 2],
|
||||
max: 10,
|
||||
effect: ['攻击 + ${level * 2}']
|
||||
},
|
||||
{
|
||||
index: 1,
|
||||
title: '致命一击',
|
||||
desc: ['爆发出全部力量攻击敌人,每级增加5点额外攻击。'],
|
||||
consume: '30 * level + 30',
|
||||
front: [[0, 5]],
|
||||
loc: [2, 1],
|
||||
max: 10,
|
||||
effect: ['额外攻击 + ${level * 5}']
|
||||
},
|
||||
{
|
||||
index: 2,
|
||||
title: '断灭之刃',
|
||||
desc: [
|
||||
'<span style="color: gold">主动技能,快捷键1</span>,',
|
||||
'开启后会在战斗时会额外增加一定量的攻击,但同时减少一定量的防御。'
|
||||
],
|
||||
consume: '200 * level + 400',
|
||||
front: [[1, 5]],
|
||||
loc: [4, 1],
|
||||
max: 5,
|
||||
effect: ['增加${level * 10}%攻击,减少${level * 10}%防御']
|
||||
},
|
||||
{
|
||||
index: 3,
|
||||
title: '坚韧',
|
||||
desc: ['由智慧转化出坚韧!每级增加2点防御'],
|
||||
consume: '10 * level + 10',
|
||||
front: [],
|
||||
loc: [1, 4],
|
||||
max: 10,
|
||||
effect: ['防御 + ${level * 2}']
|
||||
},
|
||||
{
|
||||
index: 4,
|
||||
title: '回春',
|
||||
desc: ['让智慧化为治愈之泉水!每级增加1点生命回复'],
|
||||
consume: '20 * level + 20',
|
||||
front: [[3, 5]],
|
||||
loc: [2, 5],
|
||||
max: 25,
|
||||
effect: ['生命回复 + ${level}']
|
||||
},
|
||||
{
|
||||
index: 5,
|
||||
title: '治愈之泉',
|
||||
desc: [
|
||||
'让生命变得更多一些吧!每吃50瓶血瓶就增加当前生命回复10%的生命回复'
|
||||
],
|
||||
consume: '1500',
|
||||
front: [[4, 25]],
|
||||
loc: [4, 5],
|
||||
max: 1,
|
||||
effect: ['50瓶血10%生命回复']
|
||||
},
|
||||
{
|
||||
index: 6,
|
||||
title: '坚固之盾',
|
||||
desc: ['让护甲更加坚硬一些吧!每级增加10点防御'],
|
||||
consume: '50 + level * 50',
|
||||
front: [[3, 5]],
|
||||
loc: [2, 3],
|
||||
max: 10,
|
||||
effect: ['防御 + ${level * 10}']
|
||||
},
|
||||
{
|
||||
index: 7,
|
||||
title: '无上之盾',
|
||||
desc: [
|
||||
'<span style="color: #dd4">第一章终极技能</span>,战斗时智慧会充当等量护盾'
|
||||
],
|
||||
consume: '2500',
|
||||
front: [
|
||||
[6, 10],
|
||||
[5, 1],
|
||||
[2, 2]
|
||||
],
|
||||
loc: [5, 3],
|
||||
max: 1,
|
||||
effect: ['战斗时智慧会充当护盾']
|
||||
}
|
||||
],
|
||||
chapter2: [
|
||||
{
|
||||
index: 8,
|
||||
title: '锋利',
|
||||
desc: ['让剑变得更加锋利!每级使攻击增加1%(buff式增加)'],
|
||||
consume: 'level > 5 ? 50 * level ** 2 : 250 * level + 250',
|
||||
front: [],
|
||||
loc: [1, 2],
|
||||
max: 15,
|
||||
effect: ['攻击增加${level}%']
|
||||
},
|
||||
{
|
||||
index: 9,
|
||||
title: '坚硬',
|
||||
desc: ['让盾牌变得更加坚固!每级使防御增加1%(buff式增加)'],
|
||||
consume: 'level > 5 ? 50 * level ** 2 : 250 * level + 250',
|
||||
front: [],
|
||||
loc: [1, 4],
|
||||
max: 15,
|
||||
effect: ['防御增加${level}%']
|
||||
},
|
||||
{
|
||||
index: 10,
|
||||
title: '铸剑为盾',
|
||||
desc: [
|
||||
'<span style="color: gold">主动技能,快捷键3</span>,',
|
||||
'减少一定的攻击,增加一定的防御'
|
||||
],
|
||||
consume: '500 * level + 1000',
|
||||
front: [[9, 5]],
|
||||
loc: [2, 5],
|
||||
max: 5,
|
||||
effect: ['增加${level * 10}%的防御,减少${level * 10}%的攻击']
|
||||
},
|
||||
{
|
||||
index: 11,
|
||||
title: '学习',
|
||||
desc: [
|
||||
'<span style="color: gold">主动技能</span>,可以消耗500智慧学习一个怪物的技能,',
|
||||
'持续5场战斗,每学习一次消耗的智慧点增加250,每次升级使持续的战斗次数增加3次。更多信息可在学习后在百科全书查看。'
|
||||
],
|
||||
consume: '2500 * level ** 2 + 2500',
|
||||
front: [
|
||||
[8, 10],
|
||||
[12, 5]
|
||||
],
|
||||
loc: [4, 1],
|
||||
max: 6,
|
||||
effect: ['学习怪物技能,持续${level * 3 + 2}场战斗']
|
||||
},
|
||||
{
|
||||
index: 12,
|
||||
title: '聪慧',
|
||||
desc: ['使主角变得更加聪明,每级使绿宝石增加的智慧点上升5%'],
|
||||
consume: 'level > 5 ? 100 * level ** 2 : 250 * level + 1250',
|
||||
front: [
|
||||
[8, 10],
|
||||
[9, 10]
|
||||
],
|
||||
loc: [3, 3],
|
||||
max: 20,
|
||||
effect: ['增加${level * 5}%绿宝石效果']
|
||||
},
|
||||
{
|
||||
index: 13,
|
||||
title: '治愈',
|
||||
desc: ['使主角能够更好地回复生命,每级使血瓶的加血量增加2%'],
|
||||
consume: 'level > 5 ? 100 * level ** 2 : 250 * level + 1250',
|
||||
front: [[10, 3]],
|
||||
loc: [4, 5],
|
||||
max: 20,
|
||||
effect: ['增加${level * 2}%的血瓶回血量']
|
||||
},
|
||||
{
|
||||
index: 14,
|
||||
title: '胜利之号',
|
||||
desc: [
|
||||
'<span style="color: #dd4">第二章终极技能</span>,',
|
||||
'每打一个怪物,勇士在本楼层对怪物造成的伤害便增加1%'
|
||||
],
|
||||
consume: '15000',
|
||||
front: [
|
||||
[13, 10],
|
||||
[12, 10],
|
||||
[11, 3]
|
||||
],
|
||||
loc: [5, 3],
|
||||
max: 1,
|
||||
effect: ['每打一个怪,勇士造成的伤害增加1%']
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
core.plugin.skills = skills;
|
||||
|
||||
export function getSkillFromIndex(index) {
|
||||
for (const [, skill] of Object.entries(skills)) {
|
||||
const s = skill.find(v => v.index === index);
|
||||
if (s) return s;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取技能等级
|
||||
* @param {number} skill
|
||||
*/
|
||||
export function getSkillLevel(skill) {
|
||||
return (levels[skill] ??= 0);
|
||||
}
|
||||
|
||||
export function getSkillConsume(skill) {
|
||||
return eval(
|
||||
this.getSkillFromIndex(skill).consume.replace(
|
||||
/level(:\d+)?/g,
|
||||
(str, $1) => {
|
||||
if ($1) return `core.plugin.skillTree.getSkillLevel(${$1})`;
|
||||
else return `core.plugin.skillTree.getSkillLevel(${skill})`;
|
||||
}
|
||||
],
|
||||
chapter2: [
|
||||
{
|
||||
index: 8,
|
||||
title: '锋利',
|
||||
desc: ['让剑变得更加锋利!每级使攻击增加1%(buff式增加)'],
|
||||
consume: 'level > 5 ? 50 * level ** 2 : 250 * level + 250',
|
||||
front: [],
|
||||
loc: [1, 2],
|
||||
max: 15,
|
||||
effect: ['攻击增加${level}%']
|
||||
},
|
||||
{
|
||||
index: 9,
|
||||
title: '坚硬',
|
||||
desc: ['让盾牌变得更加坚固!每级使防御增加1%(buff式增加)'],
|
||||
consume: 'level > 5 ? 50 * level ** 2 : 250 * level + 250',
|
||||
front: [],
|
||||
loc: [1, 4],
|
||||
max: 15,
|
||||
effect: ['防御增加${level}%']
|
||||
},
|
||||
{
|
||||
index: 10,
|
||||
title: '铸剑为盾',
|
||||
desc: [
|
||||
'<span style="color: gold">主动技能,快捷键3</span>,',
|
||||
'减少一定的攻击,增加一定的防御'
|
||||
],
|
||||
consume: '500 * level + 1000',
|
||||
front: [[9, 5]],
|
||||
loc: [2, 5],
|
||||
max: 5,
|
||||
effect: ['增加${level * 10}%的防御,减少${level * 10}%的攻击']
|
||||
},
|
||||
{
|
||||
index: 11,
|
||||
title: '学习',
|
||||
desc: [
|
||||
'<span style="color: gold">主动技能</span>,可以消耗500智慧学习一个怪物的技能,',
|
||||
'持续5场战斗,每学习一次消耗的智慧点增加250,每次升级使持续的战斗次数增加3次。更多信息可在学习后在百科全书查看。'
|
||||
],
|
||||
consume: '2500 * level ** 2 + 2500',
|
||||
front: [
|
||||
[8, 10],
|
||||
[12, 5]
|
||||
],
|
||||
loc: [4, 1],
|
||||
max: 6,
|
||||
effect: ['学习怪物技能,持续${level * 3 + 2}场战斗']
|
||||
},
|
||||
{
|
||||
index: 12,
|
||||
title: '聪慧',
|
||||
desc: ['使主角变得更加聪明,每级使绿宝石增加的智慧点上升5%'],
|
||||
consume: 'level > 5 ? 100 * level ** 2 : 250 * level + 1250',
|
||||
front: [
|
||||
[8, 10],
|
||||
[9, 10]
|
||||
],
|
||||
loc: [3, 3],
|
||||
max: 20,
|
||||
effect: ['增加${level * 5}%绿宝石效果']
|
||||
},
|
||||
{
|
||||
index: 13,
|
||||
title: '治愈',
|
||||
desc: ['使主角能够更好地回复生命,每级使血瓶的加血量增加2%'],
|
||||
consume: 'level > 5 ? 100 * level ** 2 : 250 * level + 1250',
|
||||
front: [[10, 3]],
|
||||
loc: [4, 5],
|
||||
max: 20,
|
||||
effect: ['增加${level * 2}%的血瓶回血量']
|
||||
},
|
||||
{
|
||||
index: 14,
|
||||
title: '胜利之号',
|
||||
desc: [
|
||||
'<span style="color: #dd4">第二章终极技能</span>,',
|
||||
'每打一个怪物,勇士在本楼层对怪物造成的伤害便增加1%'
|
||||
],
|
||||
consume: '15000',
|
||||
front: [
|
||||
[13, 10],
|
||||
[12, 10],
|
||||
[11, 3]
|
||||
],
|
||||
loc: [5, 3],
|
||||
max: 1,
|
||||
effect: ['每打一个怪,勇士造成的伤害增加1%']
|
||||
}
|
||||
]
|
||||
};
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
core.plugin.skills = skills;
|
||||
export function openTree() {
|
||||
if (main.replayChecking) return;
|
||||
core.plugin.skillTreeOpened.value = true;
|
||||
}
|
||||
|
||||
function getSkillFromIndex(index) {
|
||||
for (const [, skill] of Object.entries(skills)) {
|
||||
const s = skill.find(v => v.index === index);
|
||||
if (s) return s;
|
||||
}
|
||||
/**
|
||||
* 能否升级某个技能
|
||||
* @param {number} skill
|
||||
*/
|
||||
export function canUpgrade(skill) {
|
||||
const consume = core.plugin.skillTree.getSkillConsume(skill);
|
||||
if (consume > core.status.hero.mdef) return false;
|
||||
const level = core.plugin.skillTree.getSkillLevel(skill);
|
||||
const s = getSkillFromIndex(skill);
|
||||
if (level === s.max) return false;
|
||||
const front = s.front;
|
||||
for (const [skill, level] of front) {
|
||||
if (core.plugin.skillTree.getSkillLevel(skill) < level) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取技能等级
|
||||
* @param {number} skill
|
||||
*/
|
||||
function getSkillLevel(skill) {
|
||||
return (levels[skill] ??= 0);
|
||||
/**
|
||||
* 实际升级效果
|
||||
* @param {number} skill
|
||||
*/
|
||||
export function upgradeSkill(skill) {
|
||||
if (!canUpgrade(skill)) return false;
|
||||
switch (skill) {
|
||||
case 0: // 力量 +2攻击
|
||||
core.status.hero.atk += 2;
|
||||
break;
|
||||
case 1: // 致命一击 +5额外攻击
|
||||
core.status.hero.mana += 5;
|
||||
break;
|
||||
case 2: // 断灭之刃
|
||||
core.setFlag('bladeOn', true);
|
||||
break;
|
||||
case 3: // 坚韧 +2防御
|
||||
core.status.hero.def += 2;
|
||||
break;
|
||||
case 4: // 回春 +1回复
|
||||
core.status.hero.hpmax += 1;
|
||||
break;
|
||||
case 5: // 治愈之泉
|
||||
core.setFlag('spring', true);
|
||||
break;
|
||||
case 6: // 坚固之盾 +10防御
|
||||
core.status.hero.def += 10;
|
||||
break;
|
||||
case 7: // 无上之盾
|
||||
core.setFlag('superSheild', true);
|
||||
break;
|
||||
case 8: // 锋利 +1%攻击
|
||||
core.addBuff('atk', 0.01);
|
||||
break;
|
||||
case 9: // 锋利 +1%防御
|
||||
core.addBuff('def', 0.01);
|
||||
break;
|
||||
case 10: // 铸剑为盾
|
||||
core.setFlag('shieldOn', true);
|
||||
break;
|
||||
case 11: // 学习
|
||||
core.setItem('I565', 1);
|
||||
break;
|
||||
}
|
||||
const consume = getSkillConsume(skill);
|
||||
core.status.hero.mdef -= consume;
|
||||
levels[skill]++;
|
||||
core.updateStatusBar();
|
||||
return true;
|
||||
}
|
||||
|
||||
function getSkillConsume(skill) {
|
||||
return eval(
|
||||
this.getSkillFromIndex(skill).consume.replace(
|
||||
/level(:\d+)?/g,
|
||||
(str, $1) => {
|
||||
if ($1) return `core.plugin.skillTree.getSkillLevel(${$1})`;
|
||||
else return `core.plugin.skillTree.getSkillLevel(${skill})`;
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
export function saveSkillTree() {
|
||||
return levels.slice();
|
||||
}
|
||||
|
||||
function openTree() {
|
||||
if (main.replayChecking) return;
|
||||
core.plugin.skillTreeOpened.value = true;
|
||||
}
|
||||
export function loadSkillTree(data) {
|
||||
levels = data ?? [];
|
||||
}
|
||||
|
||||
/**
|
||||
* 能否升级某个技能
|
||||
* @param {number} skill
|
||||
*/
|
||||
function canUpgrade(skill) {
|
||||
const consume = core.plugin.skillTree.getSkillConsume(skill);
|
||||
if (consume > core.status.hero.mdef) return false;
|
||||
const level = core.plugin.skillTree.getSkillLevel(skill);
|
||||
const s = getSkillFromIndex(skill);
|
||||
if (level === s.max) return false;
|
||||
const front = s.front;
|
||||
for (const [skill, level] of front) {
|
||||
if (core.plugin.skillTree.getSkillLevel(skill) < level)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 实际升级效果
|
||||
* @param {number} skill
|
||||
*/
|
||||
function upgradeSkill(skill) {
|
||||
if (!canUpgrade(skill)) return false;
|
||||
switch (skill) {
|
||||
case 0: // 力量 +2攻击
|
||||
core.status.hero.atk += 2;
|
||||
break;
|
||||
case 1: // 致命一击 +5额外攻击
|
||||
core.status.hero.mana += 5;
|
||||
break;
|
||||
case 2: // 断灭之刃
|
||||
core.setFlag('bladeOn', true);
|
||||
break;
|
||||
case 3: // 坚韧 +2防御
|
||||
core.status.hero.def += 2;
|
||||
break;
|
||||
case 4: // 回春 +1回复
|
||||
core.status.hero.hpmax += 1;
|
||||
break;
|
||||
case 5: // 治愈之泉
|
||||
core.setFlag('spring', true);
|
||||
break;
|
||||
case 6: // 坚固之盾 +10防御
|
||||
core.status.hero.def += 10;
|
||||
break;
|
||||
case 7: // 无上之盾
|
||||
core.setFlag('superSheild', true);
|
||||
break;
|
||||
case 8: // 锋利 +1%攻击
|
||||
core.addBuff('atk', 0.01);
|
||||
break;
|
||||
case 9: // 锋利 +1%防御
|
||||
core.addBuff('def', 0.01);
|
||||
break;
|
||||
case 10: // 铸剑为盾
|
||||
core.setFlag('shieldOn', true);
|
||||
break;
|
||||
case 11: // 学习
|
||||
core.setItem('I565', 1);
|
||||
break;
|
||||
}
|
||||
const consume = getSkillConsume(skill);
|
||||
core.status.hero.mdef -= consume;
|
||||
levels[skill]++;
|
||||
core.updateStatusBar();
|
||||
return true;
|
||||
}
|
||||
|
||||
function saveSkillTree() {
|
||||
return levels.slice();
|
||||
}
|
||||
|
||||
function loadSkillTree(data) {
|
||||
levels = data ?? [];
|
||||
}
|
||||
|
||||
core.plugin.skillTree = {
|
||||
getSkillConsume,
|
||||
getSkillFromIndex,
|
||||
getSkillLevel,
|
||||
saveSkillTree,
|
||||
loadSkillTree,
|
||||
upgradeSkill,
|
||||
openTree
|
||||
};
|
||||
})();
|
||||
core.plugin.skillTree = {
|
||||
getSkillConsume,
|
||||
getSkillFromIndex,
|
||||
getSkillLevel,
|
||||
saveSkillTree,
|
||||
loadSkillTree,
|
||||
upgradeSkill,
|
||||
openTree
|
||||
};
|
||||
|
@ -1,182 +1,173 @@
|
||||
///<reference path="../../../src/types/core.d.ts" />
|
||||
'use strict';
|
||||
|
||||
(function () {
|
||||
// 所有的主动技能效果
|
||||
var ignoreInJump = {
|
||||
event: ['X20007', 'X20001', 'X20006', 'X20014', 'X20010', 'X20007'],
|
||||
bg: [
|
||||
'X20037',
|
||||
'X20038',
|
||||
'X20039',
|
||||
'X20045',
|
||||
'X20047',
|
||||
'X20053',
|
||||
'X20054',
|
||||
'X20055',
|
||||
'X20067',
|
||||
'X20068',
|
||||
'X20075',
|
||||
'X20076'
|
||||
]
|
||||
};
|
||||
// 所有的主动技能效果
|
||||
var ignoreInJump = {
|
||||
event: ['X20007', 'X20001', 'X20006', 'X20014', 'X20010', 'X20007'],
|
||||
bg: [
|
||||
'X20037',
|
||||
'X20038',
|
||||
'X20039',
|
||||
'X20045',
|
||||
'X20047',
|
||||
'X20053',
|
||||
'X20054',
|
||||
'X20055',
|
||||
'X20067',
|
||||
'X20068',
|
||||
'X20075',
|
||||
'X20076'
|
||||
]
|
||||
};
|
||||
|
||||
/** @type {FloorIds[]} */
|
||||
const jumpIgnoreFloor = ['MT31', 'snowTown'];
|
||||
// 跳跃
|
||||
function jumpSkill() {
|
||||
if (core.status.floorId.startsWith('tower'))
|
||||
return core.drawTip('当无法使用该技能');
|
||||
if (jumpIgnoreFloor.includes(core.status.floorId) || flags.onChase) {
|
||||
return core.drawTip('当前楼层无法使用该技能');
|
||||
}
|
||||
if (!flags.skill2) return;
|
||||
if (!flags['jump_' + core.status.floorId])
|
||||
flags['jump_' + core.status.floorId] = 0;
|
||||
/** @type {FloorIds[]} */
|
||||
const jumpIgnoreFloor = ['MT31', 'snowTown'];
|
||||
// 跳跃
|
||||
export function jumpSkill() {
|
||||
if (core.status.floorId.startsWith('tower'))
|
||||
return core.drawTip('当无法使用该技能');
|
||||
if (jumpIgnoreFloor.includes(core.status.floorId) || flags.onChase) {
|
||||
return core.drawTip('当前楼层无法使用该技能');
|
||||
}
|
||||
if (!flags.skill2) return;
|
||||
if (!flags['jump_' + core.status.floorId])
|
||||
flags['jump_' + core.status.floorId] = 0;
|
||||
if (
|
||||
core.status.floorId == 'MT14' &&
|
||||
flags['jump_' + core.status.floorId] == 2 &&
|
||||
!flags.MT14Jump
|
||||
) {
|
||||
if (
|
||||
core.status.floorId == 'MT14' &&
|
||||
flags['jump_' + core.status.floorId] == 2 &&
|
||||
!flags.MT14Jump
|
||||
!(
|
||||
core.status.hero.loc.x === 77 &&
|
||||
core.status.hero.loc.y === 5 &&
|
||||
core.status.hero.loc.direction === 'right'
|
||||
)
|
||||
) {
|
||||
if (
|
||||
!(
|
||||
core.status.hero.loc.x === 77 &&
|
||||
core.status.hero.loc.y === 5 &&
|
||||
core.status.hero.loc.direction === 'right'
|
||||
)
|
||||
) {
|
||||
return core.drawTip('该地图还有一个必跳的地方,你还没有跳');
|
||||
} else flags.MT14Jump = true;
|
||||
return core.drawTip('该地图还有一个必跳的地方,你还没有跳');
|
||||
} else flags.MT14Jump = true;
|
||||
}
|
||||
if (flags['jump_' + core.status.floorId] >= 3)
|
||||
return core.drawTip('当前地图使用次数已用完');
|
||||
var direction = core.status.hero.loc.direction;
|
||||
var loc = core.status.hero.loc;
|
||||
var checkLoc = {};
|
||||
switch (direction) {
|
||||
case 'up':
|
||||
checkLoc.x = loc.x;
|
||||
checkLoc.y = loc.y - 1;
|
||||
break;
|
||||
case 'right':
|
||||
checkLoc.x = loc.x + 1;
|
||||
checkLoc.y = loc.y;
|
||||
break;
|
||||
case 'down':
|
||||
checkLoc.x = loc.x;
|
||||
checkLoc.y = loc.y + 1;
|
||||
break;
|
||||
case 'left':
|
||||
checkLoc.x = loc.x - 1;
|
||||
checkLoc.y = loc.y;
|
||||
break;
|
||||
}
|
||||
// 前方是否可通行 或 是怪物
|
||||
var cls = core.getBlockCls(checkLoc.x, checkLoc.y);
|
||||
var noPass = core.noPass(checkLoc.x, checkLoc.y);
|
||||
var id = core.getBlockId(checkLoc.x, checkLoc.y) || '';
|
||||
var bgId =
|
||||
core.getBlockByNumber(core.getBgNumber(checkLoc.x, checkLoc.y)).event
|
||||
.id || '';
|
||||
// 可以通行
|
||||
if (
|
||||
!noPass ||
|
||||
cls == 'items' ||
|
||||
(id.startsWith('X') && !ignoreInJump.event.includes(id)) ||
|
||||
(bgId.startsWith('X') && !ignoreInJump.bg.includes(bgId))
|
||||
)
|
||||
return core.drawTip('当前无法使用技能');
|
||||
// 不是怪物且不可以通行
|
||||
if (noPass && !(cls == 'enemys' || cls == 'enemy48')) {
|
||||
var toLoc = checkNoPass(direction, checkLoc.x, checkLoc.y, true);
|
||||
if (!toLoc) return;
|
||||
core.autosave();
|
||||
if (flags.chapter <= 1) core.status.hero.hp -= 200 * flags.hard;
|
||||
core.updateStatusBar();
|
||||
flags['jump_' + core.status.floorId]++;
|
||||
if (core.status.hero.hp <= 0) {
|
||||
core.status.hero.hp = 0;
|
||||
core.updateStatusBar();
|
||||
core.events.lose('你跳死了');
|
||||
}
|
||||
if (flags['jump_' + core.status.floorId] >= 3)
|
||||
return core.drawTip('当前地图使用次数已用完');
|
||||
var direction = core.status.hero.loc.direction;
|
||||
var loc = core.status.hero.loc;
|
||||
var checkLoc = {};
|
||||
core.playSound('015-Jump01.ogg');
|
||||
core.insertAction([
|
||||
{ type: 'jumpHero', loc: [toLoc.x, toLoc.y], time: 500 }
|
||||
]);
|
||||
}
|
||||
// 是怪物
|
||||
if (cls == 'enemys' || cls == 'enemy48') {
|
||||
var firstNoPass = checkNoPass(direction, checkLoc.x, checkLoc.y, false);
|
||||
if (!firstNoPass) return;
|
||||
core.autosave();
|
||||
if (flags.chapter <= 1) core.status.hero.hp -= 200 * flags.hard;
|
||||
core.updateStatusBar();
|
||||
flags['jump_' + core.status.floorId]++;
|
||||
if (core.status.hero.hp <= 0) {
|
||||
core.status.hero.hp = 0;
|
||||
core.updateStatusBar();
|
||||
core.events.lose('你跳死了');
|
||||
}
|
||||
core.playSound('015-Jump01.ogg');
|
||||
core.insertAction([
|
||||
{
|
||||
type: 'jump',
|
||||
from: [checkLoc.x, checkLoc.y],
|
||||
to: [firstNoPass.x, firstNoPass.y],
|
||||
time: 500,
|
||||
keep: true
|
||||
}
|
||||
]);
|
||||
}
|
||||
// 检查一条线上的不可通过
|
||||
function checkNoPass(direction, x, y, startNo) {
|
||||
if (!startNo) startNo = false;
|
||||
switch (direction) {
|
||||
case 'up':
|
||||
checkLoc.x = loc.x;
|
||||
checkLoc.y = loc.y - 1;
|
||||
y--;
|
||||
break;
|
||||
case 'right':
|
||||
checkLoc.x = loc.x + 1;
|
||||
checkLoc.y = loc.y;
|
||||
x++;
|
||||
break;
|
||||
case 'down':
|
||||
checkLoc.x = loc.x;
|
||||
checkLoc.y = loc.y + 1;
|
||||
y++;
|
||||
break;
|
||||
case 'left':
|
||||
checkLoc.x = loc.x - 1;
|
||||
checkLoc.y = loc.y;
|
||||
x--;
|
||||
break;
|
||||
}
|
||||
// 前方是否可通行 或 是怪物
|
||||
var cls = core.getBlockCls(checkLoc.x, checkLoc.y);
|
||||
var noPass = core.noPass(checkLoc.x, checkLoc.y);
|
||||
var id = core.getBlockId(checkLoc.x, checkLoc.y) || '';
|
||||
var bgId =
|
||||
core.getBlockByNumber(core.getBgNumber(checkLoc.x, checkLoc.y))
|
||||
.event.id || '';
|
||||
// 可以通行
|
||||
if (
|
||||
!noPass ||
|
||||
cls == 'items' ||
|
||||
(id.startsWith('X') && !ignoreInJump.event.includes(id)) ||
|
||||
(bgId.startsWith('X') && !ignoreInJump.bg.includes(bgId))
|
||||
x > core.status.thisMap.width - 1 ||
|
||||
y > core.status.thisMap.height - 1 ||
|
||||
x < 0 ||
|
||||
y < 0
|
||||
)
|
||||
return core.drawTip('当前无法使用技能');
|
||||
// 不是怪物且不可以通行
|
||||
if (noPass && !(cls == 'enemys' || cls == 'enemy48')) {
|
||||
var toLoc = checkNoPass(direction, checkLoc.x, checkLoc.y, true);
|
||||
if (!toLoc) return;
|
||||
core.autosave();
|
||||
if (flags.chapter <= 1) core.status.hero.hp -= 200 * flags.hard;
|
||||
core.updateStatusBar();
|
||||
flags['jump_' + core.status.floorId]++;
|
||||
if (core.status.hero.hp <= 0) {
|
||||
core.status.hero.hp = 0;
|
||||
core.updateStatusBar();
|
||||
core.events.lose('你跳死了');
|
||||
}
|
||||
core.playSound('015-Jump01.ogg');
|
||||
core.insertAction([
|
||||
{ type: 'jumpHero', loc: [toLoc.x, toLoc.y], time: 500 }
|
||||
]);
|
||||
}
|
||||
// 是怪物
|
||||
if (cls == 'enemys' || cls == 'enemy48') {
|
||||
var firstNoPass = checkNoPass(
|
||||
direction,
|
||||
checkLoc.x,
|
||||
checkLoc.y,
|
||||
false
|
||||
);
|
||||
if (!firstNoPass) return;
|
||||
core.autosave();
|
||||
if (flags.chapter <= 1) core.status.hero.hp -= 200 * flags.hard;
|
||||
core.updateStatusBar();
|
||||
flags['jump_' + core.status.floorId]++;
|
||||
if (core.status.hero.hp <= 0) {
|
||||
core.status.hero.hp = 0;
|
||||
core.updateStatusBar();
|
||||
core.events.lose('你跳死了');
|
||||
}
|
||||
core.playSound('015-Jump01.ogg');
|
||||
core.insertAction([
|
||||
{
|
||||
type: 'jump',
|
||||
from: [checkLoc.x, checkLoc.y],
|
||||
to: [firstNoPass.x, firstNoPass.y],
|
||||
time: 500,
|
||||
keep: true
|
||||
}
|
||||
]);
|
||||
}
|
||||
// 检查一条线上的不可通过
|
||||
function checkNoPass(direction, x, y, startNo) {
|
||||
if (!startNo) startNo = false;
|
||||
switch (direction) {
|
||||
case 'up':
|
||||
y--;
|
||||
break;
|
||||
case 'right':
|
||||
x++;
|
||||
break;
|
||||
case 'down':
|
||||
y++;
|
||||
break;
|
||||
case 'left':
|
||||
x--;
|
||||
break;
|
||||
}
|
||||
if (
|
||||
x > core.status.thisMap.width - 1 ||
|
||||
y > core.status.thisMap.height - 1 ||
|
||||
x < 0 ||
|
||||
y < 0
|
||||
)
|
||||
return core.drawTip('当前无法使用技能');
|
||||
var id = core.getBlockId(x, y) || '';
|
||||
if (core.getBgNumber(x, y))
|
||||
var bgId =
|
||||
core.getBlockByNumber(core.getBgNumber(x, y)).event.id ||
|
||||
'';
|
||||
else var bgId = '';
|
||||
if (
|
||||
core.noPass(x, y) ||
|
||||
core.getBlockCls(x, y) == 'items' ||
|
||||
(id.startsWith('X') && !ignoreInJump.event.includes(id)) ||
|
||||
(bgId.startsWith('X') && !ignoreInJump.bg.includes(bgId)) ||
|
||||
core.getBlockCls(x, y) == 'animates'
|
||||
)
|
||||
return checkNoPass(direction, x, y, true);
|
||||
if (!startNo) return checkNoPass(direction, x, y, false);
|
||||
return { x: x, y: y };
|
||||
}
|
||||
var id = core.getBlockId(x, y) || '';
|
||||
if (core.getBgNumber(x, y))
|
||||
var bgId =
|
||||
core.getBlockByNumber(core.getBgNumber(x, y)).event.id || '';
|
||||
else var bgId = '';
|
||||
if (
|
||||
core.noPass(x, y) ||
|
||||
core.getBlockCls(x, y) == 'items' ||
|
||||
(id.startsWith('X') && !ignoreInJump.event.includes(id)) ||
|
||||
(bgId.startsWith('X') && !ignoreInJump.bg.includes(bgId)) ||
|
||||
core.getBlockCls(x, y) == 'animates'
|
||||
)
|
||||
return checkNoPass(direction, x, y, true);
|
||||
if (!startNo) return checkNoPass(direction, x, y, false);
|
||||
return { x: x, y: y };
|
||||
}
|
||||
}
|
||||
|
||||
core.plugin.skillEffects = {
|
||||
jumpSkill
|
||||
};
|
||||
})();
|
||||
core.plugin.skillEffects = {
|
||||
jumpSkill
|
||||
};
|
||||
|
@ -1,80 +1,77 @@
|
||||
///<reference path="../../../src/types/core.d.ts" />
|
||||
'use strict';
|
||||
|
||||
(function () {
|
||||
// 负责勇士技能:学习
|
||||
const values = {
|
||||
1: ['crit'],
|
||||
6: ['n'],
|
||||
7: ['hungry'],
|
||||
8: ['together'],
|
||||
10: ['courage'],
|
||||
11: ['charge']
|
||||
};
|
||||
// 负责勇士技能:学习
|
||||
const values = {
|
||||
1: ['crit'],
|
||||
6: ['n'],
|
||||
7: ['hungry'],
|
||||
8: ['together'],
|
||||
10: ['courage'],
|
||||
11: ['charge']
|
||||
};
|
||||
|
||||
const cannotStudy = [9, 12, 14, 15, 24];
|
||||
const cannotStudy = [9, 12, 14, 15, 24];
|
||||
|
||||
function canStudySkill(number) {
|
||||
const s = (core.status.hero.special ??= { num: [], last: [] });
|
||||
if (core.plugin.skillTree.getSkillLevel(11) === 0) return false;
|
||||
if (s.num.length >= 1) return false;
|
||||
if (s.num.includes(number)) return false;
|
||||
if (cannotStudy.includes(number)) return false;
|
||||
return true;
|
||||
}
|
||||
export function canStudySkill(number) {
|
||||
const s = (core.status.hero.special ??= { num: [], last: [] });
|
||||
if (core.plugin.skillTree.getSkillLevel(11) === 0) return false;
|
||||
if (s.num.length >= 1) return false;
|
||||
if (s.num.includes(number)) return false;
|
||||
if (cannotStudy.includes(number)) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
function studySkill(enemy, number) {
|
||||
core.status.hero.special ??= { num: [], last: [] };
|
||||
const s = core.status.hero.special;
|
||||
const specials = core.getSpecials();
|
||||
let special = specials[number - 1][1];
|
||||
if (special instanceof Function) special = special(enemy);
|
||||
if (!canStudySkill(number)) {
|
||||
if (!main.replayChecking) {
|
||||
core.tip('error', `无法学习${special}`);
|
||||
}
|
||||
return;
|
||||
export function studySkill(enemy, number) {
|
||||
core.status.hero.special ??= { num: [], last: [] };
|
||||
const s = core.status.hero.special;
|
||||
const specials = core.getSpecials();
|
||||
let special = specials[number - 1][1];
|
||||
if (special instanceof Function) special = special(enemy);
|
||||
if (!canStudySkill(number)) {
|
||||
if (!main.replayChecking) {
|
||||
core.tip('error', `无法学习${special}`);
|
||||
}
|
||||
s.num.push(number);
|
||||
s.last.push(core.plugin.skillTree.getSkillLevel(11) * 3 + 2);
|
||||
const value = values[number] ?? [];
|
||||
for (const key of value) {
|
||||
s[key] = enemy[key];
|
||||
return;
|
||||
}
|
||||
s.num.push(number);
|
||||
s.last.push(core.plugin.skillTree.getSkillLevel(11) * 3 + 2);
|
||||
const value = values[number] ?? [];
|
||||
for (const key of value) {
|
||||
s[key] = enemy[key];
|
||||
}
|
||||
}
|
||||
|
||||
export function forgetStudiedSkill(num, i) {
|
||||
const s = core.status.hero.special;
|
||||
const index = i !== void 0 && i !== null ? i : s.num.indexOf(num);
|
||||
if (index === -1) return;
|
||||
s.num.splice(index, 1);
|
||||
s.last.splice(index, 1);
|
||||
const value = values[number] ?? [];
|
||||
for (const key of value) {
|
||||
delete s[key];
|
||||
}
|
||||
}
|
||||
|
||||
export function declineStudiedSkill() {
|
||||
const s = (core.status.hero.special ??= { num: [], last: [] });
|
||||
s.last = s.last.map(v => v - 1);
|
||||
}
|
||||
|
||||
export function checkStudiedSkill() {
|
||||
const s = core.status.hero.special;
|
||||
for (let i = 0; i < s.last.length; i++) {
|
||||
if (s.last[i] <= 0) {
|
||||
this.forgetStudiedSkill(void 0, i);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function forgetStudiedSkill(num, i) {
|
||||
const s = core.status.hero.special;
|
||||
const index = i !== void 0 && i !== null ? i : s.num.indexOf(num);
|
||||
if (index === -1) return;
|
||||
s.num.splice(index, 1);
|
||||
s.last.splice(index, 1);
|
||||
const value = values[number] ?? [];
|
||||
for (const key of value) {
|
||||
delete s[key];
|
||||
}
|
||||
}
|
||||
|
||||
function declineStudiedSkill() {
|
||||
const s = (core.status.hero.special ??= { num: [], last: [] });
|
||||
s.last = s.last.map(v => v - 1);
|
||||
}
|
||||
|
||||
function checkStudiedSkill() {
|
||||
const s = core.status.hero.special;
|
||||
for (let i = 0; i < s.last.length; i++) {
|
||||
if (s.last[i] <= 0) {
|
||||
this.forgetStudiedSkill(void 0, i);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
core.plugin.study = {
|
||||
canStudySkill,
|
||||
studySkill,
|
||||
forgetStudiedSkill,
|
||||
declineStudiedSkill,
|
||||
checkStudiedSkill
|
||||
};
|
||||
})();
|
||||
core.plugin.study = {
|
||||
canStudySkill,
|
||||
studySkill,
|
||||
forgetStudiedSkill,
|
||||
declineStudiedSkill,
|
||||
checkStudiedSkill
|
||||
};
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,5 @@
|
||||
///<reference path="../../../src/types/core.d.ts" />
|
||||
'use strict';
|
||||
export {};
|
||||
|
||||
(function () {
|
||||
if (main.replayChecking) return (core.plugin.gameUi = {});
|
||||
|
@ -1,56 +1,53 @@
|
||||
///<reference path="../../../src/types/core.d.ts" />
|
||||
'use strict';
|
||||
|
||||
(function () {
|
||||
/**
|
||||
* 滑动数组
|
||||
* @param {any[]} arr
|
||||
* @param {number} delta
|
||||
*/
|
||||
function slide(arr, delta) {
|
||||
if (delta === 0) return arr;
|
||||
delta %= arr.length;
|
||||
if (delta > 0) {
|
||||
arr.unshift(...arr.splice(arr.length - delta, delta));
|
||||
return arr;
|
||||
}
|
||||
if (delta < 0) {
|
||||
arr.push(...arr.splice(0, -delta));
|
||||
return arr;
|
||||
}
|
||||
/**
|
||||
* 滑动数组
|
||||
* @param {any[]} arr
|
||||
* @param {number} delta
|
||||
*/
|
||||
export function slide(arr, delta) {
|
||||
if (delta === 0) return arr;
|
||||
delta %= arr.length;
|
||||
if (delta > 0) {
|
||||
arr.unshift(...arr.splice(arr.length - delta, delta));
|
||||
return arr;
|
||||
}
|
||||
|
||||
function backDir(dir) {
|
||||
return {
|
||||
up: 'down',
|
||||
down: 'up',
|
||||
left: 'right',
|
||||
right: 'left'
|
||||
}[dir];
|
||||
if (delta < 0) {
|
||||
arr.push(...arr.splice(0, -delta));
|
||||
return arr;
|
||||
}
|
||||
}
|
||||
|
||||
function has(v) {
|
||||
return v !== null && v !== void 0;
|
||||
}
|
||||
export function backDir(dir) {
|
||||
return {
|
||||
up: 'down',
|
||||
down: 'up',
|
||||
left: 'right',
|
||||
right: 'left'
|
||||
}[dir];
|
||||
}
|
||||
|
||||
function maxGameScale(n = 0) {
|
||||
const index = core.domStyle.availableScale.indexOf(core.domStyle.scale);
|
||||
core.control.setDisplayScale(
|
||||
core.domStyle.availableScale.length - 1 - index - n
|
||||
export function has(v) {
|
||||
return v !== null && v !== void 0;
|
||||
}
|
||||
|
||||
export function maxGameScale(n = 0) {
|
||||
const index = core.domStyle.availableScale.indexOf(core.domStyle.scale);
|
||||
core.control.setDisplayScale(
|
||||
core.domStyle.availableScale.length - 1 - index - n
|
||||
);
|
||||
if (!core.isPlaying() && core.flags.enableHDCanvas) {
|
||||
core.domStyle.ratio = Math.max(
|
||||
window.devicePixelRatio || 1,
|
||||
core.domStyle.scale
|
||||
);
|
||||
if (!core.isPlaying() && core.flags.enableHDCanvas) {
|
||||
core.domStyle.ratio = Math.max(
|
||||
window.devicePixelRatio || 1,
|
||||
core.domStyle.scale
|
||||
);
|
||||
core.resize();
|
||||
}
|
||||
core.resize();
|
||||
}
|
||||
}
|
||||
|
||||
core.plugin.utils = {
|
||||
slide,
|
||||
backDir,
|
||||
has,
|
||||
maxGameScale
|
||||
};
|
||||
})();
|
||||
core.plugin.utils = {
|
||||
slide,
|
||||
backDir,
|
||||
has,
|
||||
maxGameScale
|
||||
};
|
||||
|
@ -2,8 +2,8 @@ import fs from 'fs/promises';
|
||||
import fss from 'fs';
|
||||
import fse from 'fs-extra';
|
||||
import Fontmin from 'fontmin';
|
||||
import { exec } from 'child_process';
|
||||
import * as babel from '@babel/core';
|
||||
import * as rollup from 'rollup';
|
||||
|
||||
(async function () {
|
||||
// 1. 去除未使用的文件
|
||||
@ -40,7 +40,7 @@ import * as babel from '@babel/core';
|
||||
})
|
||||
);
|
||||
await fse.remove('./dist/maps/');
|
||||
// 编辑器需要留着吗?
|
||||
// 在线查看什么都看不到,这编辑器难道还需要留着吗?
|
||||
} catch {}
|
||||
|
||||
// 2. 压缩字体
|
||||
@ -98,22 +98,23 @@ import * as babel from '@babel/core';
|
||||
|
||||
// 3. 压缩js插件
|
||||
try {
|
||||
exec(
|
||||
`babel ${data.main.plugin
|
||||
.map(v => `./dist/project/plugin/${v}.js`)
|
||||
.join(' ')} --out-file ./dist/project/plugin.m.js`
|
||||
).on('close', async () => {
|
||||
const main = await fs.readFile('./dist/main.js', 'utf-8');
|
||||
await fs.writeFile(
|
||||
'./dist/main.js',
|
||||
main.replace(
|
||||
/this.pluginUseCompress\s*=\s*false\;/,
|
||||
'this.pluginUseCompress = true;'
|
||||
)
|
||||
);
|
||||
await fse.remove('./dist/project/plugin/');
|
||||
const build = await rollup.rollup({
|
||||
input: 'public/project/plugin/index.js'
|
||||
});
|
||||
} catch {
|
||||
const code = await build.generate({
|
||||
format: 'iife',
|
||||
name: 'CorePlugin'
|
||||
});
|
||||
const compressed = babel.transformSync(code.output[0].code)?.code!;
|
||||
await fs.writeFile('./dist/project/plugin.m.js', compressed, 'utf-8');
|
||||
|
||||
const main = await fs.readFile('./dist/main.js', 'utf-8');
|
||||
main.replace(
|
||||
/this.pluginUseCompress\s*=\s*false\;/,
|
||||
'this.pluginUseCompress = true;'
|
||||
);
|
||||
await fse.remove('./dist/project/plugin/');
|
||||
} catch (e) {
|
||||
console.log('压缩插件失败');
|
||||
}
|
||||
|
||||
@ -124,20 +125,8 @@ import * as babel from '@babel/core';
|
||||
const endIndex = main.indexOf('// >>>> body end');
|
||||
const nonCompress = main.slice(0, endIndex);
|
||||
const needCompress = main.slice(endIndex + 17);
|
||||
await fs.writeFile('./dist/temp.js', needCompress, 'utf-8');
|
||||
await fs.rm('./dist/main.js');
|
||||
exec('babel ./dist/temp.js --out-file ./dist/main.js').on(
|
||||
'close',
|
||||
async () => {
|
||||
const nowMain = await fs.readFile('./dist/main.js', 'utf-8');
|
||||
await fs.writeFile(
|
||||
'./dist/main.js',
|
||||
nonCompress + nowMain,
|
||||
'utf-8'
|
||||
);
|
||||
await fs.rm('./dist/temp.js');
|
||||
}
|
||||
);
|
||||
const compressed = babel.transformSync(needCompress)?.code;
|
||||
await fs.writeFile('./dist/main.js', nonCompress + compressed, 'utf-8');
|
||||
} catch {
|
||||
console.log('main.js压缩失败');
|
||||
}
|
@ -1,5 +1,7 @@
|
||||
import { ref, watch } from 'vue';
|
||||
|
||||
// todo 优化,可以考虑改成reactive
|
||||
|
||||
/** 打开和关闭ui时是否展示动画 */
|
||||
export const transition = ref(false);
|
||||
|
||||
|
@ -1,7 +1,8 @@
|
||||
import { power } from 'mutate-animate';
|
||||
import { hyper, power } from 'mutate-animate';
|
||||
import { Polygon } from './polygon';
|
||||
import {
|
||||
Light,
|
||||
animateLight,
|
||||
getAllLights,
|
||||
moveLight,
|
||||
refreshLight,
|
||||
@ -27,7 +28,7 @@ export default function init() {
|
||||
}
|
||||
};
|
||||
|
||||
return { updateShadow, clearShadowCache, setCalShadow, testLight: test };
|
||||
return { updateShadow, clearShadowCache, setCalShadow };
|
||||
}
|
||||
|
||||
const shadowInfo: Partial<Record<FloorIds, Light[]>> = {
|
||||
@ -35,11 +36,10 @@ const shadowInfo: Partial<Record<FloorIds, Light[]>> = {
|
||||
{
|
||||
id: 'mt48_1',
|
||||
x: 0,
|
||||
y: 0,
|
||||
y: 48,
|
||||
decay: 0,
|
||||
r: 300,
|
||||
color: '#0000',
|
||||
followHero: true
|
||||
color: '#0000'
|
||||
}
|
||||
]
|
||||
};
|
||||
@ -153,7 +153,3 @@ export function setCalShadow(n: boolean) {
|
||||
calMapShadow = n;
|
||||
updateShadow();
|
||||
}
|
||||
|
||||
function test() {
|
||||
moveLight('mt48_1', 480, 48, 2000, power(4, 'in-out'));
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user