mirror of
https://github.com/unanmed/HumanBreak.git
synced 2025-03-03 19:27:07 +08:00
refactor: 插件
This commit is contained in:
parent
ef9a3d6537
commit
325a1e85ec
4
idea.md
4
idea.md
@ -100,7 +100,7 @@ dam4.png ---- 存档 59
|
||||
[] 优化各种 ui
|
||||
[] 怪物脚下加入阴影
|
||||
[x] 着色器特效
|
||||
[] 完全删除 core.plugin,采用 Plugin.register 的形式进行插件编写
|
||||
[x] 完全删除 core.plugin,采用 Plugin.register 的形式进行插件编写
|
||||
[] 通用 Addon 接口
|
||||
[] 完善加载系统
|
||||
[] 不同怪物可以在怪物手册中添加一些不同的边框
|
||||
@ -113,5 +113,5 @@ dam4.png ---- 存档 59
|
||||
[] 注册可录像操作,比如可以在点击的时候执行,自动计入录像
|
||||
[] 机关门显示绑定怪物
|
||||
[] 自定义状态栏,通过申请空间进行布局
|
||||
[] 复写 api,rewrite()
|
||||
[x] 复写 api,rewrite()
|
||||
[] 对 vnode 进行简单的包装,提供出显示文字、显示图片等 api 以及修改 css 的 api
|
||||
|
@ -3850,7 +3850,7 @@ isShopVisited_e
|
||||
/* isShopVisited_e
|
||||
default : ['shop1']
|
||||
allShops : ['IdString_0']
|
||||
var code = 'core.plugin.shop.isShopVisited(\'' + IdString_0 + '\')';
|
||||
var code = 'Mota.Plugin.require("shop_g").isShopVisited(\'' + IdString_0 + '\')';
|
||||
return [code, Blockly.JavaScript.ORDER_ATOMIC];
|
||||
*/;
|
||||
|
||||
|
@ -1620,7 +1620,8 @@ actions.prototype._keyUpViewMaps = function (keycode) {
|
||||
|
||||
////// 快捷商店界面时的点击操作 //////
|
||||
actions.prototype._clickQuickShop = function (x, y) {
|
||||
var shopIds = core.plugin.shop.listShopIds();
|
||||
const shop = Mota.Plugin.require('shop_g');
|
||||
var shopIds = shop.listShopIds();
|
||||
if (this._out(x)) return;
|
||||
var topIndex =
|
||||
this._HY_ -
|
||||
@ -1628,15 +1629,15 @@ actions.prototype._clickQuickShop = function (x, y) {
|
||||
(core.status.event.ui.offset || 0);
|
||||
if (y >= topIndex && y < topIndex + shopIds.length) {
|
||||
var shopId = shopIds[y - topIndex];
|
||||
if (!core.plugin.shop.canOpenShop(shopId)) {
|
||||
if (!shop.canOpenShop(shopId)) {
|
||||
core.playSound('操作失败');
|
||||
core.drawTip('当前项尚未开启');
|
||||
return;
|
||||
}
|
||||
var message = core.plugin.shop.canUseQuickShop(shopId);
|
||||
var message = shop.canUseQuickShop(shopId);
|
||||
if (message == null) {
|
||||
// core.ui.closePanel();
|
||||
core.plugin.shop.openShop(shopIds[y - topIndex], false);
|
||||
shop.openShop(shopIds[y - topIndex], false);
|
||||
} else {
|
||||
core.playSound('操作失败');
|
||||
core.drawTip(message);
|
||||
@ -1657,7 +1658,7 @@ actions.prototype._keyUpQuickShop = function (keycode) {
|
||||
return;
|
||||
}
|
||||
this._selectChoices(
|
||||
core.plugin.shop.listShopIds().length + 1,
|
||||
Mota.Plugin.require('shop_g').listShopIds().length + 1,
|
||||
keycode,
|
||||
this._clickQuickShop
|
||||
);
|
||||
|
@ -1449,9 +1449,10 @@ control.prototype.checkBlock = function () {
|
||||
|
||||
control.prototype._checkBlock_disableQuickShop = function () {
|
||||
// 禁用快捷商店
|
||||
const { setShopVisited } = Mota.Plugin.require('shop_g');
|
||||
if (core.flags.disableShopOnDamage) {
|
||||
Object.keys(core.status.shops).forEach(function (shopId) {
|
||||
core.plugin.shop.setShopVisited(shopId, false);
|
||||
setShopVisited(shopId, false);
|
||||
});
|
||||
}
|
||||
};
|
||||
@ -1544,7 +1545,7 @@ control.prototype.startReplay = function (list) {
|
||||
core.status.replay.totalList = core.status.route.concat(list);
|
||||
core.status.replay.steps = 0;
|
||||
core.status.replay.save = [];
|
||||
core.plugin.replay.ready();
|
||||
Mota.Plugin.require('replay_g').ready();
|
||||
core.createCanvas('replay', 0, core._PY_ - 40, core._PX_, 40, 199);
|
||||
core.setOpacity('replay', 0.6);
|
||||
this._replay_drawProgress();
|
||||
|
@ -279,7 +279,7 @@ core.prototype.init = async function (coreData, callback) {
|
||||
this._init_flags();
|
||||
this._init_platform();
|
||||
this._init_others();
|
||||
await this._loadPlugin();
|
||||
await this._loadGameProcess();
|
||||
|
||||
var b = main.mode == 'editor';
|
||||
// 初始化画布
|
||||
@ -307,34 +307,31 @@ core.prototype.initSync = function (coreData, callback) {
|
||||
this._init_flags();
|
||||
this._init_platform();
|
||||
this._init_others();
|
||||
this._loadPluginSync();
|
||||
this._loadGameProcessSync();
|
||||
|
||||
core.loader._load(function () {
|
||||
core._afterLoadResources(callback);
|
||||
});
|
||||
};
|
||||
|
||||
core.prototype._loadPluginSync = function () {
|
||||
core.plugin = {};
|
||||
if (main.useCompress) main.loadMod('project', 'plugin', () => 0);
|
||||
else main.loadMod('project', 'plugin.min', () => 0);
|
||||
};
|
||||
|
||||
core.prototype._loadPlugin = async function () {
|
||||
const mainData = data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d.main;
|
||||
core.plugin = {};
|
||||
// 加载插件
|
||||
core.prototype._loadGameProcess = async function () {
|
||||
// 加载游戏进程代码
|
||||
if (main.pluginUseCompress) {
|
||||
await main.loadScript(`project/plugin.min.js?v=${main.version}`);
|
||||
await main.loadScript(`project/processG.min.js?v=${main.version}`);
|
||||
} else {
|
||||
if (main.mode === 'play') {
|
||||
await main.loadScript(`src/plugin/game/index.js`, true);
|
||||
await main.loadScript(`src/game/index.ts`, true);
|
||||
} else {
|
||||
await main.loadScript(`src/plugin/game/index.esm.js`, true);
|
||||
await main.loadScript(`src/game/index.esm.ts`, true);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
core.prototype._loadGameProcessSync = function () {
|
||||
if (main.useCompress) main.loadMod('project', 'processG', () => 0);
|
||||
else main.loadMod('project', 'processG.min', () => 0);
|
||||
};
|
||||
|
||||
core.prototype._init_flags = function () {
|
||||
core.flags = core.clone(core.data.flags);
|
||||
core.values = core.clone(core.data.values);
|
||||
@ -580,7 +577,6 @@ core.prototype._init_others = function () {
|
||||
|
||||
core.prototype._afterLoadResources = function (callback) {
|
||||
// 初始化地图
|
||||
core.initStatus.maps = core.maps._initMaps();
|
||||
core.control._setRequestAnimationFrame();
|
||||
// 图片裁剪
|
||||
(main.splitImages || []).forEach(function (one) {
|
||||
@ -604,7 +600,7 @@ core.prototype._afterLoadResources = function (callback) {
|
||||
}
|
||||
});
|
||||
|
||||
if (core.plugin._afterLoadResources) core.plugin._afterLoadResources();
|
||||
// if (core.plugin._afterLoadResources) core.plugin._afterLoadResources();
|
||||
core.showStartAnimate();
|
||||
if (callback) callback();
|
||||
};
|
||||
@ -664,8 +660,9 @@ core.prototype._forwardFunc = function (name, funcname) {
|
||||
|
||||
core.prototype.doFunc = function (func, _this) {
|
||||
if (typeof func == 'string') {
|
||||
func = core.plugin[func];
|
||||
_this = core.plugin;
|
||||
throw new Error('Parameter func must be a function.');
|
||||
// func = core.plugin[func];
|
||||
// _this = core.plugin;
|
||||
}
|
||||
return func.apply(_this, Array.prototype.slice.call(arguments, 2));
|
||||
};
|
||||
|
@ -30,7 +30,7 @@ events.prototype.startGame = function (hard, seed, route, callback) {
|
||||
}
|
||||
|
||||
if (main.mode != 'play') return;
|
||||
core.plugin.skillTree.resetSkillLevel();
|
||||
Mota.Plugin.require('skillTree_g').resetSkillLevel();
|
||||
|
||||
// 无动画的开始游戏
|
||||
if (core.flags.startUsingCanvas || route != null) {
|
||||
@ -2079,13 +2079,13 @@ events.prototype._action_unloadEquip = function (data, x, y, prefix) {
|
||||
};
|
||||
|
||||
events.prototype._action_openShop = function (data, x, y, prefix) {
|
||||
core.plugin.shop.setShopVisited(data.id, true);
|
||||
if (data.open) core.plugin.shop.openShop(data.id, true);
|
||||
Mota.Plugin.require('shop_g').setShopVisited(data.id, true);
|
||||
if (data.open) Mota.Plugin.require('shop_g').openShop(data.id, true);
|
||||
core.doAction();
|
||||
};
|
||||
|
||||
events.prototype._action_disableShop = function (data, x, y, prefix) {
|
||||
core.plugin.shop.setShopVisited(data.id, false);
|
||||
Mota.Plugin.require('shop_g').setShopVisited(data.id, false);
|
||||
core.doAction();
|
||||
};
|
||||
|
||||
@ -3272,6 +3272,7 @@ events.prototype.openToolbox = function (fromUserAction) {
|
||||
////// 点击快捷商店按钮时的打开操作 //////
|
||||
events.prototype.openQuickShop = function (fromUserAction) {
|
||||
if (core.isReplaying()) return;
|
||||
const shop = Mota.Plugin.require('shop_g');
|
||||
|
||||
if (Object.keys(core.status.shops).length == 0) {
|
||||
core.playSound('操作失败');
|
||||
@ -3283,18 +3284,18 @@ events.prototype.openQuickShop = function (fromUserAction) {
|
||||
if (Object.keys(core.status.shops).length == 1) {
|
||||
var shopId = Object.keys(core.status.shops)[0];
|
||||
if (core.status.event.id != null) return;
|
||||
if (!core.plugin.shop.canOpenShop(shopId)) {
|
||||
if (!shop.canOpenShop(shopId)) {
|
||||
core.playSound('操作失败');
|
||||
core.drawTip('当前无法打开快捷商店!');
|
||||
return;
|
||||
}
|
||||
var message = core.plugin.shop.canUseQuickShop(shopId);
|
||||
var message = shop.canUseQuickShop(shopId);
|
||||
if (message != null) {
|
||||
core.playSound('操作失败');
|
||||
core.drawTip(message);
|
||||
return;
|
||||
}
|
||||
core.plugin.shop.openShop(shopId, false);
|
||||
shop.openShop(shopId, false);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -3099,13 +3099,14 @@ ui.prototype._drawNotes = function () {
|
||||
|
||||
////// 绘制快捷商店选择栏 //////
|
||||
ui.prototype._drawQuickShop = function () {
|
||||
const shop = Mota.Plugin.require('shop');
|
||||
core.status.event.id = 'selectShop';
|
||||
var shopList = core.status.shops,
|
||||
keys = core.plugin.shop.listShopIds();
|
||||
keys = shop.listShopIds();
|
||||
var choices = keys.map(function (shopId) {
|
||||
return {
|
||||
text: shopList[shopId].textInList,
|
||||
color: core.plugin.shop.isShopVisited(shopId) ? null : '#999999'
|
||||
color: shop.isShopVisited(shopId) ? null : '#999999'
|
||||
};
|
||||
});
|
||||
choices.push('返回游戏');
|
||||
|
@ -404,6 +404,7 @@ main.prototype.loadAsync = async function (mode, callback) {
|
||||
});
|
||||
await core.init(coreData, callback);
|
||||
if (main.mode === 'play') main.loading.emit('coreInit');
|
||||
core.initStatus.maps = core.maps._initMaps();
|
||||
|
||||
core.resize();
|
||||
|
||||
@ -414,7 +415,7 @@ main.prototype.loadAsync = async function (mode, callback) {
|
||||
|
||||
if (auto && !core.domStyle.isVertical) {
|
||||
try {
|
||||
core.plugin.utils.maxGameScale();
|
||||
Mota.Plugin.require('utils_g').maxGameScale();
|
||||
requestAnimationFrame(() => {
|
||||
var style = getComputedStyle(main.dom.gameGroup);
|
||||
var height = parseFloat(style.height);
|
||||
|
@ -413,7 +413,7 @@ main.floors.MT16=
|
||||
"这里是漏怪检测,将会检测\r[gold]洞穴、山路、山脚、平原\r[white]地区的怪物是否清完",
|
||||
{
|
||||
"type": "function",
|
||||
"function": "function(){\nconst enemy = core.plugin.remainEnemy.getRemainEnemyString(core.floorIds.slice(5, 17));\nif (enemy.length === 0) {\n\tcore.insertAction(['当前无剩余怪物!', { \"type\": \"hide\", \"remove\": true }, ]);\n} else {\n\tcore.insertAction(enemy);\n}\n}"
|
||||
"function": "function(){\nconst enemy = Mota.Plugin.require('remainEnemy_g').getRemainEnemyString(core.floorIds.slice(5, 17));\nif (enemy.length === 0) {\n\tcore.insertAction(['当前无剩余怪物!', { \"type\": \"hide\", \"remove\": true }, ]);\n} else {\n\tcore.insertAction(enemy);\n}\n}"
|
||||
},
|
||||
{
|
||||
"type": "loadBgm",
|
||||
|
@ -148,7 +148,7 @@ main.floors.MT31=
|
||||
"这里是漏怪检测,会检测\r[gold]勇气之路\r[]区域是否有遗漏怪物",
|
||||
{
|
||||
"type": "function",
|
||||
"function": "function(){\nconst enemy = core.plugin.remainEnemy.getRemainEnemyString(core.floorIds.slice(17, 22));\nif (enemy.length === 0) {\n\tcore.insertAction(['当前无剩余怪物!', { \"type\": \"hide\", \"remove\": true }, ]);\n} else {\n\tcore.insertAction(enemy);\n}\n}"
|
||||
"function": "function(){\nconst enemy = Mota.Plugin.require('remainEnemy_g').getRemainEnemyString(core.floorIds.slice(17, 22));\nif (enemy.length === 0) {\n\tcore.insertAction(['当前无剩余怪物!', { \"type\": \"hide\", \"remove\": true }, ]);\n} else {\n\tcore.insertAction(enemy);\n}\n}"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -76,7 +76,7 @@ main.floors.MT35=
|
||||
"这里是漏怪检测,会检测\r[gold]智慧小径\r[]区域是否有遗漏怪物",
|
||||
{
|
||||
"type": "function",
|
||||
"function": "function(){\nconst enemy = core.plugin.remainEnemy.getRemainEnemyString(core.floorIds.slice(30, 40));\nif (enemy.length === 0) {\n\tcore.insertAction(['当前无剩余怪物!', { \"type\": \"hide\", \"remove\": true }, ]);\n} else {\n\tcore.insertAction(enemy);\n}\n}"
|
||||
"function": "function(){\nconst enemy = Mota.Plugin.require('remainEnemy_g').getRemainEnemyString(core.floorIds.slice(30, 40));\nif (enemy.length === 0) {\n\tcore.insertAction(['当前无剩余怪物!', { \"type\": \"hide\", \"remove\": true }, ]);\n} else {\n\tcore.insertAction(enemy);\n}\n}"
|
||||
}
|
||||
],
|
||||
"7,0": [
|
||||
|
@ -120,7 +120,7 @@ main.floors.MT5=
|
||||
"这里是漏怪检测,会检测\r[gold]山洞\r[]区域的怪物是否清空",
|
||||
{
|
||||
"type": "function",
|
||||
"function": "function(){\nconst enemy = core.plugin.remainEnemy.getRemainEnemyString(core.floorIds.slice(0, 5));\nif (enemy.length === 0) {\n\tcore.insertAction(['当前无剩余怪物!', { \"type\": \"hide\", \"remove\": true }, ]);\n} else {\n\tcore.insertAction(enemy);\n}\n}"
|
||||
"function": "function(){\nconst enemy = Mota.Plugin.require('remainEnemy_g').getRemainEnemyString(core.floorIds.slice(0, 5));\nif (enemy.length === 0) {\n\tcore.insertAction(['当前无剩余怪物!', { \"type\": \"hide\", \"remove\": true }, ]);\n} else {\n\tcore.insertAction(enemy);\n}\n}"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -21,7 +21,7 @@ main.floors.tower5=
|
||||
"这里是漏怪检测,会检测\r[gold]智慧之塔\r[]区域是否有遗漏怪物",
|
||||
{
|
||||
"type": "function",
|
||||
"function": "function(){\nconst enemy = core.plugin.remainEnemy.getRemainEnemyString([\"tower1\", \"tower2\", \"tower3\", \"tower4\", \"tower5\", \"tower6\"]);\nif (enemy.length === 0) {\n\tcore.insertAction(['当前无剩余怪物!', { \"type\": \"hide\", \"remove\": true }, ]);\n} else {\n\tcore.insertAction(enemy);\n}\n}"
|
||||
"function": "function(){\nconst enemy = Mota.Plugin.require('remainEnemy_g').getRemainEnemyString([\"tower1\", \"tower2\", \"tower3\", \"tower4\", \"tower5\", \"tower6\"]);\nif (enemy.length === 0) {\n\tcore.insertAction(['当前无剩余怪物!', { \"type\": \"hide\", \"remove\": true }, ]);\n} else {\n\tcore.insertAction(enemy);\n}\n}"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -50,7 +50,7 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = {
|
||||
core.hideStatusBar(core.hasFlag('showToolbox'));
|
||||
else core.showStatusBar();
|
||||
if (main.mode === 'play' && !main.replayChecking) {
|
||||
Mota.Plugin.require('fly').splitArea();
|
||||
Mota.Plugin.require('fly_r').splitArea();
|
||||
Mota.require('var', 'hook').emit('reset');
|
||||
} else {
|
||||
flags.autoSkill ??= true;
|
||||
@ -113,7 +113,7 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = {
|
||||
// 正在切换楼层过程中执行的操作;此函数的执行时间是“屏幕完全变黑“的那一刻
|
||||
// floorId为要切换到的楼层ID;heroLoc表示勇士切换到的位置
|
||||
|
||||
const { checkLoopMap } = core.plugin.loopMap;
|
||||
const { checkLoopMap } = Mota.Plugin.require('loopMap_g');
|
||||
|
||||
flags.floorChanging = true;
|
||||
|
||||
@ -131,8 +131,7 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = {
|
||||
}
|
||||
|
||||
// 根据分区信息自动砍层与恢复
|
||||
if (core.plugin.removeMap.autoRemoveMaps)
|
||||
core.plugin.removeMap.autoRemoveMaps(floorId);
|
||||
Mota.Plugin.require('removeMap_g')?.autoRemoveMaps?.(floorId);
|
||||
|
||||
// 重置画布尺寸
|
||||
core.maps.resizeMap(floorId);
|
||||
@ -201,7 +200,7 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = {
|
||||
}
|
||||
}
|
||||
if (!flags.debug && !main.replayChecking)
|
||||
Mota.Plugin.require('completion').checkVisitedFloor();
|
||||
Mota.Plugin.require('completion_r').checkVisitedFloor();
|
||||
},
|
||||
flyTo: function (toId, callback) {
|
||||
// 楼层传送器的使用,从当前楼层飞往toId
|
||||
@ -279,7 +278,7 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = {
|
||||
version: core.firstData.version,
|
||||
guid: core.getGuid(),
|
||||
time: new Date().getTime(),
|
||||
skills: core.plugin.skillTree.saveSkillTree()
|
||||
skills: Mota.Plugin.require('skillTree_g').saveSkillTree()
|
||||
};
|
||||
|
||||
return data;
|
||||
@ -327,7 +326,7 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = {
|
||||
}
|
||||
core.setFlag('__fromLoad__', true);
|
||||
|
||||
core.plugin.skillTree.loadSkillTree(data.skills);
|
||||
Mota.Plugin.require('skillTree_g').loadSkillTree(data.skills);
|
||||
|
||||
// 切换到对应的楼层
|
||||
core.changeFloor(data.floorId, null, data.hero.loc, 0, function () {
|
||||
@ -340,7 +339,7 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = {
|
||||
if (callback) callback();
|
||||
|
||||
if (flags.onChase) {
|
||||
Mota.Plugin.require('chase').startChase(flags.chaseIndex);
|
||||
Mota.Plugin.require('chase_r').startChase(flags.chaseIndex);
|
||||
if (flags.chaseIndex === 1) {
|
||||
core.playBgm('escape.mp3', 43.5);
|
||||
}
|
||||
@ -388,7 +387,7 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = {
|
||||
// 2, 将楼层属性中的cannotMoveDirectly这个开关勾上,即禁止在该层楼使用瞬移。
|
||||
// 3. 将flag:cannotMoveDirectly置为true,即可使用flag控制在某段剧情范围内禁止瞬移。
|
||||
|
||||
const { checkLoopMap } = core.plugin.loopMap;
|
||||
const { checkLoopMap } = Mota.Plugin.require('loopMap_g');
|
||||
|
||||
// 增加步数
|
||||
core.status.hero.steps++;
|
||||
|
@ -40,8 +40,8 @@ var items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a =
|
||||
"cls": "items",
|
||||
"name": "小绿宝石",
|
||||
"text": ",护盾+${core.values.greenGem}",
|
||||
"itemEffect": "core.status.hero.mdef += 20 * core.status.thisMap.ratio / core.getFlag(\"hard\") * (core.plugin.skillTree.getSkillLevel(12) / 20 + 1)",
|
||||
"itemEffectTip": ",智慧+${20 * core.status.thisMap.ratio / core.getFlag(\"hard\") * (core.plugin.skillTree.getSkillLevel(12) / 20 + 1)}",
|
||||
"itemEffect": "core.status.hero.mdef += 20 * core.status.thisMap.ratio / core.getFlag(\"hard\") * (Mota.Plugin.require('skillTree_g').getSkillLevel(12) / 20 + 1)",
|
||||
"itemEffectTip": ",智慧+${20 * core.status.thisMap.ratio / core.getFlag(\"hard\") * (Mota.Plugin.require('skillTree_g').getSkillLevel(12) / 20 + 1)}",
|
||||
"useItemEffect": "core.status.hero.mdef += core.values.greenGem",
|
||||
"canUseItemEffect": "true"
|
||||
},
|
||||
@ -97,8 +97,8 @@ var items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a =
|
||||
"cls": "items",
|
||||
"name": "红血瓶",
|
||||
"text": ",生命+${core.values.redPotion}",
|
||||
"itemEffect": "core.status.hero.hp += 100 * core.status.thisMap.ratio * (1 + core.plugin.skillTree.getSkillLevel(13) / 50)",
|
||||
"itemEffectTip": ",生命+${100 * core.status.thisMap.ratio * (1 + core.plugin.skillTree.getSkillLevel(13) / 50)}",
|
||||
"itemEffect": "core.status.hero.hp += 100 * core.status.thisMap.ratio * (1 + Mota.Plugin.require('skillTree_g').getSkillLevel(13) / 50)",
|
||||
"itemEffectTip": ",生命+${100 * core.status.thisMap.ratio * (1 + Mota.Plugin.require('skillTree_g').getSkillLevel(13) / 50)}",
|
||||
"useItemEffect": "core.status.hero.hp += core.values.redPotion",
|
||||
"canUseItemEffect": "true"
|
||||
},
|
||||
@ -106,8 +106,8 @@ var items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a =
|
||||
"cls": "items",
|
||||
"name": "蓝血瓶",
|
||||
"text": ",生命+${core.values.bluePotion}",
|
||||
"itemEffect": "core.status.hero.hp += 200 * core.status.thisMap.ratio * (1 + core.plugin.skillTree.getSkillLevel(13) / 50)",
|
||||
"itemEffectTip": ",生命+${200 * core.status.thisMap.ratio * (1 + core.plugin.skillTree.getSkillLevel(13) / 50)}",
|
||||
"itemEffect": "core.status.hero.hp += 200 * core.status.thisMap.ratio * (1 + Mota.Plugin.require('skillTree_g').getSkillLevel(13) / 50)",
|
||||
"itemEffectTip": ",生命+${200 * core.status.thisMap.ratio * (1 + Mota.Plugin.require('skillTree_g').getSkillLevel(13) / 50)}",
|
||||
"useItemEffect": "core.status.hero.hp += core.values.bluePotion",
|
||||
"canUseItemEffect": "true"
|
||||
},
|
||||
@ -115,8 +115,8 @@ var items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a =
|
||||
"cls": "items",
|
||||
"name": "黄血瓶",
|
||||
"text": ",生命+${core.values.yellowPotion}",
|
||||
"itemEffect": "core.status.hero.hp += 400 * core.status.thisMap.ratio * (1 + core.plugin.skillTree.getSkillLevel(13) / 50)",
|
||||
"itemEffectTip": ",生命+${400 * core.status.thisMap.ratio * (1 + core.plugin.skillTree.getSkillLevel(13) / 50)}",
|
||||
"itemEffect": "core.status.hero.hp += 400 * core.status.thisMap.ratio * (1 + Mota.Plugin.require('skillTree_g').getSkillLevel(13) / 50)",
|
||||
"itemEffectTip": ",生命+${400 * core.status.thisMap.ratio * (1 + Mota.Plugin.require('skillTree_g').getSkillLevel(13) / 50)}",
|
||||
"useItemEffect": "core.status.hero.hp += core.values.yellowPotion",
|
||||
"canUseItemEffect": "true"
|
||||
},
|
||||
@ -124,8 +124,8 @@ var items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a =
|
||||
"cls": "items",
|
||||
"name": "绿血瓶",
|
||||
"text": ",生命+${core.values.greenPotion}",
|
||||
"itemEffect": "core.status.hero.hp += 800 * core.status.thisMap.ratio * (1 + core.plugin.skillTree.getSkillLevel(13) / 50)",
|
||||
"itemEffectTip": ",生命+${800 * core.status.thisMap.ratio * (1 + core.plugin.skillTree.getSkillLevel(13) / 50)}",
|
||||
"itemEffect": "core.status.hero.hp += 800 * core.status.thisMap.ratio * (1 + Mota.Plugin.require('skillTree_g').getSkillLevel(13) / 50)",
|
||||
"itemEffectTip": ",生命+${800 * core.status.thisMap.ratio * (1 + Mota.Plugin.require('skillTree_g').getSkillLevel(13) / 50)}",
|
||||
"useItemEffect": "core.status.hero.hp += core.values.greenPotion",
|
||||
"canUseItemEffect": "true"
|
||||
},
|
||||
@ -349,7 +349,7 @@ var items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a =
|
||||
"name": "查看技能",
|
||||
"text": "查看勇士的技能",
|
||||
"canUseItemEffect": true,
|
||||
"useItemEffect": "core.plugin.gameUi.openSkill();"
|
||||
"useItemEffect": "Mota.Plugin.require('gameUi_g').openSkill();"
|
||||
},
|
||||
"dagger": {
|
||||
"cls": "constants",
|
||||
@ -522,7 +522,7 @@ var items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a =
|
||||
"name": "技能树",
|
||||
"text": "打开技能树",
|
||||
"hideInReplay": true,
|
||||
"useItemEffect": "core.plugin.skillTree.openTree();",
|
||||
"useItemEffect": "Mota.Plugin.require('skillTree_g').openTree();",
|
||||
"canUseItemEffect": "true"
|
||||
},
|
||||
"wand": {
|
||||
@ -626,8 +626,8 @@ var items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a =
|
||||
"cls": "items",
|
||||
"name": "中绿宝石",
|
||||
"text": ",护盾+${core.values.greenGem}",
|
||||
"itemEffect": "core.status.hero.mdef += 40 * core.status.thisMap.ratio / core.getFlag(\"hard\") * (core.plugin.skillTree.getSkillLevel(12) / 20 + 1)",
|
||||
"itemEffectTip": ",智慧+${40 * core.status.thisMap.ratio / core.getFlag(\"hard\") * (core.plugin.skillTree.getSkillLevel(12) / 20 + 1)}",
|
||||
"itemEffect": "core.status.hero.mdef += 40 * core.status.thisMap.ratio / core.getFlag(\"hard\") * (Mota.Plugin.require('skillTree_g').getSkillLevel(12) / 20 + 1)",
|
||||
"itemEffectTip": ",智慧+${40 * core.status.thisMap.ratio / core.getFlag(\"hard\") * (Mota.Plugin.require('skillTree_g').getSkillLevel(12) / 20 + 1)}",
|
||||
"useItemEffect": "core.status.hero.mdef += core.values.greenGem",
|
||||
"canUseItemEffect": "true"
|
||||
},
|
||||
@ -729,8 +729,8 @@ var items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a =
|
||||
"cls": "items",
|
||||
"name": "大绿宝石",
|
||||
"text": ",护盾+${core.values.greenGem}",
|
||||
"itemEffect": "core.status.hero.mdef += 80 * core.status.thisMap.ratio / core.getFlag(\"hard\") * (core.plugin.skillTree.getSkillLevel(12) / 20 + 1)",
|
||||
"itemEffectTip": ",智慧+${80 * core.status.thisMap.ratio / core.getFlag(\"hard\") * (core.plugin.skillTree.getSkillLevel(12) / 20 + 1)}",
|
||||
"itemEffect": "core.status.hero.mdef += 80 * core.status.thisMap.ratio / core.getFlag(\"hard\") * (Mota.Plugin.require('skillTree_g').getSkillLevel(12) / 20 + 1)",
|
||||
"itemEffectTip": ",智慧+${80 * core.status.thisMap.ratio / core.getFlag(\"hard\") * (Mota.Plugin.require('skillTree_g').getSkillLevel(12) / 20 + 1)}",
|
||||
"useItemEffect": "core.status.hero.mdef += core.values.greenGem",
|
||||
"canUseItemEffect": "true"
|
||||
},
|
||||
@ -896,8 +896,8 @@ var items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a =
|
||||
"cls": "items",
|
||||
"name": "超大绿宝石",
|
||||
"text": ",护盾+${core.values.greenGem}",
|
||||
"itemEffect": "core.status.hero.mdef += 160 * core.status.thisMap.ratio / core.getFlag(\"hard\") * (core.plugin.skillTree.getSkillLevel(12) / 20 + 1)",
|
||||
"itemEffectTip": ",智慧+${160 * core.status.thisMap.ratio / core.getFlag(\"hard\") * (core.plugin.skillTree.getSkillLevel(12) / 20 + 1)}",
|
||||
"itemEffect": "core.status.hero.mdef += 160 * core.status.thisMap.ratio / core.getFlag(\"hard\") * (Mota.Plugin.require('skillTree_g').getSkillLevel(12) / 20 + 1)",
|
||||
"itemEffectTip": ",智慧+${160 * core.status.thisMap.ratio / core.getFlag(\"hard\") * (Mota.Plugin.require('skillTree_g').getSkillLevel(12) / 20 + 1)}",
|
||||
"useItemEffect": "core.status.hero.mdef += core.values.greenGem",
|
||||
"canUseItemEffect": "true"
|
||||
},
|
||||
@ -1019,8 +1019,8 @@ var items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a =
|
||||
"cls": "items",
|
||||
"name": "璀璨绿宝石",
|
||||
"text": ",护盾+${core.values.greenGem}",
|
||||
"itemEffect": "core.status.hero.mdef += 320 * core.status.thisMap.ratio / core.getFlag(\"hard\") * (core.plugin.skillTree.getSkillLevel(12) / 20 + 1)",
|
||||
"itemEffectTip": ",智慧+${320 * core.status.thisMap.ratio / core.getFlag(\"hard\") * (core.plugin.skillTree.getSkillLevel(12) / 20 + 1)}",
|
||||
"itemEffect": "core.status.hero.mdef += 320 * core.status.thisMap.ratio / core.getFlag(\"hard\") * (Mota.Plugin.require('skillTree_g').getSkillLevel(12) / 20 + 1)",
|
||||
"itemEffectTip": ",智慧+${320 * core.status.thisMap.ratio / core.getFlag(\"hard\") * (Mota.Plugin.require('skillTree_g').getSkillLevel(12) / 20 + 1)}",
|
||||
"useItemEffect": "core.status.hero.mdef += core.values.greenGem",
|
||||
"canUseItemEffect": "true"
|
||||
},
|
||||
@ -1050,8 +1050,8 @@ var items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a =
|
||||
"cls": "items",
|
||||
"name": "新物品",
|
||||
"text": ",防御+${core.values.blueGem}",
|
||||
"itemEffect": "core.status.hero.mdef += 640 * core.status.thisMap.ratio / core.getFlag(\"hard\") * (core.plugin.skillTree.getSkillLevel(12) / 20 + 1)",
|
||||
"itemEffectTip": ",智慧+${640 * core.status.thisMap.ratio / core.getFlag(\"hard\") * (core.plugin.skillTree.getSkillLevel(12) / 20 + 1)}",
|
||||
"itemEffect": "core.status.hero.mdef += 640 * core.status.thisMap.ratio / core.getFlag(\"hard\") * (Mota.Plugin.require('skillTree_g').getSkillLevel(12) / 20 + 1)",
|
||||
"itemEffectTip": ",智慧+${640 * core.status.thisMap.ratio / core.getFlag(\"hard\") * (Mota.Plugin.require('skillTree_g').getSkillLevel(12) / 20 + 1)}",
|
||||
"useItemEffect": "core.status.hero.def += core.values.blueGem",
|
||||
"canUseItemEffect": "true"
|
||||
},
|
||||
@ -1071,8 +1071,8 @@ var items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a =
|
||||
"cls": "items",
|
||||
"name": "史诗绿宝石",
|
||||
"text": ",护盾+${core.values.greenGem}",
|
||||
"itemEffect": "core.status.hero.mdef += 1280 * core.status.thisMap.ratio / core.getFlag(\"hard\") * (core.plugin.skillTree.getSkillLevel(12) / 20 + 1)",
|
||||
"itemEffectTip": ",智慧+${1280 * core.status.thisMap.ratio / core.getFlag(\"hard\") * (core.plugin.skillTree.getSkillLevel(12) / 20 + 1)}",
|
||||
"itemEffect": "core.status.hero.mdef += 1280 * core.status.thisMap.ratio / core.getFlag(\"hard\") * (Mota.Plugin.require('skillTree_g').getSkillLevel(12) / 20 + 1)",
|
||||
"itemEffectTip": ",智慧+${1280 * core.status.thisMap.ratio / core.getFlag(\"hard\") * (Mota.Plugin.require('skillTree_g').getSkillLevel(12) / 20 + 1)}",
|
||||
"useItemEffect": "core.status.hero.mdef += core.values.greenGem",
|
||||
"canUseItemEffect": "true"
|
||||
},
|
||||
@ -1100,8 +1100,8 @@ var items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a =
|
||||
"cls": "items",
|
||||
"name": "大红血瓶",
|
||||
"text": ",生命+${core.values.redPotion}",
|
||||
"itemEffect": "core.status.hero.hp += 1000 * core.status.thisMap.ratio * (1 + core.plugin.skillTree.getSkillLevel(13) / 50)",
|
||||
"itemEffectTip": ",生命+${1000 * core.status.thisMap.ratio * (1 + core.plugin.skillTree.getSkillLevel(13) / 50)}",
|
||||
"itemEffect": "core.status.hero.hp += 1000 * core.status.thisMap.ratio * (1 + Mota.Plugin.require('skillTree_g').getSkillLevel(13) / 50)",
|
||||
"itemEffectTip": ",生命+${1000 * core.status.thisMap.ratio * (1 + Mota.Plugin.require('skillTree_g').getSkillLevel(13) / 50)}",
|
||||
"useItemEffect": "core.status.hero.hp += core.values.redPotion",
|
||||
"canUseItemEffect": "true"
|
||||
},
|
||||
@ -1113,8 +1113,8 @@ var items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a =
|
||||
"cls": "items",
|
||||
"name": "大蓝血瓶",
|
||||
"text": ",生命+${core.values.redPotion}",
|
||||
"itemEffect": "core.status.hero.hp += 2000 * core.status.thisMap.ratio * (1 + core.plugin.skillTree.getSkillLevel(13) / 50)",
|
||||
"itemEffectTip": ",生命+${2000 * core.status.thisMap.ratio * (1 + core.plugin.skillTree.getSkillLevel(13) / 50)}",
|
||||
"itemEffect": "core.status.hero.hp += 2000 * core.status.thisMap.ratio * (1 + Mota.Plugin.require('skillTree_g').getSkillLevel(13) / 50)",
|
||||
"itemEffectTip": ",生命+${2000 * core.status.thisMap.ratio * (1 + Mota.Plugin.require('skillTree_g').getSkillLevel(13) / 50)}",
|
||||
"useItemEffect": "core.status.hero.hp += core.values.redPotion",
|
||||
"canUseItemEffect": "true"
|
||||
},
|
||||
@ -1130,8 +1130,8 @@ var items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a =
|
||||
"cls": "items",
|
||||
"name": "大绿血瓶",
|
||||
"text": ",生命+${core.values.redPotion}",
|
||||
"itemEffect": "core.status.hero.hp += 8000 * core.status.thisMap.ratio * (1 + core.plugin.skillTree.getSkillLevel(13) / 50)",
|
||||
"itemEffectTip": ",生命+${8000 * core.status.thisMap.ratio * (1 + core.plugin.skillTree.getSkillLevel(13) / 50)}",
|
||||
"itemEffect": "core.status.hero.hp += 8000 * core.status.thisMap.ratio * (1 + Mota.Plugin.require('skillTree_g').getSkillLevel(13) / 50)",
|
||||
"itemEffectTip": ",生命+${8000 * core.status.thisMap.ratio * (1 + Mota.Plugin.require('skillTree_g').getSkillLevel(13) / 50)}",
|
||||
"useItemEffect": "core.status.hero.hp += core.values.redPotion",
|
||||
"canUseItemEffect": "true"
|
||||
},
|
||||
@ -1151,8 +1151,8 @@ var items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a =
|
||||
"cls": "items",
|
||||
"name": "大黄血瓶",
|
||||
"text": ",生命+${core.values.redPotion}",
|
||||
"itemEffect": "core.status.hero.hp += 4000 * core.status.thisMap.ratio * (1 + core.plugin.skillTree.getSkillLevel(13) / 50)",
|
||||
"itemEffectTip": ",生命+${4000 * core.status.thisMap.ratio * (1 + core.plugin.skillTree.getSkillLevel(13) / 50)}",
|
||||
"itemEffect": "core.status.hero.hp += 4000 * core.status.thisMap.ratio * (1 + Mota.Plugin.require('skillTree_g').getSkillLevel(13) / 50)",
|
||||
"itemEffectTip": ",生命+${4000 * core.status.thisMap.ratio * (1 + Mota.Plugin.require('skillTree_g').getSkillLevel(13) / 50)}",
|
||||
"useItemEffect": "core.status.hero.hp += core.values.redPotion",
|
||||
"canUseItemEffect": "true"
|
||||
},
|
||||
@ -1181,7 +1181,7 @@ var items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a =
|
||||
"cls": "constants",
|
||||
"name": "学习",
|
||||
"canUseItemEffect": "true",
|
||||
"text": "可以学习怪物的技能,学习后持续${core.plugin.skillTree.getSkillLevel(11) * 3 + 2}场战斗"
|
||||
"text": "可以学习怪物的技能,学习后持续${Mota.Plugin.require('skillTree_g').getSkillLevel(11) * 3 + 2}场战斗"
|
||||
},
|
||||
"I574": {
|
||||
"cls": "items",
|
||||
|
@ -19,28 +19,31 @@ import { gameKey } from './main/init/hotkey';
|
||||
import { mainSetting, settingStorage } from './main/setting';
|
||||
import { isMobile } from '../plugin/use';
|
||||
import { KeyCode } from '@/plugin/keyCodes';
|
||||
import { status } from '@/plugin/ui/statusBar';
|
||||
import './plugin';
|
||||
import './package';
|
||||
|
||||
interface AncTePlugin {
|
||||
pop: ReturnType<typeof import('../plugin/pop').default>;
|
||||
use: ReturnType<typeof import('../plugin/use').default>;
|
||||
animate: ReturnType<typeof import('../plugin/animateController').default>;
|
||||
utils: ReturnType<typeof import('../plugin/utils').default>;
|
||||
status: ReturnType<typeof import('../plugin/ui/statusBar').default>;
|
||||
fly: ReturnType<typeof import('../plugin/ui/fly').default>;
|
||||
chase: ReturnType<typeof import('../plugin/chase/chase').default>;
|
||||
webglUtils: ReturnType<typeof import('../plugin/webgl/utils').default>;
|
||||
shadow: ReturnType<typeof import('../plugin/shadow/shadow').default>;
|
||||
gameShadow: ReturnType<
|
||||
typeof import('../plugin/shadow/gameShadow').default
|
||||
>;
|
||||
achievement: ReturnType<typeof import('../plugin/ui/achievement').default>;
|
||||
completion: ReturnType<typeof import('../plugin/completion').default>;
|
||||
path: ReturnType<typeof import('../plugin/fx/path').default>;
|
||||
gameCanvas: ReturnType<typeof import('../plugin/fx/gameCanvas').default>;
|
||||
noise: ReturnType<typeof import('../plugin/fx/noise').default>;
|
||||
smooth: ReturnType<typeof import('../plugin/fx/smoothView').default>;
|
||||
frag: ReturnType<typeof import('../plugin/fx/frag').default>;
|
||||
}
|
||||
// interface AncTePlugin {
|
||||
// pop: ReturnType<typeof import('../plugin/pop').default>;
|
||||
// use: ReturnType<typeof import('../plugin/use').default>;
|
||||
// animate: ReturnType<typeof import('../plugin/animateController').default>;
|
||||
// utils: ReturnType<typeof import('../plugin/utils').default>;
|
||||
// status: ReturnType<typeof import('../plugin/ui/statusBar').default>;
|
||||
// fly: ReturnType<typeof import('../plugin/ui/fly').default>;
|
||||
// chase: ReturnType<typeof import('../plugin/chase/chase').default>;
|
||||
// webglUtils: ReturnType<typeof import('../plugin/webgl/utils').default>;
|
||||
// shadow: ReturnType<typeof import('../plugin/shadow/shadow').default>;
|
||||
// gameShadow: ReturnType<
|
||||
// typeof import('../plugin/shadow/gameShadow').default
|
||||
// >;
|
||||
// achievement: ReturnType<typeof import('../plugin/ui/achievement').default>;
|
||||
// completion: ReturnType<typeof import('../plugin/completion').default>;
|
||||
// path: ReturnType<typeof import('../plugin/fx/path').default>;
|
||||
// gameCanvas: ReturnType<typeof import('../plugin/fx/gameCanvas').default>;
|
||||
// noise: ReturnType<typeof import('../plugin/fx/noise').default>;
|
||||
// smooth: ReturnType<typeof import('../plugin/fx/smoothView').default>;
|
||||
// frag: ReturnType<typeof import('../plugin/fx/frag').default>;
|
||||
// }
|
||||
|
||||
// export interface Mota {
|
||||
// sound: SoundController;
|
||||
@ -93,3 +96,4 @@ Mota.register('var', 'KeyCode', KeyCode);
|
||||
Mota.register('var', 'resource', resource);
|
||||
Mota.register('var', 'zipResource', zipResource);
|
||||
Mota.register('var', 'settingStorage', settingStorage);
|
||||
Mota.register('var', 'status', status);
|
||||
|
@ -16,6 +16,7 @@ const showFixed = debounce((block: Block) => {
|
||||
const e = core.material.enemys[block.event.id as EnemyIds];
|
||||
if (!e) return;
|
||||
const enemy = core.status.thisMap.enemy.get(block.x, block.y);
|
||||
if (!enemy) return;
|
||||
fixedUi.open(
|
||||
'fixed',
|
||||
{ enemy, close, loc: [cx, cy] },
|
||||
|
15
src/core/package.ts
Normal file
15
src/core/package.ts
Normal file
@ -0,0 +1,15 @@
|
||||
import * as axios from 'axios';
|
||||
import * as chart from 'chart.js';
|
||||
import jszip from 'jszip';
|
||||
import * as lodash from 'lodash-es';
|
||||
import * as lzstring from 'lz-string';
|
||||
import * as animate from 'mutate-animate';
|
||||
import * as vue from 'vue';
|
||||
|
||||
Mota.Package.register('axios', axios);
|
||||
Mota.Package.register('chart.js', chart);
|
||||
Mota.Package.register('jszip', jszip);
|
||||
Mota.Package.register('lodash', lodash);
|
||||
Mota.Package.register('lz-string', lzstring);
|
||||
Mota.Package.register('mutate-animate', animate);
|
||||
Mota.Package.register('vue', vue);
|
@ -17,21 +17,32 @@
|
||||
// import frag from '@/plugin/fx/frag';
|
||||
// import { Mota } from '.';
|
||||
|
||||
import * as shadow from '@/plugin/shadow/shadow';
|
||||
import * as gameShadow from '@/plugin/shadow/gameShadow';
|
||||
import * as fly from '@/plugin/ui/fly';
|
||||
import * as chase from '@/plugin/chase/chase';
|
||||
import * as completion from '@/plugin/completion';
|
||||
import * as pop from '@/plugin/pop';
|
||||
import * as status from '@/plugin/ui/statusBar';
|
||||
import * as frag from '@/plugin/fx/frag';
|
||||
import * as use from '@/plugin/use';
|
||||
import * as gameCanvas from '@/plugin/fx/gameCanvas';
|
||||
import * as smooth from '@/plugin/fx/smoothView';
|
||||
import { loading } from './loader/load';
|
||||
|
||||
Mota.Plugin.register('gameShadow', gameShadow, gameShadow.init);
|
||||
Mota.Plugin.register('fly', fly);
|
||||
Mota.Plugin.register('chase', chase);
|
||||
Mota.Plugin.register('completion', completion);
|
||||
Mota.Plugin.register('pop', pop, pop.init);
|
||||
Mota.Plugin.register('status', status); // todo: 改成系统变量,而非插件
|
||||
Mota.Plugin.register('frag', frag, frag.init);
|
||||
Mota.Plugin.register('shadow_r', shadow, shadow.init);
|
||||
Mota.Plugin.register('gameShadow_r', gameShadow, gameShadow.init);
|
||||
Mota.Plugin.register('fly_r', fly);
|
||||
Mota.Plugin.register('chase_r', chase);
|
||||
Mota.Plugin.register('completion_r', completion);
|
||||
Mota.Plugin.register('pop_r', pop, pop.init);
|
||||
Mota.Plugin.register('frag_r', frag, frag.init);
|
||||
Mota.Plugin.register('use_r', use);
|
||||
Mota.Plugin.register('gameCanvas_r', gameCanvas);
|
||||
Mota.Plugin.register('smooth_r', smooth, smooth.init);
|
||||
|
||||
loading.once('coreInit', () => {
|
||||
Mota.Plugin.init();
|
||||
});
|
||||
|
||||
// // todo: 将插件更改为注册形式,分为渲染进程和游戏进程两部分,同时分配优先级
|
||||
|
||||
|
@ -483,14 +483,14 @@
|
||||
},
|
||||
"study": {
|
||||
"text": "学习",
|
||||
"condition": "core.plugin.skillTree.getSkillLevel(11) > 0",
|
||||
"condition": "Mota.Plugin.require('skillTree_g').getSkillLevel(11) > 0",
|
||||
"desc": [
|
||||
"本条目会详细说明学习的机制与所有可以被学习的技能被学习后的效果。当前已经学习的技能会以与状态栏类似的盒子展示出来。",
|
||||
"<br>",
|
||||
"<br>",
|
||||
"首先,学习技能消耗的智慧点会越来越多,初始消耗的智慧点为500,每学习一次增加250。",
|
||||
"学习的技能可以持续5场战斗,在技能树界面每升级一次增加3场,",
|
||||
"<span style=\"color: gold\">当前为${core.plugin.skillTree.getSkillLevel(11) * 3 + 2}场</span>。",
|
||||
"<span style=\"color: gold\">当前为${Mota.Plugin.require('skillTree_g').getSkillLevel(11) * 3 + 2}场</span>。",
|
||||
"学习后对应属性的值,例如抱团怪增加的属性百分比,会与被学习的怪物相同。学习界面可以使用背包中的道具或点击状态栏打开。",
|
||||
"<br>",
|
||||
"<br>",
|
||||
|
@ -8,7 +8,7 @@
|
||||
},
|
||||
"blade": {
|
||||
"text": "1:断灭之刃",
|
||||
"opened": "core.plugin.skillTree.getSkillLevel(2) > 0",
|
||||
"opened": "Mota.Plugin.require('skillTree_g').getSkillLevel(2) > 0",
|
||||
"desc": [
|
||||
"<span style=\"color: gold\">快捷键1</span>,开启后勇士攻击增加${level:2 * 10}%,",
|
||||
"同时防御减少${level:2 * 10}%。",
|
||||
@ -31,7 +31,7 @@
|
||||
},
|
||||
"shield": {
|
||||
"text": "3:铸剑为盾",
|
||||
"opened": "core.plugin.skillTree.getSkillLevel(10) > 0",
|
||||
"opened": "Mota.Plugin.require('skillTree_g').getSkillLevel(10) > 0",
|
||||
"desc": [
|
||||
"<span style=\"color: gold\">快捷键3</span>,开启后勇士防御增加${level:10 * 10}%,",
|
||||
"同时攻击减少${level:10 * 10}%。",
|
||||
|
@ -1 +1,2 @@
|
||||
import './system';
|
||||
import '../plugin/game/index';
|
||||
|
@ -25,9 +25,10 @@ import type {
|
||||
} from '@/core/main/setting';
|
||||
import type { GameStorage } from '@/core/main/storage';
|
||||
import type { DamageEnemy, EnemyCollection } from '@/plugin/game/enemy/damage';
|
||||
import type { enemySpecials } from '@/plugin/game/enemy/special';
|
||||
import type { specials } from '@/plugin/game/enemy/special';
|
||||
import type { Range } from '@/plugin/game/range';
|
||||
import type { KeyCode } from '@/plugin/keyCodes';
|
||||
import type { Ref } from 'vue';
|
||||
|
||||
interface ClassInterface {
|
||||
// 渲染进程与游戏进程通用
|
||||
@ -82,9 +83,10 @@ interface VariableInterface {
|
||||
resource: ResourceStore<Exclude<ResourceType, 'zip'>>;
|
||||
zipResource: ResourceStore<'zip'>;
|
||||
settingStorage: GameStorage<SettingStorage>;
|
||||
status: Ref<boolean>;
|
||||
// 定义于游戏进程,渲染进程依然可用
|
||||
haloSpecials: number[];
|
||||
enemySpecials: typeof enemySpecials;
|
||||
enemySpecials: typeof specials;
|
||||
}
|
||||
|
||||
interface SystemInterfaceMap {
|
||||
@ -95,12 +97,67 @@ interface SystemInterfaceMap {
|
||||
|
||||
type InterfaceType = keyof SystemInterfaceMap;
|
||||
|
||||
interface PluginInterface {}
|
||||
interface PluginInterface {
|
||||
// 渲染进程定义的插件
|
||||
pop_r: typeof import('../plugin/pop');
|
||||
use_r: typeof import('../plugin/use');
|
||||
// animate: typeof import('../plugin/animateController');
|
||||
// utils: typeof import('../plugin/utils');
|
||||
// status: typeof import('../plugin/ui/statusBar');
|
||||
fly_r: typeof import('../plugin/ui/fly');
|
||||
chase_r: typeof import('../plugin/chase/chase');
|
||||
// webglUtils: typeof import('../plugin/webgl/utils');
|
||||
shadow_r: typeof import('../plugin/shadow/shadow');
|
||||
gameShadow_r: typeof import('../plugin/shadow/gameShadow');
|
||||
// achievement: typeof import('../plugin/ui/achievement');
|
||||
completion_r: typeof import('../plugin/completion');
|
||||
// path: typeof import('../plugin/fx/path');
|
||||
gameCanvas_r: typeof import('../plugin/fx/gameCanvas');
|
||||
// noise: typeof import('../plugin/fx/noise');
|
||||
smooth_r: typeof import('../plugin/fx/smoothView');
|
||||
frag_r: typeof import('../plugin/fx/frag');
|
||||
// 游戏进程定义的插件
|
||||
utils_g: typeof import('../plugin/game/utils');
|
||||
loopMap_g: typeof import('../plugin/game/loopMap');
|
||||
shop_g: typeof import('../plugin/game/shop');
|
||||
replay_g: typeof import('../plugin/game/replay');
|
||||
skillTree_g: typeof import('../plugin/game/skillTree');
|
||||
removeMap_g: typeof import('../plugin/game/removeMap');
|
||||
remainEnemy_g: typeof import('../plugin/game/enemy/remainEnemy');
|
||||
chase_g: typeof import('../plugin/game/chase');
|
||||
skill_g: typeof import('../plugin/game/skill');
|
||||
towerBoss_g: typeof import('../plugin/game/towerBoss');
|
||||
heroFourFrames_g: typeof import('../plugin/game/fx/heroFourFrames');
|
||||
rewrite_g: typeof import('../plugin/game/fx/rewrite');
|
||||
itemDetail_g: typeof import('../plugin/game/fx/itemDetail');
|
||||
checkBlock_g: typeof import('../plugin/game/enemy/checkblock');
|
||||
halo_g: typeof import('../plugin/game/fx/halo');
|
||||
study_g: typeof import('../plugin/game/study');
|
||||
}
|
||||
|
||||
interface PackageInterface {
|
||||
axios: typeof import('axios');
|
||||
'chart.js': typeof import('chart.js');
|
||||
jszip: typeof import('jszip');
|
||||
lodash: typeof import('lodash-es');
|
||||
'lz-string': typeof import('lz-string');
|
||||
'mutate-animate': typeof import('mutate-animate');
|
||||
vue: typeof import('vue');
|
||||
}
|
||||
|
||||
export interface IMota {
|
||||
rewrite: typeof rewrite;
|
||||
r: typeof r;
|
||||
rf: typeof rf;
|
||||
|
||||
/** 样板插件接口 */
|
||||
Plugin: IPlugin;
|
||||
/**
|
||||
* 样板使用的第三方库接口,可以直接获取到库的原有接口。
|
||||
* 接口在渲染进程中引入,在游戏进程中不会polyfill,因此在游戏进程中使用时,
|
||||
* 应先使用main.replayChecking进行检查,保证该值不存在时才进行使用,否则会引起录像出错
|
||||
*/
|
||||
Package: IPackage;
|
||||
|
||||
/**
|
||||
* 获取一个样板接口
|
||||
@ -145,15 +202,12 @@ export interface IMota {
|
||||
}
|
||||
|
||||
export interface IPlugin {
|
||||
inited: boolean;
|
||||
|
||||
/**
|
||||
* 初始化所有插件
|
||||
*/
|
||||
init(): void;
|
||||
/**
|
||||
* 初始化指定插件
|
||||
* @param plugin 要初始化的插件
|
||||
*/
|
||||
init(plugin: string): void;
|
||||
|
||||
/**
|
||||
* 获取到一个插件的内容
|
||||
@ -169,7 +223,7 @@ export interface IPlugin {
|
||||
/**
|
||||
* 获取所有插件
|
||||
*/
|
||||
requireAll(): PluginInterface;
|
||||
requireAll(): PluginInterface & { [x: string]: any };
|
||||
|
||||
/**
|
||||
* 注册一个插件
|
||||
@ -210,6 +264,24 @@ export interface IPlugin {
|
||||
register<K extends string>(plugin: K, init: (plugin: K) => any): void;
|
||||
}
|
||||
|
||||
export interface IPackage {
|
||||
/**
|
||||
* 获取样板使用的第三方库
|
||||
* @param name 要获取的第三方库
|
||||
*/
|
||||
require<K extends keyof PackageInterface>(name: K): PackageInterface[K];
|
||||
|
||||
/**
|
||||
* 获取样板使用的所有第三方库
|
||||
*/
|
||||
requireAll(): PackageInterface;
|
||||
|
||||
register<K extends keyof PackageInterface>(
|
||||
name: K,
|
||||
data: PackageInterface[K]
|
||||
): void;
|
||||
}
|
||||
|
||||
interface IPluginData {
|
||||
/** 插件类型,content表示直接注册了内容,function表示注册了初始化函数,内容从其返回值获取 */
|
||||
type: 'content' | 'function';
|
||||
@ -219,8 +291,8 @@ interface IPluginData {
|
||||
|
||||
class MPlugin {
|
||||
private static plugins: Record<string, IPluginData> = {};
|
||||
private static inited = false;
|
||||
private static pluginData: Record<string, any> = {};
|
||||
static inited = false;
|
||||
|
||||
constructor() {
|
||||
throw new Error(`System plugin class cannot be constructed.`);
|
||||
@ -248,8 +320,8 @@ class MPlugin {
|
||||
return this.plugins[key].data;
|
||||
}
|
||||
|
||||
static requireAll() {
|
||||
return this.pluginData;
|
||||
static requireAll(): PluginInterface {
|
||||
return this.pluginData as PluginInterface;
|
||||
}
|
||||
|
||||
static register(key: string, data: any, init?: any) {
|
||||
@ -269,6 +341,32 @@ class MPlugin {
|
||||
}
|
||||
}
|
||||
|
||||
class MPackage {
|
||||
// @ts-ignore
|
||||
private static packages: PackageInterface = {};
|
||||
|
||||
constructor() {
|
||||
throw new Error(`System package class cannot be constructed.`);
|
||||
}
|
||||
|
||||
static require<K extends keyof PackageInterface>(
|
||||
name: K
|
||||
): PackageInterface[K] {
|
||||
return this.packages[name];
|
||||
}
|
||||
|
||||
static requireAll() {
|
||||
return this.packages;
|
||||
}
|
||||
|
||||
static register<K extends keyof PackageInterface>(
|
||||
name: K,
|
||||
data: PackageInterface[K]
|
||||
) {
|
||||
this.packages[name] = data;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 样板接口系统,通过 Mota 获取到样板的核心功能,不可实例化
|
||||
*/
|
||||
@ -278,7 +376,10 @@ class Mota {
|
||||
private static variables: Record<string, any> = {};
|
||||
|
||||
static rewrite = rewrite;
|
||||
static r = r;
|
||||
static rf = rf;
|
||||
static Plugin = MPlugin;
|
||||
static Package = MPackage;
|
||||
|
||||
constructor() {
|
||||
throw new Error(`System interface class cannot be constructed.`);
|
||||
@ -330,11 +431,19 @@ type _Func = (...params: any) => any;
|
||||
* @param bind 原函数的调用对象,默认为base
|
||||
* @param rebind 复写函数的调用对象,默认为base
|
||||
*/
|
||||
function rewrite<O, K extends SelectKey<O, _Func>, T = O>(
|
||||
function rewrite<
|
||||
O,
|
||||
K extends SelectKey<O, _Func>,
|
||||
R extends 'full' | 'front',
|
||||
T = O
|
||||
>(
|
||||
base: O,
|
||||
key: K,
|
||||
type: 'full' | 'front',
|
||||
re: (this: T, ...params: [..._F<O[K]>[0], ...any[]]) => _F<O[K]>[1],
|
||||
type: R,
|
||||
re: (
|
||||
this: T,
|
||||
...params: [..._F<O[K]>[0], ...any[]]
|
||||
) => R extends 'full' ? _F<O[K]>[1] : void,
|
||||
bind?: any,
|
||||
rebind?: T
|
||||
): (this: T, ...params: [..._F<O[K]>[0], ...any[]]) => _F<O[K]>[1];
|
||||
@ -345,8 +454,8 @@ function rewrite<O, K extends SelectKey<O, _Func>, T = O>(
|
||||
* @param type 复写类型,add表示在函数后追加
|
||||
* @param re 复写函数,类型为add时表示在原函数后面追加复写函数,会在第一个参数中传入原函数的返回值,
|
||||
* 并要求复写函数必须有返回值,作为复写的最终返回值。
|
||||
* @param bind 原函数的调用对象,默认为base
|
||||
* @param rebind 复写函数的调用对象,默认为base
|
||||
* @param bind 原函数的调用对象,默认为`base`
|
||||
* @param rebind 复写函数的调用对象,默认为`base`
|
||||
*/
|
||||
function rewrite<O, K extends SelectKey<O, _Func>, T = O>(
|
||||
base: O,
|
||||
@ -390,7 +499,7 @@ function rewrite<O, K extends SelectKey<O, _Func>, T = O>(
|
||||
const origin = base[key];
|
||||
function res(this: T, ...params: [..._F<O[K]>[0], ...any[]]) {
|
||||
// @ts-ignore
|
||||
re.call(rebind ?? base, v, ...params);
|
||||
re.call(rebind ?? base, ...params);
|
||||
const ret = (origin as _Func).call(bind ?? base, ...params);
|
||||
return ret;
|
||||
}
|
||||
@ -399,6 +508,43 @@ function rewrite<O, K extends SelectKey<O, _Func>, T = O>(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 在渲染进程包裹下执行一段代码,该段代码不会在录像验证中执行,因此里面的内容一定不会引起录像报错
|
||||
* 一般特效,或者是ui显示、内容显示、交互监听等内容应当在渲染进程包裹下执行
|
||||
* @param fn 要执行的函数,传入一个参数,表示所有的第三方库,也就是`Mota.Package.requireAll()`的内容
|
||||
* @param thisArg 函数的执行上下文,即函数中`this`指向
|
||||
*/
|
||||
function r<T = undefined>(
|
||||
fn: (this: T, packages: PackageInterface) => void,
|
||||
thisArg?: T
|
||||
) {
|
||||
if (!main.replayChecking) fn.call(thisArg as T, MPackage.requireAll());
|
||||
}
|
||||
|
||||
/**
|
||||
* 将一个函数包裹成渲染进程函数,执行这个函数时将直接在渲染进程下执行。该函数与 {@link r} 函数的关系,
|
||||
* 与`call`和`bind`的关系类似。
|
||||
* ```ts
|
||||
* const fn = rf((x) => x * x);
|
||||
* console.log(fn(2)); // 在正常游玩中会输出 4,但是录像验证中会输出undefined,因为录像验证中不会执行渲染进程函数
|
||||
* ```
|
||||
* @param fn 要执行的函数
|
||||
* @param thisArg 函数执行时的上下文,即this指向
|
||||
* @returns 经过渲染进程包裹的函数,直接调用即是在渲染进程下执行的
|
||||
*/
|
||||
function rf<F extends (...params: any) => any, T>(
|
||||
fn: F,
|
||||
thisArg?: T
|
||||
): (this: T, ...params: Parameters<F>) => ReturnType<F> | undefined {
|
||||
// @ts-ignore
|
||||
if (main.replayChecking) return () => {};
|
||||
else {
|
||||
return (...params) => {
|
||||
return fn.call(thisArg, ...params);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
Mota: IMota;
|
||||
|
@ -123,7 +123,7 @@ export const camera1: ChaseCameraData[] = [
|
||||
* 追逐战开始前的初始化函数,移除所有血瓶和门等
|
||||
*/
|
||||
export function init1() {
|
||||
return core.plugin.chase.chaseInit1();
|
||||
return Mota.Plugin.require('chase_g').chaseInit1();
|
||||
}
|
||||
|
||||
export function chaseShake(chase: Chase) {
|
||||
@ -561,7 +561,7 @@ export function para3(chase: Chase) {
|
||||
'MT14',
|
||||
async () => {
|
||||
flags.finishChase1 = true;
|
||||
core.plugin.replay.clip('choices:0');
|
||||
Mota.Plugin.require('replay_g').clip('choices:0');
|
||||
core.showStatusBar();
|
||||
ani.time(750).apply('rect', 0);
|
||||
chase.end();
|
||||
|
@ -5,6 +5,7 @@ import {
|
||||
} from './ui/achievement';
|
||||
import { changeLocalStorage } from './utils';
|
||||
import list from '../data/achievement.json';
|
||||
import { loading } from '@/core/loader/load';
|
||||
|
||||
export const floors: Record<number, FloorIds[]> = {
|
||||
1: ['MT0', 'tower7']
|
||||
@ -21,6 +22,15 @@ export const achiDict: Record<number, number> = {
|
||||
1: 0
|
||||
};
|
||||
|
||||
loading.once('coreInit', () => {
|
||||
Object.values(floors).forEach((v, i) => {
|
||||
const from = core.floorIds.indexOf(v[0]);
|
||||
const to = core.floorIds.indexOf(v[1]);
|
||||
const all = core.floorIds.slice(from, to + 1);
|
||||
floors[i + 1] = all;
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* 检查所有到达过的楼层,用于成就的计算
|
||||
*/
|
||||
|
@ -7,7 +7,9 @@ tran.value.y = 0;
|
||||
|
||||
let needSmooth = false;
|
||||
|
||||
export default function init() {
|
||||
export function init() {
|
||||
const setting = Mota.require('var', 'mainSetting');
|
||||
|
||||
tran.ticker.add(() => {
|
||||
if (core.isPlaying() && needSmooth) {
|
||||
core.setViewport(tran.value.x, tran.value.y);
|
||||
@ -18,50 +20,47 @@ export default function init() {
|
||||
needSmooth = false;
|
||||
}, 700);
|
||||
|
||||
control.prototype._drawHero_updateViewport = function (
|
||||
x: number,
|
||||
y: number,
|
||||
offset: Loc
|
||||
) {
|
||||
const ox = core.clamp(
|
||||
(x - core._HALF_WIDTH_) * 32 + offset.x,
|
||||
0,
|
||||
Math.max(32 * core.bigmap.width - core._PX_, 0)
|
||||
);
|
||||
const oy = core.clamp(
|
||||
(y - core._HALF_HEIGHT_) * 32 + offset.y,
|
||||
0,
|
||||
Math.max(32 * core.bigmap.height - core._PY_, 0)
|
||||
);
|
||||
Mota.rewrite(
|
||||
core.control,
|
||||
'_drawHero_updateViewport',
|
||||
'full',
|
||||
(x, y, offset) => {
|
||||
const ox = core.clamp(
|
||||
(x - core._HALF_WIDTH_) * 32 + offset.x,
|
||||
0,
|
||||
Math.max(32 * core.bigmap.width - core._PX_, 0)
|
||||
);
|
||||
const oy = core.clamp(
|
||||
(y - core._HALF_HEIGHT_) * 32 + offset.y,
|
||||
0,
|
||||
Math.max(32 * core.bigmap.height - core._PY_, 0)
|
||||
);
|
||||
|
||||
tran.transition('x', ox).transition('y', oy);
|
||||
tran.transition('x', ox).transition('y', oy);
|
||||
|
||||
if (tran.easeTime > 0) {
|
||||
needSmooth = true;
|
||||
func();
|
||||
} else {
|
||||
core.setViewport(tran.value.x, tran.value.y);
|
||||
const t = setting.getValue('screen.smoothView', false);
|
||||
if (!t) return;
|
||||
if (tran.easeTime > 0) {
|
||||
needSmooth = true;
|
||||
func();
|
||||
} else {
|
||||
core.setViewport(tran.value.x, tran.value.y);
|
||||
}
|
||||
}
|
||||
};
|
||||
);
|
||||
|
||||
const hso = hyper('sin', 'out');
|
||||
let time2 = Date.now();
|
||||
const origin1 = control.prototype._moveAction_moving;
|
||||
control.prototype._moveAction_moving = function (...params: any[]) {
|
||||
if (Date.now() - time2 > 20)
|
||||
tran.mode(hyper('sin', 'out')).time(200).absolute();
|
||||
return origin1.call(this, ...params);
|
||||
};
|
||||
|
||||
const origin2 = control.prototype.moveDirectly;
|
||||
control.prototype.moveDirectly = function (...params: any[]) {
|
||||
Mota.rewrite(core.control, '_moveAction_moving', 'front', () => {
|
||||
const t = setting.getValue('screen.smoothView', false) ? 200 : 1;
|
||||
if (Date.now() - time2 > 20) tran.mode(hso).time(t).absolute();
|
||||
});
|
||||
Mota.rewrite(core.control, 'moveDirectly', 'front', () => {
|
||||
const t = setting.getValue('screen.smoothView', false) ? 600 : 1;
|
||||
time2 = Date.now();
|
||||
tran.mode(hyper('sin', 'out')).time(600).absolute();
|
||||
return origin2.call(this, ...params);
|
||||
};
|
||||
|
||||
const origin3 = events.prototype._changeFloor_beforeChange;
|
||||
events.prototype._changeFloor_beforeChange = function (...params: any[]) {
|
||||
tran.mode(hso).time(t).absolute();
|
||||
});
|
||||
Mota.rewrite(core.events, '_changeFloor_beforeChange', 'front', () => {
|
||||
tran.time(1).absolute();
|
||||
return origin3.call(this, ...params);
|
||||
};
|
||||
});
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
export function chaseInit1() {
|
||||
const ids = ['MT13', 'MT14', 'MT15'];
|
||||
const toRemove = [];
|
||||
const ids: FloorIds[] = ['MT13', 'MT14', 'MT15'];
|
||||
const toRemove: [number, number, FloorIds][] = [];
|
||||
ids.forEach(v => {
|
||||
core.status.maps[v].cannotMoveDirectly = true;
|
||||
core.extractBlocks(v);
|
||||
@ -17,7 +17,3 @@ export function chaseInit1() {
|
||||
core.removeBlock(...v);
|
||||
});
|
||||
}
|
||||
|
||||
core.plugin.chase = {
|
||||
chaseInit1
|
||||
};
|
@ -22,232 +22,224 @@ export function getEnemy(
|
||||
return enemy;
|
||||
}
|
||||
|
||||
core.enemys.canBattle = function (
|
||||
x: number,
|
||||
y: number,
|
||||
floorId: FloorIds = core.status.floorId
|
||||
) {
|
||||
const enemy = getEnemy(x, y, floorId);
|
||||
const { damage } = enemy.calDamage();
|
||||
return damage < core.status.hero.hp;
|
||||
};
|
||||
export function init() {
|
||||
core.enemys.canBattle = function (
|
||||
x: number,
|
||||
y: number,
|
||||
floorId: FloorIds = core.status.floorId
|
||||
) {
|
||||
const enemy = getEnemy(x, y, floorId);
|
||||
const { damage } = enemy.calDamage();
|
||||
return damage < core.status.hero.hp;
|
||||
};
|
||||
|
||||
core.events.battle = function (
|
||||
x: number,
|
||||
y: number,
|
||||
force: boolean = false,
|
||||
callback?: () => void
|
||||
) {
|
||||
core.saveAndStopAutomaticRoute();
|
||||
const enemy = getEnemy(x, y);
|
||||
// 非强制战斗
|
||||
if (!core.enemys.canBattle(x, y) && !force && !core.status.event.id) {
|
||||
core.stopSound();
|
||||
core.playSound('操作失败');
|
||||
core.drawTip('你打不过此怪物!', enemy.id);
|
||||
return core.clearContinueAutomaticRoute(callback);
|
||||
}
|
||||
// 自动存档
|
||||
if (!core.status.event.id) core.autosave(true);
|
||||
// 战前事件
|
||||
if (!this.beforeBattle(enemy, x, y))
|
||||
return core.clearContinueAutomaticRoute(callback);
|
||||
// 战后事件
|
||||
this.afterBattle(enemy, x, y);
|
||||
callback?.();
|
||||
};
|
||||
|
||||
core.events.beforeBattle = function () {
|
||||
return true;
|
||||
};
|
||||
|
||||
core.events.afterBattle = function (
|
||||
enemy: DamageEnemy,
|
||||
x?: number,
|
||||
y?: number
|
||||
) {
|
||||
const floorId = core.status.floorId;
|
||||
const special = enemy.info.special;
|
||||
|
||||
// 播放战斗动画
|
||||
let animate: AnimationIds = 'hand';
|
||||
// 检查当前装备是否存在攻击动画
|
||||
const equipId = core.getEquip(0);
|
||||
if (equipId && (core.material.items[equipId].equip || {}).animate)
|
||||
animate = core.material.items[equipId].equip.animate;
|
||||
|
||||
// 检查该动画是否存在SE,如果不存在则使用默认音效
|
||||
if (!core.material.animates[animate]?.se) core.playSound('attack.mp3');
|
||||
|
||||
// 战斗伤害
|
||||
const info = enemy.calDamage(core.status.hero);
|
||||
const damage = info.damage;
|
||||
// 判定是否致死
|
||||
if (damage >= core.status.hero.hp) {
|
||||
core.status.hero.hp = 0;
|
||||
core.updateStatusBar(false, true);
|
||||
core.events.lose('战斗失败');
|
||||
return;
|
||||
}
|
||||
|
||||
// 扣减体力值并记录统计数据
|
||||
core.status.hero.hp -= damage;
|
||||
core.status.hero.statistics.battleDamage += damage;
|
||||
core.status.hero.statistics.battle++;
|
||||
|
||||
// 智慧之源
|
||||
if (special.includes(14) && flags.hard === 2) {
|
||||
core.addFlag(
|
||||
'inte_' + floorId,
|
||||
Math.ceil((core.status.hero.mdef / 10) * 0.3) * 10
|
||||
);
|
||||
core.status.hero.mdef -=
|
||||
Math.ceil((core.status.hero.mdef / 10) * 0.3) * 10;
|
||||
}
|
||||
|
||||
// 极昼永夜
|
||||
if (special.includes(22)) {
|
||||
flags[`night_${floorId}`] ??= 0;
|
||||
flags[`night_${floorId}`] -= enemy.enemy.night!;
|
||||
}
|
||||
if (special.includes(23)) {
|
||||
flags[`night_${floorId}`] ??= 0;
|
||||
flags[`night_${floorId}`] += enemy.enemy.day;
|
||||
}
|
||||
|
||||
// if (core.plugin.skillTree.getSkillLevel(11) > 0) {
|
||||
// core.plugin.study.declineStudiedSkill();
|
||||
// }
|
||||
|
||||
// 如果是融化怪,需要特殊标记一下
|
||||
if (special.includes(25) && core.has(x) && core.has(y)) {
|
||||
flags[`melt_${floorId}`] ??= {};
|
||||
flags[`melt_${floorId}`][`${x},${y}`] = enemy.enemy.melt;
|
||||
}
|
||||
|
||||
// 获得金币
|
||||
const money = enemy.enemy.money;
|
||||
core.status.hero.money += money;
|
||||
core.status.hero.statistics.money += money;
|
||||
|
||||
// 获得经验
|
||||
const exp = enemy.enemy.exp;
|
||||
core.status.hero.exp += exp;
|
||||
core.status.hero.statistics.exp += exp;
|
||||
|
||||
const hint =
|
||||
'打败 ' + enemy.enemy.name + ',金币+' + money + ',经验+' + exp;
|
||||
core.drawTip(hint, enemy.id);
|
||||
|
||||
if (core.getFlag('bladeOn') && core.getFlag('blade')) {
|
||||
core.setFlag('blade', false);
|
||||
}
|
||||
if (core.getFlag('shieldOn') && core.getFlag('shield')) {
|
||||
core.setFlag('shield', false);
|
||||
}
|
||||
|
||||
// 事件的处理
|
||||
const todo: MotaEvent = [];
|
||||
|
||||
// 战后事件
|
||||
if (has(core.status.floorId)) {
|
||||
const loc = `${x},${y}` as LocString;
|
||||
todo.push(...(core.floors[core.status.floorId].afterBattle[loc] ?? []));
|
||||
}
|
||||
todo.push(...(enemy.enemy.afterBattle ?? []));
|
||||
|
||||
// 如果事件不为空,将其插入
|
||||
if (todo.length > 0) core.insertAction(todo, x, y);
|
||||
|
||||
if (has(x) && has(y)) {
|
||||
core.drawAnimate(animate, x, y);
|
||||
core.removeBlock(x, y);
|
||||
} else core.drawHeroAnimate(animate);
|
||||
|
||||
// 如果已有事件正在处理中
|
||||
if (core.status.event.id == null) core.continueAutomaticRoute();
|
||||
else core.clearContinueAutomaticRoute();
|
||||
};
|
||||
|
||||
core.events._sys_battle = function (data: Block, callback?: () => void) {
|
||||
// 检查战前事件
|
||||
const floor = core.floors[core.status.floorId];
|
||||
const beforeBattle: MotaEvent = [];
|
||||
const loc = `${data.x},${data.y}` as LocString;
|
||||
const enemy = getEnemy(data.x, data.y);
|
||||
|
||||
beforeBattle.push(...(floor.beforeBattle[loc] ?? []));
|
||||
beforeBattle.push(...(enemy.enemy.beforeBattle ?? []));
|
||||
|
||||
if (beforeBattle.length > 0) {
|
||||
beforeBattle.push({ type: 'battle', x: data.x, y: data.y });
|
||||
core.clearContinueAutomaticRoute();
|
||||
|
||||
// 自动存档
|
||||
var inAction = core.status.event.id == 'action';
|
||||
if (inAction) {
|
||||
core.insertAction(beforeBattle, data.x, data.y);
|
||||
core.doAction();
|
||||
} else {
|
||||
core.autosave(true);
|
||||
core.insertAction(beforeBattle, data.x, data.y, callback);
|
||||
core.events.battle = function (
|
||||
x: number,
|
||||
y: number,
|
||||
force: boolean = false,
|
||||
callback?: () => void
|
||||
) {
|
||||
core.saveAndStopAutomaticRoute();
|
||||
const enemy = getEnemy(x, y);
|
||||
// 非强制战斗
|
||||
if (!core.enemys.canBattle(x, y) && !force && !core.status.event.id) {
|
||||
core.stopSound();
|
||||
core.playSound('操作失败');
|
||||
core.drawTip('你打不过此怪物!', enemy.id);
|
||||
return core.clearContinueAutomaticRoute(callback);
|
||||
}
|
||||
} else {
|
||||
this.battle(data.x, data.y, false, callback);
|
||||
}
|
||||
};
|
||||
// 自动存档
|
||||
if (!core.status.event.id) core.autosave(true);
|
||||
// 战前事件
|
||||
// 战后事件
|
||||
this.afterBattle(enemy, x, y);
|
||||
callback?.();
|
||||
};
|
||||
|
||||
core.events._action_battle = function (data, x, y, prefix) {
|
||||
if (data.id) {
|
||||
const enemy = getSingleEnemy(data.id as EnemyIds);
|
||||
// todo: 与不在地图上的怪物战斗
|
||||
} else {
|
||||
if (data.floorId != core.status.floorId) {
|
||||
core.doAction();
|
||||
core.events.afterBattle = function (
|
||||
enemy: DamageEnemy,
|
||||
x?: number,
|
||||
y?: number
|
||||
) {
|
||||
const floorId = core.status.floorId;
|
||||
const special = enemy.info.special;
|
||||
|
||||
// 播放战斗动画
|
||||
let animate: AnimationIds = 'hand';
|
||||
// 检查当前装备是否存在攻击动画
|
||||
const equipId = core.getEquip(0);
|
||||
if (equipId && (core.material.items[equipId].equip || {}).animate)
|
||||
animate = core.material.items[equipId].equip.animate;
|
||||
|
||||
// 检查该动画是否存在SE,如果不存在则使用默认音效
|
||||
if (!core.material.animates[animate]?.se) core.playSound('attack.mp3');
|
||||
|
||||
// 战斗伤害
|
||||
const info = enemy.calDamage(core.status.hero);
|
||||
const damage = info.damage;
|
||||
// 判定是否致死
|
||||
if (damage >= core.status.hero.hp) {
|
||||
core.status.hero.hp = 0;
|
||||
core.updateStatusBar(false, true);
|
||||
core.events.lose('战斗失败');
|
||||
return;
|
||||
}
|
||||
const [ex, ey] = this.__action_getLoc(data.loc, x, y, prefix) as LocArr;
|
||||
this.battle(ex, ey, true, core.doAction);
|
||||
}
|
||||
};
|
||||
|
||||
core.enemys.getCurrentEnemys = function (floorId = core.status.floorId) {
|
||||
floorId = floorId || core.status.floorId;
|
||||
const enemys: CurrentEnemy[] = [];
|
||||
const used: Record<string, DamageEnemy[]> = {};
|
||||
ensureFloorDamage(floorId);
|
||||
const floor = core.status.maps[floorId];
|
||||
floor.enemy.list.forEach(v => {
|
||||
if (!(v.id in used)) {
|
||||
const e = new DamageEnemy(v.enemy);
|
||||
e.calAttribute();
|
||||
e.getRealInfo();
|
||||
e.calDamage();
|
||||
const curr: CurrentEnemy = {
|
||||
enemy: e,
|
||||
onMapEnemy: [v]
|
||||
};
|
||||
enemys.push(curr);
|
||||
used[v.id] = curr.onMapEnemy;
|
||||
} else {
|
||||
used[v.id].push(v);
|
||||
// 扣减体力值并记录统计数据
|
||||
core.status.hero.hp -= damage;
|
||||
core.status.hero.statistics.battleDamage += damage;
|
||||
core.status.hero.statistics.battle++;
|
||||
|
||||
// 智慧之源
|
||||
if (special.includes(14) && flags.hard === 2) {
|
||||
core.addFlag(
|
||||
'inte_' + floorId,
|
||||
Math.ceil((core.status.hero.mdef / 10) * 0.3) * 10
|
||||
);
|
||||
core.status.hero.mdef -=
|
||||
Math.ceil((core.status.hero.mdef / 10) * 0.3) * 10;
|
||||
}
|
||||
});
|
||||
|
||||
return enemys.sort((a, b) => {
|
||||
const ad = a.enemy.calDamage().damage;
|
||||
const bd = b.enemy.calDamage().damage;
|
||||
return ad - bd;
|
||||
});
|
||||
};
|
||||
// 极昼永夜
|
||||
if (special.includes(22)) {
|
||||
flags[`night_${floorId}`] ??= 0;
|
||||
flags[`night_${floorId}`] -= enemy.enemy.night!;
|
||||
}
|
||||
if (special.includes(23)) {
|
||||
flags[`night_${floorId}`] ??= 0;
|
||||
flags[`night_${floorId}`] += enemy.enemy.day;
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface Events {
|
||||
beforeBattle(enemy: DamageEnemy, x: number, y: number): boolean;
|
||||
afterBattle(enemy: DamageEnemy, x: number, y: number): void;
|
||||
}
|
||||
// if (core.plugin.skillTree.getSkillLevel(11) > 0) {
|
||||
// core.plugin.study.declineStudiedSkill();
|
||||
// }
|
||||
|
||||
interface Enemys {
|
||||
getCurrentEnemys(floorId?: FloorIds): CurrentEnemy[];
|
||||
}
|
||||
// 如果是融化怪,需要特殊标记一下
|
||||
if (special.includes(25) && has(x) && has(y)) {
|
||||
flags[`melt_${floorId}`] ??= {};
|
||||
flags[`melt_${floorId}`][`${x},${y}`] = enemy.enemy.melt;
|
||||
}
|
||||
|
||||
// 获得金币
|
||||
const money = enemy.enemy.money;
|
||||
core.status.hero.money += money;
|
||||
core.status.hero.statistics.money += money;
|
||||
|
||||
// 获得经验
|
||||
const exp = enemy.enemy.exp;
|
||||
core.status.hero.exp += exp;
|
||||
core.status.hero.statistics.exp += exp;
|
||||
|
||||
const hint =
|
||||
'打败 ' + enemy.enemy.name + ',金币+' + money + ',经验+' + exp;
|
||||
core.drawTip(hint, enemy.id);
|
||||
|
||||
if (core.getFlag('bladeOn') && core.getFlag('blade')) {
|
||||
core.setFlag('blade', false);
|
||||
}
|
||||
if (core.getFlag('shieldOn') && core.getFlag('shield')) {
|
||||
core.setFlag('shield', false);
|
||||
}
|
||||
|
||||
// 事件的处理
|
||||
const todo: MotaEvent = [];
|
||||
|
||||
// 战后事件
|
||||
if (has(core.status.floorId)) {
|
||||
const loc = `${x},${y}` as LocString;
|
||||
todo.push(
|
||||
...(core.floors[core.status.floorId].afterBattle[loc] ?? [])
|
||||
);
|
||||
}
|
||||
todo.push(...(enemy.enemy.afterBattle ?? []));
|
||||
|
||||
// 如果事件不为空,将其插入
|
||||
if (todo.length > 0) core.insertAction(todo, x, y);
|
||||
|
||||
if (has(x) && has(y)) {
|
||||
core.drawAnimate(animate, x, y);
|
||||
core.removeBlock(x, y);
|
||||
} else core.drawHeroAnimate(animate);
|
||||
|
||||
// 如果已有事件正在处理中
|
||||
if (core.status.event.id == null) core.continueAutomaticRoute();
|
||||
else core.clearContinueAutomaticRoute();
|
||||
};
|
||||
|
||||
core.events._sys_battle = function (data: Block, callback?: () => void) {
|
||||
// 检查战前事件
|
||||
const floor = core.floors[core.status.floorId];
|
||||
const beforeBattle: MotaEvent = [];
|
||||
const loc = `${data.x},${data.y}` as LocString;
|
||||
const enemy = getEnemy(data.x, data.y);
|
||||
|
||||
beforeBattle.push(...(floor.beforeBattle[loc] ?? []));
|
||||
beforeBattle.push(...(enemy.enemy.beforeBattle ?? []));
|
||||
|
||||
if (beforeBattle.length > 0) {
|
||||
beforeBattle.push({ type: 'battle', x: data.x, y: data.y });
|
||||
core.clearContinueAutomaticRoute();
|
||||
|
||||
// 自动存档
|
||||
var inAction = core.status.event.id == 'action';
|
||||
if (inAction) {
|
||||
core.insertAction(beforeBattle, data.x, data.y);
|
||||
core.doAction();
|
||||
} else {
|
||||
core.autosave(true);
|
||||
core.insertAction(beforeBattle, data.x, data.y, callback);
|
||||
}
|
||||
} else {
|
||||
this.battle(data.x, data.y, false, callback);
|
||||
}
|
||||
};
|
||||
|
||||
core.events._action_battle = function (data, x, y, prefix) {
|
||||
if (data.id) {
|
||||
const enemy = getSingleEnemy(data.id as EnemyIds);
|
||||
// todo: 与不在地图上的怪物战斗
|
||||
} else {
|
||||
if (data.floorId != core.status.floorId) {
|
||||
core.doAction();
|
||||
return;
|
||||
}
|
||||
const [ex, ey] = this.__action_getLoc(
|
||||
data.loc,
|
||||
x,
|
||||
y,
|
||||
prefix
|
||||
) as LocArr;
|
||||
this.battle(ex, ey, true, core.doAction);
|
||||
}
|
||||
};
|
||||
|
||||
core.enemys.getCurrentEnemys = function (floorId = core.status.floorId) {
|
||||
floorId = floorId || core.status.floorId;
|
||||
const enemys: CurrentEnemy[] = [];
|
||||
const used: Record<string, DamageEnemy[]> = {};
|
||||
ensureFloorDamage(floorId);
|
||||
const floor = core.status.maps[floorId];
|
||||
floor.enemy.list.forEach(v => {
|
||||
if (!(v.id in used)) {
|
||||
const e = new DamageEnemy(v.enemy);
|
||||
e.calAttribute();
|
||||
e.getRealInfo();
|
||||
e.calDamage();
|
||||
const curr: CurrentEnemy = {
|
||||
enemy: e,
|
||||
onMapEnemy: [v]
|
||||
};
|
||||
enemys.push(curr);
|
||||
used[v.id] = curr.onMapEnemy;
|
||||
} else {
|
||||
used[v.id].push(v);
|
||||
}
|
||||
});
|
||||
|
||||
return enemys.sort((a, b) => {
|
||||
const ad = a.enemy.calDamage().damage;
|
||||
const bd = b.enemy.calDamage().damage;
|
||||
return ad - bd;
|
||||
});
|
||||
};
|
||||
}
|
||||
|
@ -1,157 +1,162 @@
|
||||
import { drawHalo } from '../fx/halo';
|
||||
|
||||
// 伤害弹出
|
||||
// 复写阻激夹域检测
|
||||
control.prototype.checkBlock = function (forceMockery: boolean = false) {
|
||||
const x = core.getHeroLoc('x'),
|
||||
y = core.getHeroLoc('y'),
|
||||
loc = x + ',' + y;
|
||||
const info = core.status.thisMap.enemy.mapDamage[loc];
|
||||
const damage = info?.damage;
|
||||
if (damage) {
|
||||
if (!main.replayChecking) {
|
||||
Mota.Plugin.require('pop').addPop(
|
||||
(x - core.bigmap.offsetX / 32) * 32 + 12,
|
||||
(y - core.bigmap.offsetY / 32) * 32 + 20,
|
||||
(-damage).toString()
|
||||
);
|
||||
}
|
||||
core.status.hero.hp -= damage;
|
||||
const type = [...info.type];
|
||||
const text = type.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();
|
||||
}
|
||||
}
|
||||
checkMockery(loc, forceMockery);
|
||||
};
|
||||
|
||||
control.prototype._drawDamage_draw = function (
|
||||
ctx: CanvasRenderingContext2D,
|
||||
onMap: boolean,
|
||||
floorId: FloorIds
|
||||
) {
|
||||
if (!core.hasItem('book')) return;
|
||||
drawHalo(ctx, onMap, floorId);
|
||||
|
||||
core.setFont(ctx, "14px 'normal'");
|
||||
core.setTextAlign(ctx, 'center');
|
||||
core.setTextBaseline(ctx, 'middle');
|
||||
core.status.damage.extraData.forEach(function (one) {
|
||||
var px = one.px,
|
||||
py = one.py;
|
||||
if (onMap && core.bigmap.v2) {
|
||||
px -= core.bigmap.posX * 32;
|
||||
py -= core.bigmap.posY * 32;
|
||||
if (
|
||||
px < -32 ||
|
||||
px > core._PX_ + 32 ||
|
||||
py < -32 ||
|
||||
py > core._PY_ + 32
|
||||
)
|
||||
export function init() {
|
||||
// 伤害弹出
|
||||
// 复写阻激夹域检测
|
||||
control.prototype.checkBlock = function (forceMockery: boolean = false) {
|
||||
const x = core.getHeroLoc('x'),
|
||||
y = core.getHeroLoc('y'),
|
||||
loc = x + ',' + y;
|
||||
const info = core.status.thisMap.enemy.mapDamage[loc];
|
||||
const damage = info?.damage;
|
||||
if (damage) {
|
||||
if (!main.replayChecking) {
|
||||
Mota.Plugin.require('pop_r').addPop(
|
||||
(x - core.bigmap.offsetX / 32) * 32 + 12,
|
||||
(y - core.bigmap.offsetY / 32) * 32 + 20,
|
||||
(-damage).toString()
|
||||
);
|
||||
}
|
||||
core.status.hero.hp -= damage;
|
||||
const type = [...info.type];
|
||||
const text = type.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();
|
||||
}
|
||||
}
|
||||
var alpha = core.setAlpha(ctx, one.alpha);
|
||||
core.fillBoldText(ctx, one.text, px, py, one.color as string);
|
||||
core.setAlpha(ctx, alpha);
|
||||
});
|
||||
checkMockery(loc, forceMockery);
|
||||
};
|
||||
|
||||
core.setTextAlign(ctx, 'left');
|
||||
core.setTextBaseline(ctx, 'alphabetic');
|
||||
core.status.damage.data.forEach(function (one) {
|
||||
var px = one.px,
|
||||
py = one.py;
|
||||
if (onMap && core.bigmap.v2) {
|
||||
px -= core.bigmap.posX * 32;
|
||||
py -= core.bigmap.posY * 32;
|
||||
if (
|
||||
px < -32 * 2 ||
|
||||
px > core._PX_ + 32 ||
|
||||
py < -32 ||
|
||||
py > core._PY_ + 32
|
||||
)
|
||||
return;
|
||||
control.prototype._drawDamage_draw = function (
|
||||
ctx: CanvasRenderingContext2D,
|
||||
onMap: boolean,
|
||||
floorId: FloorIds
|
||||
) {
|
||||
if (!core.hasItem('book')) return;
|
||||
drawHalo(ctx, onMap, floorId);
|
||||
|
||||
core.setFont(ctx, "14px 'normal'");
|
||||
core.setTextAlign(ctx, 'center');
|
||||
core.setTextBaseline(ctx, 'middle');
|
||||
core.status.damage.extraData.forEach(function (one) {
|
||||
var px = one.px,
|
||||
py = one.py;
|
||||
if (onMap && core.bigmap.v2) {
|
||||
px -= core.bigmap.posX * 32;
|
||||
py -= core.bigmap.posY * 32;
|
||||
if (
|
||||
px < -32 ||
|
||||
px > core._PX_ + 32 ||
|
||||
py < -32 ||
|
||||
py > core._PY_ + 32
|
||||
)
|
||||
return;
|
||||
}
|
||||
var alpha = core.setAlpha(ctx, one.alpha);
|
||||
core.fillBoldText(ctx, one.text, px, py, one.color as string);
|
||||
core.setAlpha(ctx, alpha);
|
||||
});
|
||||
|
||||
core.setTextAlign(ctx, 'left');
|
||||
core.setTextBaseline(ctx, 'alphabetic');
|
||||
core.status.damage.data.forEach(function (one) {
|
||||
var px = one.px,
|
||||
py = one.py;
|
||||
if (onMap && core.bigmap.v2) {
|
||||
px -= core.bigmap.posX * 32;
|
||||
py -= core.bigmap.posY * 32;
|
||||
if (
|
||||
px < -32 * 2 ||
|
||||
px > core._PX_ + 32 ||
|
||||
py < -32 ||
|
||||
py > core._PY_ + 32
|
||||
)
|
||||
return;
|
||||
}
|
||||
core.fillBoldText(ctx, one.text, px, py, one.color as string);
|
||||
});
|
||||
|
||||
ctx.save();
|
||||
ctx.lineCap = 'round';
|
||||
ctx.lineJoin = 'round';
|
||||
ctx.lineWidth = 2;
|
||||
core.status.damage.dir.forEach(v => {
|
||||
let x = v.x;
|
||||
let y = v.y;
|
||||
if (onMap && core.bigmap.v2) {
|
||||
x -= core.bigmap.posX;
|
||||
y -= core.bigmap.posY;
|
||||
}
|
||||
if (x < -1 || x > 15 || y < 0 || y > 15) return;
|
||||
let px = x * 32;
|
||||
let py = y * 32;
|
||||
ctx.beginPath();
|
||||
if (v.dir === 'down') {
|
||||
py -= 32;
|
||||
ctx.moveTo(px + 16, py + 18);
|
||||
ctx.lineTo(px + 16, py + 32);
|
||||
ctx.moveTo(px + 10, py + 26);
|
||||
ctx.lineTo(px + 16, py + 32);
|
||||
ctx.lineTo(px + 22, py + 26);
|
||||
} else if (v.dir === 'left') {
|
||||
px += 32;
|
||||
ctx.moveTo(px + 14, py + 16);
|
||||
ctx.lineTo(px, py + 16);
|
||||
ctx.moveTo(px + 6, py + 10);
|
||||
ctx.lineTo(px, py + 16);
|
||||
ctx.lineTo(px + 6, py + 22);
|
||||
} else if (v.dir === 'up') {
|
||||
py += 32;
|
||||
ctx.moveTo(px + 16, py + 14);
|
||||
ctx.lineTo(px + 16, py);
|
||||
ctx.moveTo(px + 10, py + 6);
|
||||
ctx.lineTo(px + 16, py);
|
||||
ctx.lineTo(px + 22, py + 6);
|
||||
} else {
|
||||
px -= 32;
|
||||
ctx.moveTo(px + 18, py + 16);
|
||||
ctx.lineTo(px + 32, py + 16);
|
||||
ctx.moveTo(px + 26, py + 10);
|
||||
ctx.lineTo(px + 32, py + 16);
|
||||
ctx.lineTo(px + 26, py + 22);
|
||||
}
|
||||
ctx.strokeStyle = 'black';
|
||||
ctx.lineWidth = 2.5;
|
||||
ctx.stroke();
|
||||
ctx.strokeStyle = v.color as string;
|
||||
ctx.lineWidth = 1;
|
||||
ctx.stroke();
|
||||
});
|
||||
ctx.restore();
|
||||
};
|
||||
|
||||
control.prototype.moveHero = function (
|
||||
direction: Dir,
|
||||
callback: () => void
|
||||
) {
|
||||
// 如果正在移动,直接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.thisMap.enemy.mapDamage[`${nx},${ny}`]?.mockery) {
|
||||
core.autosave();
|
||||
}
|
||||
core.fillBoldText(ctx, one.text, px, py, one.color as string);
|
||||
});
|
||||
|
||||
ctx.save();
|
||||
ctx.lineCap = 'round';
|
||||
ctx.lineJoin = 'round';
|
||||
ctx.lineWidth = 2;
|
||||
core.status.damage.dir.forEach(v => {
|
||||
let x = v.x;
|
||||
let y = v.y;
|
||||
if (onMap && core.bigmap.v2) {
|
||||
x -= core.bigmap.posX;
|
||||
y -= core.bigmap.posY;
|
||||
}
|
||||
if (x < -1 || x > 15 || y < 0 || y > 15) return;
|
||||
let px = x * 32;
|
||||
let py = y * 32;
|
||||
ctx.beginPath();
|
||||
if (v.dir === 'down') {
|
||||
py -= 32;
|
||||
ctx.moveTo(px + 16, py + 18);
|
||||
ctx.lineTo(px + 16, py + 32);
|
||||
ctx.moveTo(px + 10, py + 26);
|
||||
ctx.lineTo(px + 16, py + 32);
|
||||
ctx.lineTo(px + 22, py + 26);
|
||||
} else if (v.dir === 'left') {
|
||||
px += 32;
|
||||
ctx.moveTo(px + 14, py + 16);
|
||||
ctx.lineTo(px, py + 16);
|
||||
ctx.moveTo(px + 6, py + 10);
|
||||
ctx.lineTo(px, py + 16);
|
||||
ctx.lineTo(px + 6, py + 22);
|
||||
} else if (v.dir === 'up') {
|
||||
py += 32;
|
||||
ctx.moveTo(px + 16, py + 14);
|
||||
ctx.lineTo(px + 16, py);
|
||||
ctx.moveTo(px + 10, py + 6);
|
||||
ctx.lineTo(px + 16, py);
|
||||
ctx.lineTo(px + 22, py + 6);
|
||||
} else {
|
||||
px -= 32;
|
||||
ctx.moveTo(px + 18, py + 16);
|
||||
ctx.lineTo(px + 32, py + 16);
|
||||
ctx.moveTo(px + 26, py + 10);
|
||||
ctx.lineTo(px + 32, py + 16);
|
||||
ctx.lineTo(px + 26, py + 22);
|
||||
}
|
||||
ctx.strokeStyle = 'black';
|
||||
ctx.lineWidth = 2.5;
|
||||
ctx.stroke();
|
||||
ctx.strokeStyle = v.color as string;
|
||||
ctx.lineWidth = 1;
|
||||
ctx.stroke();
|
||||
});
|
||||
ctx.restore();
|
||||
};
|
||||
|
||||
control.prototype.moveHero = function (direction: Dir, callback: () => void) {
|
||||
// 如果正在移动,直接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.thisMap.enemy.mapDamage[`${nx},${ny}`]?.mockery) {
|
||||
core.autosave();
|
||||
}
|
||||
|
||||
if (callback) return this.moveAction(callback);
|
||||
this._moveHero_moving();
|
||||
};
|
||||
if (callback) return this.moveAction(callback);
|
||||
this._moveHero_moving();
|
||||
};
|
||||
}
|
||||
|
||||
function checkMockery(loc: string, force: boolean = false) {
|
||||
if (core.status.lockControl && !force) return;
|
||||
|
@ -394,7 +394,7 @@ export class DamageEnemy<T extends EnemyIds = EnemyIds> {
|
||||
|
||||
getHaloSpecials(): number[] {
|
||||
if (!this.floorId) return [];
|
||||
if (!core.has(this.x) || !core.has(this.y)) return [];
|
||||
if (!has(this.x) || !has(this.y)) return [];
|
||||
const special = this.info.special ?? this.enemy.special;
|
||||
const filter = special.filter(v => {
|
||||
return haloSpecials.includes(v) && !this.providedHalo.includes(v);
|
||||
@ -424,7 +424,7 @@ export class DamageEnemy<T extends EnemyIds = EnemyIds> {
|
||||
if (this.progress !== 2) return;
|
||||
this.progress = 3;
|
||||
if (!this.floorId) return;
|
||||
if (!core.has(this.x) || !core.has(this.y)) return;
|
||||
if (!has(this.x) || !has(this.y)) return;
|
||||
const col = this.col ?? core.status.maps[this.floorId].enemy;
|
||||
if (!col) return;
|
||||
const special = this.getHaloSpecials();
|
||||
@ -950,8 +950,3 @@ declare global {
|
||||
enemy: EnemyCollection;
|
||||
}
|
||||
}
|
||||
|
||||
core.plugin.damage = {
|
||||
Enemy: DamageEnemy,
|
||||
Collection: EnemyCollection
|
||||
};
|
||||
|
@ -1,27 +1,19 @@
|
||||
///<reference path="../../../../src/types/core.d.ts" />
|
||||
|
||||
// todo: 优化,直接调用 floor.enemy.list 进行计算
|
||||
|
||||
/**
|
||||
* 检查漏怪
|
||||
* @param {FloorIds[]} floorIds
|
||||
*/
|
||||
export function checkRemainEnemy(floorIds) {
|
||||
/**
|
||||
* @type {Record<FloorIds, {loc: LocArr, id: EnemyIds}[]>}
|
||||
*/
|
||||
const enemy = {};
|
||||
export function checkRemainEnemy(floorIds: FloorIds[]) {
|
||||
const enemy: Partial<Record<FloorIds, { loc: LocArr; id: EnemyIds }[]>> =
|
||||
{};
|
||||
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;
|
||||
const id: EnemyIds = block.event.id as EnemyIds;
|
||||
enemy[v] ??= [];
|
||||
const info = enemy[v];
|
||||
const info = enemy[v]!;
|
||||
info.push({ loc: [block.x, block.y], id });
|
||||
});
|
||||
});
|
||||
@ -30,30 +22,23 @@ export function checkRemainEnemy(floorIds) {
|
||||
|
||||
/**
|
||||
* 获取剩余怪物字符串
|
||||
* @param {FloorIds[]} floorIds
|
||||
*/
|
||||
export function getRemainEnemyString(floorIds) {
|
||||
export function getRemainEnemyString(floorIds: 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 = {};
|
||||
const all: { loc: LocArr; id: EnemyIds }[] = enemy[floor as FloorIds]!;
|
||||
const remain: Partial<Record<EnemyIds, number>> = {};
|
||||
all.forEach(v => {
|
||||
const id = v.id;
|
||||
remain[id] ??= 0;
|
||||
remain[id]++;
|
||||
remain[id]!++;
|
||||
});
|
||||
const title = core.status.maps[floor].title;
|
||||
const title = core.status.maps[floor as FloorIds].title;
|
||||
for (const id in remain) {
|
||||
const name = core.material.enemys[id].name;
|
||||
now.push(`${title}(${floor}): ${name} * ${remain[id]}`);
|
||||
const name = core.material.enemys[id as EnemyIds].name;
|
||||
now.push(`${title}(${floor}): ${name} * ${remain[id as EnemyIds]}`);
|
||||
if (now.length === 10) {
|
||||
str.push(now.join('\n'));
|
||||
now = [];
|
||||
@ -67,8 +52,3 @@ export function getRemainEnemyString(floorIds) {
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
core.plugin.remainEnemy = {
|
||||
checkRemainEnemy,
|
||||
getRemainEnemyString
|
||||
};
|
@ -7,7 +7,7 @@ export interface SpecialDeclaration {
|
||||
color: string;
|
||||
}
|
||||
|
||||
export const enemySpecials: SpecialDeclaration[] = [
|
||||
export const specials: SpecialDeclaration[] = [
|
||||
{
|
||||
code: 0,
|
||||
name: '空',
|
||||
@ -202,11 +202,3 @@ export const enemySpecials: SpecialDeclaration[] = [
|
||||
color: '#ff6f0a'
|
||||
}
|
||||
];
|
||||
|
||||
declare global {
|
||||
interface PluginDeclaration {
|
||||
special: SpecialDeclaration[];
|
||||
}
|
||||
}
|
||||
|
||||
core.plugin.special = enemySpecials;
|
||||
|
@ -1,199 +0,0 @@
|
||||
///<reference path="../../../src/types/core.d.ts" />
|
||||
export {};
|
||||
|
||||
// 创建新图层
|
||||
function createCanvas(name, zIndex) {
|
||||
if (!name) return;
|
||||
var canvas = document.createElement('canvas');
|
||||
canvas.id = name;
|
||||
canvas.className = 'gameCanvas no-anti-aliasing';
|
||||
// 编辑器模式下设置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;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
maps.prototype._loadFloor_doNotCopy = function () {
|
||||
return [
|
||||
'firstArrive',
|
||||
'eachArrive',
|
||||
'blocks',
|
||||
'parallelDo',
|
||||
'map',
|
||||
'bgmap',
|
||||
'fgmap',
|
||||
'bg2map',
|
||||
'fg2map',
|
||||
'events',
|
||||
'changeFloor',
|
||||
'afterBattle',
|
||||
'afterGetItem',
|
||||
'afterOpenDoor',
|
||||
'cannotMove',
|
||||
'enemy'
|
||||
];
|
||||
};
|
||||
////// 绘制背景和前景层 //////
|
||||
maps.prototype._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._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;
|
||||
};
|
||||
maps.prototype._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.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;
|
||||
};
|
||||
////// 移动判定 //////
|
||||
maps.prototype._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)
|
||||
};
|
||||
};
|
219
src/plugin/game/fiveLayer.ts
Normal file
219
src/plugin/game/fiveLayer.ts
Normal file
@ -0,0 +1,219 @@
|
||||
// @ts-nocheck
|
||||
|
||||
// 创建新图层
|
||||
function createCanvas(name, zIndex) {
|
||||
if (!name) return;
|
||||
var canvas = document.createElement('canvas');
|
||||
canvas.id = name;
|
||||
canvas.className = 'gameCanvas no-anti-aliasing';
|
||||
// 编辑器模式下设置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;
|
||||
}
|
||||
|
||||
export function init() {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
maps.prototype._loadFloor_doNotCopy = function () {
|
||||
return [
|
||||
'firstArrive',
|
||||
'eachArrive',
|
||||
'blocks',
|
||||
'parallelDo',
|
||||
'map',
|
||||
'bgmap',
|
||||
'fgmap',
|
||||
'bg2map',
|
||||
'fg2map',
|
||||
'events',
|
||||
'changeFloor',
|
||||
'afterBattle',
|
||||
'afterGetItem',
|
||||
'afterOpenDoor',
|
||||
'cannotMove',
|
||||
'enemy'
|
||||
];
|
||||
};
|
||||
////// 绘制背景和前景层 //////
|
||||
maps.prototype._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._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;
|
||||
};
|
||||
maps.prototype._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.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;
|
||||
};
|
||||
////// 移动判定 //////
|
||||
maps.prototype._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,58 +0,0 @@
|
||||
///<reference path="../../../../src/types/core.d.ts" />
|
||||
export {};
|
||||
|
||||
['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);
|
||||
|
||||
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;
|
||||
};
|
60
src/plugin/game/fx/heroFourFrames.ts
Normal file
60
src/plugin/game/fx/heroFourFrames.ts
Normal file
@ -0,0 +1,60 @@
|
||||
// @ts-nocheck
|
||||
|
||||
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
|
||||
);
|
||||
};
|
||||
|
||||
export function init() {
|
||||
['up', 'down', 'left', 'right'].forEach(one => {
|
||||
// 指定中间帧动画
|
||||
core.material.icons.hero[one].midFoot = 2;
|
||||
});
|
||||
|
||||
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;
|
||||
};
|
||||
}
|
@ -1,33 +1,35 @@
|
||||
import { ensureFloorDamage } from '../enemy/damage';
|
||||
|
||||
core.control.updateDamage = function (floorId = core.status.floorId, ctx) {
|
||||
if (!floorId || core.status.gameOver || main.mode !== 'play') return;
|
||||
const onMap = ctx == null;
|
||||
const floor = core.status.maps[floorId];
|
||||
export function init() {
|
||||
core.control.updateDamage = function (floorId = core.status.floorId, ctx) {
|
||||
if (!floorId || core.status.gameOver || main.mode !== 'play') return;
|
||||
const onMap = ctx == null;
|
||||
const floor = core.status.maps[floorId];
|
||||
|
||||
// 没有怪物手册
|
||||
// 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;
|
||||
}
|
||||
// 计算伤害
|
||||
ensureFloorDamage(floorId);
|
||||
// 没有怪物手册
|
||||
// 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;
|
||||
}
|
||||
// 计算伤害
|
||||
ensureFloorDamage(floorId);
|
||||
|
||||
floor.enemy.extract();
|
||||
floor.enemy.calDamage(true);
|
||||
floor.enemy.calMapDamage();
|
||||
core.status.damage.data = [];
|
||||
floor.enemy.extract();
|
||||
floor.enemy.calDamage(true);
|
||||
floor.enemy.calMapDamage();
|
||||
core.status.damage.data = [];
|
||||
|
||||
floor.enemy.render(true);
|
||||
floor.enemy.render(true);
|
||||
|
||||
getItemDetail(floorId, onMap); // 宝石血瓶详细信息
|
||||
this.drawDamage(ctx, floorId);
|
||||
};
|
||||
getItemDetail(floorId, onMap); // 宝石血瓶详细信息
|
||||
this.drawDamage(ctx, floorId);
|
||||
};
|
||||
}
|
||||
|
||||
// 获取宝石信息 并绘制
|
||||
function getItemDetail(floorId: FloorIds, onMap: boolean) {
|
||||
|
@ -1,59 +1,61 @@
|
||||
import { getEnemy } from '../enemy/battle';
|
||||
import { formatDamage } from '../utils';
|
||||
|
||||
core.maps._initDetachedBlock = function (
|
||||
info: BlockInfo,
|
||||
x: number,
|
||||
y: number,
|
||||
displayDamage: boolean = false
|
||||
) {
|
||||
let headCanvas = null,
|
||||
bodyCanvas = '__body_' + x + '_' + y,
|
||||
damageCanvas = null;
|
||||
|
||||
// head
|
||||
if (!info.bigImage && info.height > 32) {
|
||||
headCanvas = '__head_' + x + '_' + y;
|
||||
core.createCanvas(headCanvas, 0, 0, 32, info.height - 32, 55);
|
||||
}
|
||||
// body
|
||||
if (info.bigImage) {
|
||||
var bigImageInfo = this._getBigImageInfo(
|
||||
info.bigImage,
|
||||
info.face,
|
||||
info.posX
|
||||
);
|
||||
const { per_width, per_height } = bigImageInfo;
|
||||
core.createCanvas(bodyCanvas, 0, 0, per_width, per_height, 35);
|
||||
} else {
|
||||
core.createCanvas(bodyCanvas, 0, 0, 32, 32, 35);
|
||||
}
|
||||
|
||||
// 伤害
|
||||
if (
|
||||
info.cls.indexOf('enemy') == 0 &&
|
||||
core.hasItem('book') &&
|
||||
displayDamage
|
||||
export function init() {
|
||||
core.maps._initDetachedBlock = function (
|
||||
info: BlockInfo,
|
||||
x: number,
|
||||
y: number,
|
||||
displayDamage: boolean = false
|
||||
) {
|
||||
const enemy = getEnemy(x, y);
|
||||
const dam = enemy.calDamage();
|
||||
const { damage, color } = formatDamage(dam.damage);
|
||||
let headCanvas = null,
|
||||
bodyCanvas = '__body_' + x + '_' + y,
|
||||
damageCanvas = null;
|
||||
|
||||
damageCanvas = '__damage_' + x + '_' + y;
|
||||
const ctx = core.createCanvas(damageCanvas, 0, 0, 32, 32, 65);
|
||||
ctx.textAlign = 'left';
|
||||
ctx.font = '14px normal';
|
||||
core.fillBoldText(ctx, damage, 1, 31, color as string);
|
||||
if (core.flags.displayCritical) {
|
||||
const critical = enemy.calCritical(1);
|
||||
const atk = core.formatBigNumber(critical[0]?.delta, true);
|
||||
const display = atk === '???' ? '?' : atk;
|
||||
core.fillBoldText(ctx, display, 1, 21, '#FFFFFF');
|
||||
// head
|
||||
if (!info.bigImage && info.height > 32) {
|
||||
headCanvas = '__head_' + x + '_' + y;
|
||||
core.createCanvas(headCanvas, 0, 0, 32, info.height - 32, 55);
|
||||
}
|
||||
}
|
||||
return {
|
||||
headCanvas,
|
||||
bodyCanvas,
|
||||
damageCanvas
|
||||
// body
|
||||
if (info.bigImage) {
|
||||
var bigImageInfo = this._getBigImageInfo(
|
||||
info.bigImage,
|
||||
info.face,
|
||||
info.posX
|
||||
);
|
||||
const { per_width, per_height } = bigImageInfo;
|
||||
core.createCanvas(bodyCanvas, 0, 0, per_width, per_height, 35);
|
||||
} else {
|
||||
core.createCanvas(bodyCanvas, 0, 0, 32, 32, 35);
|
||||
}
|
||||
|
||||
// 伤害
|
||||
if (
|
||||
info.cls.indexOf('enemy') == 0 &&
|
||||
core.hasItem('book') &&
|
||||
displayDamage
|
||||
) {
|
||||
const enemy = getEnemy(x, y);
|
||||
const dam = enemy.calDamage();
|
||||
const { damage, color } = formatDamage(dam.damage);
|
||||
|
||||
damageCanvas = '__damage_' + x + '_' + y;
|
||||
const ctx = core.createCanvas(damageCanvas, 0, 0, 32, 32, 65);
|
||||
ctx.textAlign = 'left';
|
||||
ctx.font = '14px normal';
|
||||
core.fillBoldText(ctx, damage, 1, 31, color as string);
|
||||
if (core.flags.displayCritical) {
|
||||
const critical = enemy.calCritical(1);
|
||||
const atk = core.formatBigNumber(critical[0]?.delta, true);
|
||||
const display = atk === '???' ? '?' : atk;
|
||||
core.fillBoldText(ctx, display, 1, 21, '#FFFFFF');
|
||||
}
|
||||
}
|
||||
return {
|
||||
headCanvas,
|
||||
bodyCanvas,
|
||||
damageCanvas
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
@ -54,6 +54,7 @@ function getRealStatus(
|
||||
name: keyof HeroStatus | 'all' | (keyof HeroStatus)[],
|
||||
floorId: FloorIds = core.status.floorId
|
||||
): any {
|
||||
const { getSkillLevel } = Mota.Plugin.require('skillTree_g');
|
||||
if (name instanceof Array) {
|
||||
return Object.fromEntries(
|
||||
name.map(v => [v, getRealStatus(status, v, floorId)])
|
||||
@ -84,7 +85,7 @@ function getRealStatus(
|
||||
|
||||
// 技能
|
||||
if (flags.bladeOn && flags.blade) {
|
||||
const level = core.plugin.skillTree.getSkillLevel(2);
|
||||
const level = getSkillLevel(2);
|
||||
if (name === 'atk') {
|
||||
s *= 1 + 0.1 * level;
|
||||
}
|
||||
@ -93,7 +94,7 @@ function getRealStatus(
|
||||
}
|
||||
}
|
||||
if (flags.shield && flags.shieldOn) {
|
||||
const level = core.plugin.skillTree.getSkillLevel(10);
|
||||
const level = getSkillLevel(10);
|
||||
if (name === 'atk') {
|
||||
s *= 1 - 0.1 * level;
|
||||
}
|
||||
@ -119,8 +120,3 @@ declare global {
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
core.plugin.hero = {
|
||||
getHeroStatusOf,
|
||||
getHeroStatusOn
|
||||
};
|
||||
|
@ -1,41 +0,0 @@
|
||||
import './fiveLayer';
|
||||
import './fx/heroFourFrames';
|
||||
import './dev/hotReload';
|
||||
import './fx/itemDetail';
|
||||
import './enemy/checkblock';
|
||||
import './replay';
|
||||
import './ui';
|
||||
import './fx/rewrite';
|
||||
import * as halo from './fx/halo';
|
||||
import * as hero from './hero';
|
||||
import * as loopMap from './loopMap';
|
||||
import * as remainEnemy from './enemy/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';
|
||||
import * as chase from './chase';
|
||||
import * as damage from './enemy/damage';
|
||||
import * as battle from './enemy/battle';
|
||||
import * as special from './enemy/special';
|
||||
|
||||
export {
|
||||
halo,
|
||||
hero,
|
||||
loopMap,
|
||||
remainEnemy,
|
||||
removeMap,
|
||||
shop,
|
||||
skill,
|
||||
skillTree,
|
||||
study,
|
||||
towerBoss,
|
||||
utils,
|
||||
chase,
|
||||
damage,
|
||||
battle,
|
||||
special
|
||||
};
|
65
src/plugin/game/index.ts
Normal file
65
src/plugin/game/index.ts
Normal file
@ -0,0 +1,65 @@
|
||||
/* @__PURE__ */ import './dev/hotReload'; // 仅开发会用到
|
||||
import * as fiveLayer from './fiveLayer';
|
||||
import * as heroFourFrames from './fx/heroFourFrames';
|
||||
import * as itemDetail from './fx/itemDetail';
|
||||
import * as checkBlock from './enemy/checkblock';
|
||||
import * as replay from './replay';
|
||||
import * as ui from './ui';
|
||||
import * as rewrite from './fx/rewrite';
|
||||
import * as halo from './fx/halo';
|
||||
import * as hero from './hero';
|
||||
import * as loopMap from './loopMap';
|
||||
import * as remainEnemy from './enemy/remainEnemy';
|
||||
import * as removeMap from './removeMap';
|
||||
import * as shop from './shop';
|
||||
import * as skill from './skill';
|
||||
import * as skillTree from './skillTree';
|
||||
import * as study from './study';
|
||||
import * as towerBoss from './towerBoss';
|
||||
import * as utils from './utils';
|
||||
import * as chase from './chase';
|
||||
import * as damage from './enemy/damage';
|
||||
import * as battle from './enemy/battle';
|
||||
import * as special from './enemy/special';
|
||||
|
||||
Mota.Plugin.register('utils_g', utils);
|
||||
Mota.Plugin.register('loopMap_g', loopMap, loopMap.init);
|
||||
Mota.Plugin.register('shop_g', shop);
|
||||
Mota.Plugin.register('replay_g', replay, replay.init);
|
||||
Mota.Plugin.register('skillTree_g', skillTree);
|
||||
Mota.Plugin.register('removeMap_g', removeMap);
|
||||
Mota.Plugin.register('remainEnemy_g', remainEnemy);
|
||||
Mota.Plugin.register('chase_g', chase);
|
||||
Mota.Plugin.register('skill_g', skill);
|
||||
Mota.Plugin.register('towerBoss_g', towerBoss);
|
||||
Mota.Plugin.register('fiveLayer_g', fiveLayer, fiveLayer.init);
|
||||
Mota.Plugin.register('heroFourFrames_g', heroFourFrames, heroFourFrames.init);
|
||||
Mota.Plugin.register('rewrite_g', rewrite, rewrite.init);
|
||||
Mota.Plugin.register('itemDetail_g', itemDetail, itemDetail.init);
|
||||
Mota.Plugin.register('checkBlock_g', checkBlock, checkBlock.init);
|
||||
Mota.Plugin.register('halo_g', halo);
|
||||
Mota.Plugin.register('study_g', study);
|
||||
// todo: 这几个不应该放到插件
|
||||
Mota.Plugin.register('damage_g', damage);
|
||||
Mota.Plugin.register('battle_g', battle, battle.init);
|
||||
Mota.Plugin.register('special_g', special);
|
||||
Mota.Plugin.register('hero_g', hero);
|
||||
Mota.Plugin.register('ui_g', ui, ui.init);
|
||||
|
||||
// export {
|
||||
// halo,
|
||||
// hero,
|
||||
// loopMap,
|
||||
// remainEnemy,
|
||||
// removeMap,
|
||||
// shop,
|
||||
// skill,
|
||||
// skillTree,
|
||||
// study,
|
||||
// towerBoss,
|
||||
// utils,
|
||||
// chase,
|
||||
// damage,
|
||||
// battle,
|
||||
// special
|
||||
// };
|
@ -1,230 +0,0 @@
|
||||
///<reference path="../../../src/types/core.d.ts" />
|
||||
import { slide } from './utils';
|
||||
|
||||
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 {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();
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (block == null) return _executeCallback();
|
||||
|
||||
// 执行该点的脚本
|
||||
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);
|
||||
}
|
||||
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 (!noCache && core.status[name + 'maps'][floorId])
|
||||
return core.status[name + 'maps'][floorId];
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
core.plugin.loopMap = {
|
||||
checkLoopMap
|
||||
};
|
257
src/plugin/game/loopMap.ts
Normal file
257
src/plugin/game/loopMap.ts
Normal file
@ -0,0 +1,257 @@
|
||||
///<reference path="../../../src/types/core.d.ts" />
|
||||
import { slide } from './utils';
|
||||
|
||||
const list = ['tower6'];
|
||||
|
||||
/**
|
||||
* 设置循环地图的偏移量
|
||||
* @param offset 横向偏移量
|
||||
*/
|
||||
function setLoopMap(offset: number, floorId: FloorIds) {
|
||||
const floor = core.status.maps[floorId];
|
||||
if (offset < 9) {
|
||||
moveMap(floor.width - 17, floorId);
|
||||
}
|
||||
if (offset > floor.width - 9) {
|
||||
moveMap(17 - floor.width, floorId);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 当勇士移动时自动设置循环地图
|
||||
*/
|
||||
function autoSetLoopMap(floorId: FloorIds) {
|
||||
setLoopMap(core.status.hero.loc.x, floorId);
|
||||
}
|
||||
|
||||
export function checkLoopMap() {
|
||||
if (isLoopMap(core.status.floorId)) {
|
||||
autoSetLoopMap(core.status.floorId);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 移动地图
|
||||
*/
|
||||
function moveMap(delta: number, floorId: FloorIds) {
|
||||
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: FloorIds) {
|
||||
return list.includes(floorId);
|
||||
}
|
||||
|
||||
export function init() {
|
||||
events.prototype._sys_changeFloor = function (
|
||||
data: any,
|
||||
callback: () => void
|
||||
) {
|
||||
data = data.event.data;
|
||||
let heroLoc: Partial<DiredLoc> = {};
|
||||
if (isLoopMap(data.floorId)) {
|
||||
const floor = core.status.maps[data.floorId as FloorIds] as Floor;
|
||||
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;
|
||||
// @ts-ignore
|
||||
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: number,
|
||||
y: number,
|
||||
callback: () => void
|
||||
) {
|
||||
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
|
||||
},
|
||||
void 0,
|
||||
void 0,
|
||||
void 0,
|
||||
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;
|
||||
// @ts-ignore
|
||||
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: DeepPartial<Block> = { event: {}, x: tx, y };
|
||||
b.event!.data = c;
|
||||
b.event!.trigger = 'changeFloor';
|
||||
block = b as Block;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (block == null) return _executeCallback();
|
||||
|
||||
// 执行该点的脚本
|
||||
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();
|
||||
// @ts-ignore
|
||||
core.status.automaticRoute.moveDirectly = false;
|
||||
this.doSystemEvent(trigger, block);
|
||||
}
|
||||
return _executeCallback();
|
||||
};
|
||||
|
||||
maps.prototype._getBgFgMapArray = function (
|
||||
name: string,
|
||||
floorId: FloorIds,
|
||||
noCache: boolean
|
||||
) {
|
||||
floorId = floorId || core.status.floorId;
|
||||
if (!floorId) return [];
|
||||
var width = core.floors[floorId].width;
|
||||
var height = core.floors[floorId].height;
|
||||
|
||||
// @ts-ignore
|
||||
if (!noCache && core.status[name + 'maps'][floorId])
|
||||
// @ts-ignore
|
||||
return core.status[name + 'maps'][floorId];
|
||||
|
||||
var arr: number[][] =
|
||||
main.mode == 'editor' &&
|
||||
// @ts-ignore
|
||||
!(window.editor && editor.uievent && editor.uievent.isOpen)
|
||||
? // @ts-ignore
|
||||
core.cloneArray(editor[name + 'map'])
|
||||
: null;
|
||||
if (arr == null)
|
||||
// @ts-ignore
|
||||
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);
|
||||
}
|
||||
// @ts-ignore
|
||||
(core.getFlag('__' + name + 'v__', {})[floorId] || []).forEach(
|
||||
// @ts-ignore
|
||||
function (one) {
|
||||
arr[one[1]][one[0]] = one[2] || 0;
|
||||
}
|
||||
);
|
||||
// @ts-ignore
|
||||
(core.getFlag('__' + name + 'd__', {})[floorId] || []).forEach(
|
||||
// @ts-ignore
|
||||
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++) {
|
||||
// @ts-ignore
|
||||
arr[y][x] = arr[y][x].idnum || arr[y][x] || 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
// @ts-ignore
|
||||
if (core.status[name + 'maps'])
|
||||
// @ts-ignore
|
||||
core.status[name + 'maps'][floorId] = arr;
|
||||
return arr;
|
||||
};
|
||||
}
|
@ -1,3 +1,5 @@
|
||||
import { has } from './utils';
|
||||
|
||||
type RangeScanFn<C extends Partial<Loc>> = (
|
||||
collection: Range<C>,
|
||||
data: any
|
||||
@ -77,8 +79,8 @@ Range.registerRangeType(
|
||||
|
||||
return list.filter(v => {
|
||||
return (
|
||||
core.has(v.x) &&
|
||||
core.has(v.y) &&
|
||||
has(v.x) &&
|
||||
has(v.y) &&
|
||||
Math.abs(v.x - x) <= r &&
|
||||
Math.abs(v.y - y) <= r
|
||||
);
|
||||
@ -87,8 +89,8 @@ Range.registerRangeType(
|
||||
(col, { x, y, d }, item) => {
|
||||
const r = Math.floor(d / 2);
|
||||
return (
|
||||
core.has(item.x) &&
|
||||
core.has(item.y) &&
|
||||
has(item.x) &&
|
||||
has(item.y) &&
|
||||
Math.abs(item.x - x) <= r &&
|
||||
Math.abs(item.y - y) <= r
|
||||
);
|
||||
|
@ -1,14 +1,20 @@
|
||||
///<reference path="../../../src/types/core.d.ts" />
|
||||
|
||||
export function removeMaps(fromId, toId, force) {
|
||||
export function removeMaps(
|
||||
fromId: FloorIds,
|
||||
toId: FloorIds,
|
||||
force: boolean = false
|
||||
) {
|
||||
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__ || {};
|
||||
// @ts-ignore
|
||||
flags.__visited__ ??= {};
|
||||
flags.__removed__ ??= [];
|
||||
flags.__disabled__ ??= {};
|
||||
// @ts-ignore
|
||||
flags.__leaveLoc__ ??= {};
|
||||
flags.__forceDelete__ ??= {};
|
||||
let deleted = false;
|
||||
for (var i = fromIndex; i <= toIndex; ++i) {
|
||||
@ -36,11 +42,11 @@ export function removeMaps(fromId, toId, force) {
|
||||
deleted = true;
|
||||
}
|
||||
if (deleted && !main.replayChecking) {
|
||||
Mota.Plugin.require('fly').splitArea();
|
||||
Mota.Plugin.require('fly_r').splitArea();
|
||||
}
|
||||
}
|
||||
|
||||
export function deleteFlags(floorId) {
|
||||
export function deleteFlags(floorId: FloorIds) {
|
||||
delete flags[`jump_${floorId}`];
|
||||
delete flags[`inte_${floorId}`];
|
||||
delete flags[`loop_${floorId}`];
|
||||
@ -51,7 +57,7 @@ export function deleteFlags(floorId) {
|
||||
// 恢复楼层
|
||||
// core.plugin.removeMap.resumeMaps("MT1", "MT300") 恢复MT1~MT300之间的全部层
|
||||
// core.plugin.removeMap.resumeMaps("MT10") 只恢复MT10层
|
||||
export function resumeMaps(fromId, toId) {
|
||||
export function resumeMaps(fromId: FloorIds, toId: FloorIds) {
|
||||
toId = toId || fromId;
|
||||
var fromIndex = core.floorIds.indexOf(fromId),
|
||||
toIndex = core.floorIds.indexOf(toId);
|
||||
@ -65,19 +71,21 @@ export function resumeMaps(fromId, toId) {
|
||||
flags.__forceDelete__[floorId]
|
||||
)
|
||||
continue;
|
||||
// @ts-ignore
|
||||
flags.__removed__ = flags.__removed__.filter(f => {
|
||||
return f != floorId;
|
||||
});
|
||||
// @ts-ignore
|
||||
core.status.maps[floorId] = core.loadFloor(floorId);
|
||||
}
|
||||
}
|
||||
|
||||
// 分区砍层相关
|
||||
var inAnyPartition = floorId => {
|
||||
var inAnyPartition = (floorId: FloorIds) => {
|
||||
var inPartition = false;
|
||||
(core.floorPartitions || []).forEach(floor => {
|
||||
var fromIndex = core.floorIds.indexOf(floor[0]);
|
||||
var toIndex = core.floorIds.indexOf(floor[1]);
|
||||
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;
|
||||
@ -87,29 +95,19 @@ var inAnyPartition = floorId => {
|
||||
};
|
||||
|
||||
// 分区砍层
|
||||
export function autoRemoveMaps(floorId) {
|
||||
export function autoRemoveMaps(floorId: FloorIds) {
|
||||
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 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]
|
||||
);
|
||||
resumeMaps(core.floorIds[fromIndex], core.floorIds[toIndex]);
|
||||
} else {
|
||||
removeMaps(core.floorIds[fromIndex], core.floorIds[toIndex]);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
core.plugin.removeMap = {
|
||||
removeMaps,
|
||||
deleteFlags,
|
||||
resumeMaps,
|
||||
autoRemoveMaps
|
||||
};
|
@ -1,122 +0,0 @@
|
||||
///<reference path="../../../src/types/core.d.ts" />
|
||||
|
||||
import { studySkill, canStudySkill } from './study';
|
||||
|
||||
const replayableSettings = ['autoSkill'];
|
||||
|
||||
let cliping = false;
|
||||
let startIndex = 0;
|
||||
|
||||
export function ready() {}
|
||||
|
||||
export function readyClip() {
|
||||
cliping = true;
|
||||
return (startIndex = core.status.route.length - 1);
|
||||
}
|
||||
|
||||
export function clip(...replace) {
|
||||
if (!cliping) return;
|
||||
cliping = false;
|
||||
|
||||
core.status.route.splice(startIndex);
|
||||
core.status.route.push(...replace);
|
||||
}
|
||||
|
||||
// 注册修改设置的录像操作
|
||||
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.status.route.push(name);
|
||||
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.status.route.push(name);
|
||||
core.replay();
|
||||
return true;
|
||||
});
|
||||
|
||||
core.registerReplayAction('study', name => {
|
||||
// todo
|
||||
// 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.status.route.push(name);
|
||||
// core.replay();
|
||||
// return true;
|
||||
});
|
||||
|
||||
// 商店
|
||||
let shopOpened = false;
|
||||
let openedShopId = '';
|
||||
core.registerReplayAction('openShop', name => {
|
||||
if (!name.startsWith('openShop:')) return false;
|
||||
if (shopOpened) return false;
|
||||
openedShopId = name.slice(9);
|
||||
shopOpened = true;
|
||||
core.status.route.push(name);
|
||||
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[openedShopId];
|
||||
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.addItem(id, type === 'buy' ? num : -num);
|
||||
core.status.route.push(name);
|
||||
core.replay();
|
||||
return true;
|
||||
});
|
||||
|
||||
core.registerReplayAction('closeShop', name => {
|
||||
if (name !== 'closeShop') return false;
|
||||
if (!shopOpened) return false;
|
||||
shopOpened = false;
|
||||
openedShopId = '';
|
||||
core.status.route.push(name);
|
||||
core.replay();
|
||||
return true;
|
||||
});
|
||||
|
||||
core.plugin.replay = {
|
||||
ready,
|
||||
readyClip,
|
||||
clip
|
||||
};
|
121
src/plugin/game/replay.ts
Normal file
121
src/plugin/game/replay.ts
Normal file
@ -0,0 +1,121 @@
|
||||
///<reference path="../../../src/types/core.d.ts" />
|
||||
|
||||
import { upgradeSkill } from './skillTree';
|
||||
|
||||
const replayableSettings = ['autoSkill'];
|
||||
|
||||
let cliping = false;
|
||||
let startIndex = 0;
|
||||
|
||||
export function ready() {}
|
||||
|
||||
export function readyClip() {
|
||||
cliping = true;
|
||||
return (startIndex = core.status.route.length - 1);
|
||||
}
|
||||
|
||||
export function clip(...replace: string[]) {
|
||||
if (!cliping) return;
|
||||
cliping = false;
|
||||
|
||||
core.status.route.splice(startIndex);
|
||||
core.status.route.push(...replace);
|
||||
}
|
||||
|
||||
export function init() {
|
||||
// 注册修改设置的录像操作
|
||||
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.status.route.push(name);
|
||||
core.replay();
|
||||
return true;
|
||||
});
|
||||
|
||||
core.registerReplayAction('upgradeSkill', name => {
|
||||
if (!name.startsWith('skill:')) return false;
|
||||
const skill = parseInt(name.slice(6));
|
||||
upgradeSkill(skill);
|
||||
core.status.route.push(name);
|
||||
core.replay();
|
||||
return true;
|
||||
});
|
||||
|
||||
core.registerReplayAction('study', name => {
|
||||
// todo
|
||||
// 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.status.route.push(name);
|
||||
// core.replay();
|
||||
return true;
|
||||
});
|
||||
|
||||
// 商店
|
||||
let shopOpened = false;
|
||||
let openedShopId = '';
|
||||
core.registerReplayAction('openShop', name => {
|
||||
if (!name.startsWith('openShop:')) return false;
|
||||
if (shopOpened) return false;
|
||||
openedShopId = name.slice(9);
|
||||
shopOpened = true;
|
||||
core.status.route.push(name);
|
||||
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[openedShopId] as ItemShopEvent;
|
||||
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 as number) > item.number - flags.itemShop[openedShopId][id]) {
|
||||
return false;
|
||||
}
|
||||
let cost = 0;
|
||||
if (type === 'buy') {
|
||||
cost = parseInt(item.money) * (num as number);
|
||||
} else {
|
||||
cost = -item.sell * (num as number);
|
||||
}
|
||||
if (cost > core.status.hero.money) return false;
|
||||
core.status.hero.money -= cost;
|
||||
flags.itemShop[openedShopId][id] += type === 'buy' ? num : -num;
|
||||
core.addItem(
|
||||
id as AllIdsOf<'items'>,
|
||||
(type === 'buy' ? num : -num) as number
|
||||
);
|
||||
core.status.route.push(name);
|
||||
core.replay();
|
||||
return true;
|
||||
});
|
||||
|
||||
core.registerReplayAction('closeShop', name => {
|
||||
if (name !== 'closeShop') return false;
|
||||
if (!shopOpened) return false;
|
||||
shopOpened = false;
|
||||
openedShopId = '';
|
||||
core.status.route.push(name);
|
||||
core.replay();
|
||||
return true;
|
||||
});
|
||||
}
|
@ -1,27 +1,29 @@
|
||||
///<reference path="../../../src/types/core.d.ts" />
|
||||
|
||||
const { openItemShop } = core.plugin.gameUi;
|
||||
|
||||
export function openShop(shopId, noRoute) {
|
||||
var shop = core.status.shops[shopId];
|
||||
export function openShop(shopId: string, noRoute: boolean) {
|
||||
const shop = core.status.shops[shopId] as ItemShopEvent;
|
||||
// Step 1: 检查能否打开此商店
|
||||
if (!this.canOpenShop(shopId)) {
|
||||
if (!canOpenShop(shopId)) {
|
||||
core.drawTip('该商店尚未开启');
|
||||
return false;
|
||||
}
|
||||
|
||||
// Step 3: 检查道具商店 or 公共事件
|
||||
if (shop.item) {
|
||||
if (openItemShop) openItemShop(shopId);
|
||||
Mota.r(() => {
|
||||
if (!core.isReplaying()) {
|
||||
Mota.require('var', 'mainUi').open('shop', {
|
||||
shopId: shopId
|
||||
});
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// 是否访问过某个快捷商店
|
||||
export function isShopVisited(id) {
|
||||
export function isShopVisited(id: string) {
|
||||
flags.__shops__ ??= {};
|
||||
var shops = core.getFlag('__shops__');
|
||||
var shops = core.getFlag<any>('__shops__');
|
||||
if (!shops[id]) shops[id] = {};
|
||||
return shops[id].visited;
|
||||
}
|
||||
@ -29,25 +31,24 @@ export function isShopVisited(id) {
|
||||
/// 当前应当显示的快捷商店列表
|
||||
export function listShopIds() {
|
||||
return Object.keys(core.status.shops).filter(id => {
|
||||
return (
|
||||
core.plugin.shop.isShopVisited(id) ||
|
||||
!core.status.shops[id].mustEnable
|
||||
);
|
||||
// @ts-ignore
|
||||
return isShopVisited(id) || !core.status.shops[id].mustEnable;
|
||||
});
|
||||
}
|
||||
|
||||
/// 是否能够打开某个商店
|
||||
export function canOpenShop(id) {
|
||||
if (this.isShopVisited(id)) return true;
|
||||
export function canOpenShop(id: string) {
|
||||
if (isShopVisited(id)) return true;
|
||||
var shop = core.status.shops[id];
|
||||
// @ts-ignore
|
||||
if (shop.item || shop.commonEvent || shop.mustEnable) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// 启用或禁用某个快捷商店
|
||||
export function setShopVisited(id, visited) {
|
||||
export function setShopVisited(id: string, visited: boolean) {
|
||||
if (!core.hasFlag('__shops__')) core.setFlag('__shops__', {});
|
||||
var shops = core.getFlag('__shops__');
|
||||
var shops = core.getFlag<any>('__shops__');
|
||||
if (!shops[id]) shops[id] = {};
|
||||
if (visited) shops[id].visited = true;
|
||||
else delete shops[id].visited;
|
||||
@ -63,12 +64,3 @@ export function canUseQuickShop() {
|
||||
return '当前楼层不能使用快捷商店。';
|
||||
return null;
|
||||
}
|
||||
|
||||
core.plugin.shop = {
|
||||
openShop,
|
||||
isShopVisited,
|
||||
listShopIds,
|
||||
canOpenShop,
|
||||
setShopVisited,
|
||||
canUseQuickShop
|
||||
};
|
@ -1,4 +1,4 @@
|
||||
///<reference path="../../../src/types/core.d.ts" />
|
||||
// @ts-nocheck
|
||||
|
||||
// 所有的主动技能效果
|
||||
var ignoreInJump = {
|
||||
@ -19,8 +19,7 @@ var ignoreInJump = {
|
||||
]
|
||||
};
|
||||
|
||||
/** @type {FloorIds[]} */
|
||||
export const jumpIgnoreFloor = [
|
||||
export const jumpIgnoreFloor: FloorIds[] = [
|
||||
'MT31',
|
||||
'snowTown',
|
||||
'MT36',
|
||||
@ -178,8 +177,3 @@ export function jumpSkill() {
|
||||
return { x: x, y: y };
|
||||
}
|
||||
}
|
||||
|
||||
core.plugin.skillEffects = {
|
||||
jumpSkill,
|
||||
jumpIgnoreFloor
|
||||
};
|
@ -1,14 +1,11 @@
|
||||
///<reference path="../../../src/types/core.d.ts" />
|
||||
|
||||
/**
|
||||
* @type {number[]}
|
||||
*/
|
||||
let levels = [];
|
||||
let levels: number[] = [];
|
||||
|
||||
/**
|
||||
* @type {Record<Chapter, Skill[]>}
|
||||
*/
|
||||
const skills = {
|
||||
export const skills: Record<Chapter, Skill[]> = {
|
||||
chapter1: [
|
||||
{
|
||||
index: 0,
|
||||
@ -195,13 +192,11 @@ const skills = {
|
||||
]
|
||||
};
|
||||
|
||||
core.plugin.skills = skills;
|
||||
|
||||
export function resetSkillLevel() {
|
||||
levels = [];
|
||||
}
|
||||
|
||||
export function getSkillFromIndex(index) {
|
||||
export function getSkillFromIndex(index: number) {
|
||||
for (const [, skill] of Object.entries(skills)) {
|
||||
const s = skill.find(v => v.index === index);
|
||||
if (s) return s;
|
||||
@ -212,16 +207,21 @@ export function getSkillFromIndex(index) {
|
||||
* 获取技能等级
|
||||
* @param {number} skill
|
||||
*/
|
||||
export function getSkillLevel(skill) {
|
||||
export function getSkillLevel(skill: number) {
|
||||
return (levels[skill] ??= 0);
|
||||
}
|
||||
|
||||
export function getSkillConsume(skill) {
|
||||
export function getSkillConsume(skill: number) {
|
||||
return eval(
|
||||
getSkillFromIndex(skill).consume.replace(/level(:\d+)?/g, (str, $1) => {
|
||||
if ($1) return `core.plugin.skillTree.getSkillLevel(${$1})`;
|
||||
else return `core.plugin.skillTree.getSkillLevel(${skill})`;
|
||||
})
|
||||
getSkillFromIndex(skill)?.consume.replace(
|
||||
/level(:\d+)?/g,
|
||||
(str, $1) => {
|
||||
if ($1)
|
||||
return `Mota.Plugin.require('skillTree_g').getSkillLevel(${$1})`;
|
||||
else
|
||||
return `Mota.Plugin.require('skillTree_g').getSkillLevel(${skill})`;
|
||||
}
|
||||
) ?? ''
|
||||
);
|
||||
}
|
||||
|
||||
@ -232,17 +232,16 @@ export function openTree() {
|
||||
|
||||
/**
|
||||
* 能否升级某个技能
|
||||
* @param {number} skill
|
||||
*/
|
||||
export function canUpgrade(skill) {
|
||||
const consume = core.plugin.skillTree.getSkillConsume(skill);
|
||||
export function canUpgrade(skill: number) {
|
||||
const consume = getSkillConsume(skill);
|
||||
if (consume > core.status.hero.mdef) return false;
|
||||
const level = core.plugin.skillTree.getSkillLevel(skill);
|
||||
const level = getSkillLevel(skill);
|
||||
const s = getSkillFromIndex(skill);
|
||||
if (level === s.max) return false;
|
||||
const front = s.front;
|
||||
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;
|
||||
if (getSkillLevel(skill) < level) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -251,7 +250,7 @@ export function canUpgrade(skill) {
|
||||
* 实际升级效果
|
||||
* @param {number} skill
|
||||
*/
|
||||
export function upgradeSkill(skill) {
|
||||
export function upgradeSkill(skill: number) {
|
||||
if (!canUpgrade(skill)) return false;
|
||||
switch (skill) {
|
||||
case 0: // 力量 +2攻击
|
||||
@ -302,17 +301,6 @@ export function saveSkillTree() {
|
||||
return levels.slice();
|
||||
}
|
||||
|
||||
export function loadSkillTree(data) {
|
||||
export function loadSkillTree(data: number[]) {
|
||||
levels = data ?? [];
|
||||
}
|
||||
|
||||
core.plugin.skillTree = {
|
||||
getSkillConsume,
|
||||
getSkillFromIndex,
|
||||
getSkillLevel,
|
||||
saveSkillTree,
|
||||
loadSkillTree,
|
||||
upgradeSkill,
|
||||
openTree,
|
||||
resetSkillLevel
|
||||
};
|
@ -12,7 +12,8 @@ const cannotStudy = [9, 12, 14, 15, 24];
|
||||
|
||||
export function canStudySkill(number: number) {
|
||||
const s = (core.status.hero.special ??= { num: [], last: [] });
|
||||
if (core.plugin.skillTree.getSkillLevel(11) === 0) return false;
|
||||
if (Mota.Plugin.require('skillTree_g').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;
|
||||
|
@ -1,4 +1,4 @@
|
||||
///<reference path="../../../src/types/core.d.ts" />
|
||||
// @ts-nocheck
|
||||
import { clip } from './replay.js';
|
||||
|
||||
// 1000多行,改不动了,原来什么样就什么样吧
|
||||
@ -11,7 +11,7 @@ var stage = 1,
|
||||
boomLocs = [], // 随机轰炸
|
||||
heroHp;
|
||||
// 初始化
|
||||
function initTowerBoss() {
|
||||
export function initTowerBoss() {
|
||||
stage = 1;
|
||||
hp = 10000;
|
||||
seconds = 0;
|
||||
@ -496,7 +496,7 @@ function intelligentArrow(fromSelf) {
|
||||
damaged[loc + direction] = true;
|
||||
core.drawHeroAnimate('hand');
|
||||
core.status.hero.hp -= 1000;
|
||||
Mota.Plugin.require('pop').addPop(
|
||||
Mota.Plugin.require('pop_r').addPop(
|
||||
x * 32 + 16,
|
||||
y * 32 + 16,
|
||||
-1000
|
||||
@ -515,7 +515,7 @@ function intelligentArrow(fromSelf) {
|
||||
damaged[loc + direction] = true;
|
||||
core.drawHeroAnimate('hand');
|
||||
core.status.hero.hp -= 1000;
|
||||
Mota.Plugin.require('pop').addPop(
|
||||
Mota.Plugin.require('pop_r').addPop(
|
||||
x * 32 + 16,
|
||||
y * 32 + 16,
|
||||
-1000
|
||||
@ -645,7 +645,7 @@ function icyMomentem() {
|
||||
if (x == locs[index][0] && y == locs[index][1]) {
|
||||
core.drawHeroAnimate('hand');
|
||||
core.status.hero.hp -= 5000;
|
||||
Mota.Plugin.require('pop').addPop(
|
||||
Mota.Plugin.require('pop_r').addPop(
|
||||
x * 32 + 16,
|
||||
y * 32 + 16,
|
||||
-5000
|
||||
@ -824,7 +824,7 @@ function getThunderDamage(x, y, power) {
|
||||
hy = core.status.hero.loc.y;
|
||||
if (Math.abs(hx - x) <= 1 && Math.abs(hy - y) <= 1) {
|
||||
core.status.hero.hp -= 3000 * power;
|
||||
Mota.Plugin.require('pop').addPop(
|
||||
Mota.Plugin.require('pop_r').addPop(
|
||||
x * 32 + 16,
|
||||
y * 32 + 16,
|
||||
-3000 * power
|
||||
@ -992,7 +992,7 @@ function ballThunder() {
|
||||
) {
|
||||
damaged[i] = true;
|
||||
core.status.hero.hp -= 3000;
|
||||
Mota.Plugin.require('pop').addPop(
|
||||
Mota.Plugin.require('pop_r').addPop(
|
||||
x * 32 + 16,
|
||||
y * 32 + 16,
|
||||
-3000
|
||||
@ -1502,7 +1502,7 @@ function boomingAnimate() {
|
||||
hy = core.status.hero.loc.y;
|
||||
if (loc[0] == hx && loc[1] == hy) {
|
||||
core.status.hero.hp -= 3000;
|
||||
Mota.Plugin.require('pop').addPop(
|
||||
Mota.Plugin.require('pop_r').addPop(
|
||||
x * 32 + 16,
|
||||
y * 32 + 16,
|
||||
-3000
|
||||
@ -1545,7 +1545,7 @@ function lineDamage(x1, y1, x2, y2, damage) {
|
||||
n2 = ((y2 - y1) / (x2 - x1)) * (loc2[0] - x1) + y1 - loc2[1];
|
||||
if (n1 * n2 <= 0) {
|
||||
core.status.hero.hp -= damage;
|
||||
Mota.Plugin.require('pop').addPop(
|
||||
Mota.Plugin.require('pop_r').addPop(
|
||||
x * 32 + 16,
|
||||
y * 32 + 16,
|
||||
-damage
|
||||
@ -1569,7 +1569,7 @@ function lineDamage(x1, y1, x2, y2, damage) {
|
||||
n2 = ((y2 - y1) / (x2 - x1)) * (loc2[0] - x1) + y1 - loc2[1];
|
||||
if (n1 * n2 <= 0) {
|
||||
core.status.hero.hp -= damage;
|
||||
Mota.Plugin.require('pop').addPop(
|
||||
Mota.Plugin.require('pop_r').addPop(
|
||||
x * 32 + 16,
|
||||
y * 32 + 16,
|
||||
-damage
|
||||
@ -1587,9 +1587,3 @@ function lineDamage(x1, y1, x2, y2, damage) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
core.plugin.towerBoss = {
|
||||
initTowerBoss
|
||||
};
|
||||
|
||||
export {};
|
@ -1,29 +1,8 @@
|
||||
///<reference path="../../../src/types/core.d.ts" />
|
||||
export {};
|
||||
// @ts-nocheck
|
||||
|
||||
(function () {
|
||||
export function init() {
|
||||
const { mainUi, fixedUi } = Mota.requireAll('var');
|
||||
|
||||
if (main.replayChecking)
|
||||
return (core.plugin.gameUi = {
|
||||
openItemShop: () => 0,
|
||||
openSkill: () => 0
|
||||
});
|
||||
|
||||
function openItemShop(itemShopId) {
|
||||
if (!core.isReplaying()) {
|
||||
Mota.require('var', 'mainUi').open('shop', {
|
||||
shopId: itemShopId
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function updateVueStatusBar() {
|
||||
if (main.replayChecking) return;
|
||||
const status = Mota.Plugin.require('status');
|
||||
status.statusBarStatus.value = !status.statusBarStatus.value;
|
||||
}
|
||||
|
||||
ui.prototype.drawBook = function () {
|
||||
if (!core.isReplaying()) return mainUi.open('book');
|
||||
};
|
||||
@ -86,14 +65,11 @@ export {};
|
||||
core.dom.toolBar.style.display = 'none';
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function openSkill() {
|
||||
if (core.isReplaying()) return;
|
||||
mainUi.open('skill');
|
||||
}
|
||||
|
||||
core.plugin.gameUi = {
|
||||
openItemShop,
|
||||
openSkill
|
||||
};
|
||||
})();
|
||||
function updateVueStatusBar() {
|
||||
Mota.r(() => {
|
||||
const status = Mota.require('var', 'status');
|
||||
status.value = !status.value;
|
||||
});
|
||||
}
|
@ -169,18 +169,3 @@ export function findDir(from: Loc, to: Loc): Dir2 | 'none' {
|
||||
})?.[0] as Dir2) ?? 'none'
|
||||
);
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface GamePluginUtils {
|
||||
ofDir: typeof ofDir;
|
||||
}
|
||||
}
|
||||
|
||||
core.plugin.utils = {
|
||||
slide,
|
||||
backDir,
|
||||
has,
|
||||
maxGameScale,
|
||||
ofDir
|
||||
};
|
||||
core.has = has;
|
||||
|
@ -35,8 +35,8 @@ const marked: MarkInfo<EnemyIds>[] = [];
|
||||
*/
|
||||
export function markEnemy(id: EnemyIds) {
|
||||
if (hasMarkedEnemy(id)) return;
|
||||
const { Enemy } = core.plugin.damage;
|
||||
const enemy = new Enemy(core.material.enemys[id]);
|
||||
const { DamageEnemy } = Mota.Plugin.require('damage_g');
|
||||
const enemy = new DamageEnemy(core.material.enemys[id]);
|
||||
enemy.calAttribute();
|
||||
enemy.getRealInfo();
|
||||
|
||||
@ -44,7 +44,7 @@ export function markEnemy(id: EnemyIds) {
|
||||
id,
|
||||
enemy,
|
||||
mode: 0b011111,
|
||||
lastAtk: core.plugin.hero.getHeroStatusOn('atk', 'empty'),
|
||||
lastAtk: Mota.Plugin.require('hero_g').getHeroStatusOn('atk', 'empty'),
|
||||
lastDamage: enemy.calDamage().damage,
|
||||
status: 0b0,
|
||||
update: ref(true)
|
||||
@ -66,9 +66,10 @@ export function unmarkEnemy(id: EnemyIds) {
|
||||
}
|
||||
|
||||
export function checkMarkedEnemy() {
|
||||
const { getHeroStatusOn } = Mota.Plugin.require('hero_g');
|
||||
marked.forEach(v => {
|
||||
const { id, enemy, mode, lastAtk, lastDamage, markDamage } = v;
|
||||
const atk = core.plugin.hero.getHeroStatusOn('atk', 'empty');
|
||||
const atk = getHeroStatusOn('atk', 'empty');
|
||||
let tip = 0;
|
||||
if (mode & 0b11110) {
|
||||
const damage = enemy.calDamage().damage;
|
||||
|
@ -36,26 +36,11 @@ export interface Light {
|
||||
_offset?: Loc;
|
||||
}
|
||||
|
||||
export default function init() {
|
||||
export function init() {
|
||||
core.registerAnimationFrame('shadow', true, () => {
|
||||
if (!needRefresh) return;
|
||||
drawShadow();
|
||||
});
|
||||
|
||||
return {
|
||||
initShadowCanvas,
|
||||
drawShadow,
|
||||
addLight,
|
||||
removeLight,
|
||||
setLight,
|
||||
setShadowNodes,
|
||||
setBackground,
|
||||
animateLight,
|
||||
transitionLight,
|
||||
moveLightAs,
|
||||
getAllLights,
|
||||
refreshLight
|
||||
};
|
||||
}
|
||||
|
||||
let canvas: HTMLCanvasElement;
|
||||
|
@ -59,13 +59,14 @@ export function getNowStatus(nowEquip?: Equip, onCol: boolean = false) {
|
||||
'hpmax',
|
||||
'money'
|
||||
] as (keyof SelectType<HeroStatus, number>)[];
|
||||
const { getHeroStatusOn } = Mota.Plugin.require('hero_g');
|
||||
|
||||
return (
|
||||
<div id="hero-status">
|
||||
{toShow.map(v => {
|
||||
let status: string;
|
||||
if (v === 'lv') status = core.getLvName() ?? '';
|
||||
else status = core.plugin.hero.getHeroStatusOn(v)?.toString();
|
||||
else status = getHeroStatusOn(v)?.toString();
|
||||
|
||||
let add = 0;
|
||||
if (has(nowEquip)) {
|
||||
|
@ -29,7 +29,7 @@ export function getDetailedEnemy(
|
||||
return typeof func === 'string' ? func : func(enemy);
|
||||
};
|
||||
const special: [string, string, string][] = enemy.enemy.special.map(vv => {
|
||||
const s = core.plugin.special[vv];
|
||||
const s = Mota.Plugin.require('special_g').special[vv];
|
||||
return [
|
||||
fromFunc(s.name, enemy.enemy),
|
||||
fromFunc(s.desc, enemy.enemy),
|
||||
|
@ -225,6 +225,7 @@ export async function doByInterval(
|
||||
|
||||
/**
|
||||
* 更改一个本地存储
|
||||
* @deprecated
|
||||
* @param name 要更改的信息
|
||||
* @param fn 更改时执行的函数
|
||||
* @param defaultValue 如果不存在时获取的默认值
|
||||
@ -287,7 +288,8 @@ export function spliceBy<T>(arr: T[], from: T): T[] {
|
||||
}
|
||||
|
||||
export async function triggerFullscreen(full: boolean) {
|
||||
const { maxGameScale } = core.plugin.utils;
|
||||
if (!Mota.Plugin.inited) return;
|
||||
const { maxGameScale } = Mota.Plugin.require('utils_g');
|
||||
if (!!document.fullscreenElement && !full) {
|
||||
await document.exitFullscreen();
|
||||
requestAnimationFrame(() => {
|
||||
|
3
src/types/control.d.ts
vendored
3
src/types/control.d.ts
vendored
@ -1068,6 +1068,9 @@ interface Control {
|
||||
* 屏幕分辨率改变后执行的函数
|
||||
*/
|
||||
resize(): void;
|
||||
|
||||
_drawHero_updateViewport(x: number, y: number, offset: Loc): void;
|
||||
_moveAction_moving(callback: () => void): void;
|
||||
}
|
||||
|
||||
declare const control: new () => Control;
|
||||
|
8
src/types/core.d.ts
vendored
8
src/types/core.d.ts
vendored
@ -1062,11 +1062,6 @@ interface Core extends Pick<Main, CoreDataFromMain> {
|
||||
*/
|
||||
readonly actions: Actions;
|
||||
|
||||
/**
|
||||
* 游戏的插件模块
|
||||
*/
|
||||
readonly plugin: PluginDeclaration;
|
||||
|
||||
/**
|
||||
* 进行游戏初始化
|
||||
* @param coreData 初始化信息
|
||||
@ -1098,8 +1093,7 @@ type CoreMixin = Core &
|
||||
Forward<Ui> &
|
||||
Forward<Utils> &
|
||||
Forward<Icons> &
|
||||
Forward<Actions> &
|
||||
Forward<PluginDeclaration>;
|
||||
Forward<Actions>;
|
||||
|
||||
interface MainStyle extends Readonly<StatusStyle> {
|
||||
/**
|
||||
|
2
src/types/enemy.d.ts
vendored
2
src/types/enemy.d.ts
vendored
@ -272,6 +272,8 @@ interface Enemys {
|
||||
floorId?: FloorIds,
|
||||
dir?: Dir | 'none' | (Dir | 'none')[]
|
||||
): boolean;
|
||||
|
||||
getCurrentEnemys(floorId: FloorIds): any[];
|
||||
}
|
||||
|
||||
declare const enemys: new () => Enemys;
|
||||
|
5
src/types/event.d.ts
vendored
5
src/types/event.d.ts
vendored
@ -758,11 +758,16 @@ interface Events extends EventData {
|
||||
*/
|
||||
tryUseItem(itemId: ItemIdOf<'tools' | 'constants'>): void;
|
||||
|
||||
beforeBattle(): boolean;
|
||||
afterBattle(enemy: DamageEnemy, x?: number, y?: number): void;
|
||||
|
||||
_sys_battle(data: Block, callback?: () => void): void;
|
||||
|
||||
_action_battle(data: any, x?: number, y?: number, prefix?: any): void;
|
||||
|
||||
__action_getLoc(data: any, x?: number, y?: number, prefix?: any): any;
|
||||
|
||||
_changeFloor_beforeChange(info: any, callback: () => void): void;
|
||||
}
|
||||
|
||||
declare const events: new () => Events;
|
||||
|
4
src/types/map.d.ts
vendored
4
src/types/map.d.ts
vendored
@ -84,6 +84,10 @@ interface Block<N extends Exclude<AllNumbers, 0> = Exclude<AllNumbers, 0>> {
|
||||
* 门信息
|
||||
*/
|
||||
doorInfo?: DoorInfo;
|
||||
|
||||
data?: any;
|
||||
script?: string;
|
||||
event?: MotaEvent;
|
||||
};
|
||||
}
|
||||
|
||||
|
4
src/types/util.d.ts
vendored
4
src/types/util.d.ts
vendored
@ -713,7 +713,9 @@ type MotaTrigger =
|
||||
| 'openDoor'
|
||||
| 'ski'
|
||||
| 'custom'
|
||||
| 'getItem';
|
||||
| 'getItem'
|
||||
| 'changeFloor'
|
||||
| 'null';
|
||||
|
||||
/**
|
||||
* 切换楼层的目标坐标
|
||||
|
@ -83,7 +83,7 @@ const special = (() => {
|
||||
};
|
||||
|
||||
const show = s.slice(0, 2).map(v => {
|
||||
const s = core.plugin.special[v];
|
||||
const s = Mota.Plugin.require('special_g').specials[v];
|
||||
return [fromFunc(s.name, enemy.enemy), s.color];
|
||||
});
|
||||
if (s.length > 2) show.push(['...', 'white']);
|
||||
|
@ -58,7 +58,7 @@ const content = computed(() => {
|
||||
.join('')
|
||||
.replace(
|
||||
/level:(\d+)/g,
|
||||
'core.plugin.skillTree.getSkillLevel($1)'
|
||||
'Mota.Plugin.require("skillTree_g").getSkillLevel($1)'
|
||||
) +
|
||||
'`'
|
||||
);
|
||||
|
@ -89,6 +89,8 @@ const props = defineProps<{
|
||||
ui: GameUi;
|
||||
}>();
|
||||
|
||||
const skillTree = Mota.Plugin.require('skillTree_g');
|
||||
|
||||
let canvas: HTMLCanvasElement;
|
||||
let ctx: CanvasRenderingContext2D;
|
||||
|
||||
@ -103,9 +105,11 @@ const chapterDict = {
|
||||
|
||||
flags.skillTree ??= 0;
|
||||
|
||||
const chapterList = Object.keys(core.plugin.skills) as Chapter[];
|
||||
const s = Mota.Plugin.require('skillTree_g').skills;
|
||||
|
||||
selected.value = core.plugin.skills[chapterList[flags.skillTree]][0].index;
|
||||
const chapterList = Object.keys(s) as Chapter[];
|
||||
|
||||
selected.value = s[chapterList[flags.skillTree]][0].index;
|
||||
chapter.value = chapterList[flags.skillTree];
|
||||
|
||||
watch(selected, draw);
|
||||
@ -115,20 +119,19 @@ const mdef = ref(core.status.hero.mdef);
|
||||
|
||||
const skill = computed(() => {
|
||||
update.value;
|
||||
return core.plugin.skillTree.getSkillFromIndex(selected.value);
|
||||
return skillTree.getSkillFromIndex(selected.value);
|
||||
});
|
||||
|
||||
const skills = computed(() => {
|
||||
return core.plugin.skills[chapter.value];
|
||||
return s[chapter.value];
|
||||
});
|
||||
|
||||
const desc = computed(() => {
|
||||
return eval(
|
||||
'`' +
|
||||
splitText(skill.value.desc).replace(/level(:\d+)?/g, (str, $1) => {
|
||||
if ($1) return `core.plugin.skillTree.getSkillLevel(${$1})`;
|
||||
else
|
||||
return `core.plugin.skillTree.getSkillLevel(${skill.value.index})`;
|
||||
if ($1) return `skillTree.getSkillLevel(${$1})`;
|
||||
else return `skillTree.getSkillLevel(${skill.value.index})`;
|
||||
}) +
|
||||
'`'
|
||||
);
|
||||
@ -143,9 +146,9 @@ const effect = computed(() => {
|
||||
.join('')
|
||||
.replace(/level(:\d+)?/g, (str, $1) => {
|
||||
if ($1)
|
||||
return `(core.plugin.skillTree.getSkillLevel(${$1}) + ${v})`;
|
||||
return `(skillTree.getSkillLevel(${$1}) + ${v})`;
|
||||
else
|
||||
return `(core.plugin.skillTree.getSkillLevel(${skill.value.index}) + ${v})`;
|
||||
return `(skillTree.getSkillLevel(${skill.value.index}) + ${v})`;
|
||||
}) +
|
||||
'`'
|
||||
);
|
||||
@ -163,20 +166,20 @@ const dict = computed(() => {
|
||||
|
||||
const front = computed(() => {
|
||||
return skill.value.front.map(v => {
|
||||
return `${
|
||||
core.plugin.skillTree.getSkillLevel(v[0]) >= v[1] ? 'a' : 'b'
|
||||
}${v[1]}级 ${skills.value[dict.value[v[0]]].title}`;
|
||||
return `${skillTree.getSkillLevel(v[0]) >= v[1] ? 'a' : 'b'}${
|
||||
v[1]
|
||||
}级 ${skills.value[dict.value[v[0]]].title}`;
|
||||
});
|
||||
});
|
||||
|
||||
const consume = computed(() => {
|
||||
update.value;
|
||||
return core.plugin.skillTree.getSkillConsume(selected.value);
|
||||
return skillTree.getSkillConsume(selected.value);
|
||||
});
|
||||
|
||||
const level = computed(() => {
|
||||
update.value;
|
||||
return core.plugin.skillTree.getSkillLevel(selected.value);
|
||||
return skillTree.getSkillLevel(selected.value);
|
||||
});
|
||||
|
||||
function exit() {
|
||||
@ -204,9 +207,9 @@ function draw() {
|
||||
ctx.lineTo(
|
||||
...(s.loc.map(v => (v * 2 - 1) * per + per / 2) as LocArr)
|
||||
);
|
||||
if (core.plugin.skillTree.getSkillLevel(s.index) < v.front[i][1])
|
||||
if (skillTree.getSkillLevel(s.index) < v.front[i][1])
|
||||
ctx.strokeStyle = '#aaa';
|
||||
else if (core.plugin.skillTree.getSkillLevel(s.index) === s.max)
|
||||
else if (skillTree.getSkillLevel(s.index) === s.max)
|
||||
ctx.strokeStyle = '#ff0';
|
||||
else ctx.strokeStyle = '#0f8';
|
||||
ctx.lineWidth = devicePixelRatio;
|
||||
@ -215,7 +218,7 @@ function draw() {
|
||||
});
|
||||
skills.value.forEach(v => {
|
||||
const [x, y] = v.loc.map(v => v * 2 - 1);
|
||||
const level = core.plugin.skillTree.getSkillLevel(v.index);
|
||||
const level = skillTree.getSkillLevel(v.index);
|
||||
// 技能图标
|
||||
ctx.save();
|
||||
ctx.lineWidth = per * 0.06;
|
||||
@ -256,7 +259,7 @@ function click(e: MouseEvent) {
|
||||
}
|
||||
|
||||
function upgrade(index: number) {
|
||||
const success = core.plugin.skillTree.upgradeSkill(index);
|
||||
const success = skillTree.upgradeSkill(index);
|
||||
if (!success) tip('error', '升级失败!');
|
||||
else {
|
||||
tip('success', '升级成功!');
|
||||
@ -296,7 +299,7 @@ function selectChapter(delta: number) {
|
||||
const to = now + delta;
|
||||
|
||||
if (has(chapterList[to]) && flags.chapter > to) {
|
||||
selected.value = core.plugin.skills[chapterList[to]][0].index;
|
||||
selected.value = s[chapterList[to]][0].index;
|
||||
chapter.value = chapterList[to];
|
||||
update.value = !update.value;
|
||||
flags.skillTree = to;
|
||||
|
@ -137,6 +137,8 @@ import { status } from '../plugin/ui/statusBar';
|
||||
import { isMobile } from '../plugin/use';
|
||||
import { has } from '../plugin/utils';
|
||||
|
||||
const skillTree = Mota.Plugin.require('skillTree_g');
|
||||
|
||||
const width = ref(
|
||||
isMobile ? window.innerWidth - 60 : window.innerWidth * 0.175
|
||||
);
|
||||
@ -155,7 +157,7 @@ const skill = ref<string>(flags.autoSkill ? '自动切换' : '无');
|
||||
const up = ref(0);
|
||||
const spring = ref<number>();
|
||||
const skillOpened = ref(core.getFlag('chapter', 0) > 0);
|
||||
const studyOpened = ref(core.plugin.skillTree.getSkillLevel(11) > 0);
|
||||
const studyOpened = ref(skillTree.getSkillLevel(11) > 0);
|
||||
const jumpCnt = ref<number>();
|
||||
/**
|
||||
* 要展示的勇士属性
|
||||
@ -178,9 +180,8 @@ watch(status, update);
|
||||
* 更新显示内容
|
||||
*/
|
||||
function update() {
|
||||
if (!core?.plugin?.hero?.getHeroStatusOn) return;
|
||||
toShow.forEach(v => {
|
||||
hero[v] = core.plugin.hero.getHeroStatusOn(v);
|
||||
hero[v] = Mota.Plugin.require('hero_g').getHeroStatusOn(v);
|
||||
});
|
||||
keys[0] = core.itemCount('yellowKey');
|
||||
keys[1] = core.itemCount('blueKey');
|
||||
@ -205,10 +206,12 @@ function update() {
|
||||
spring.value = void 0;
|
||||
}
|
||||
skillOpened.value = core.getFlag('chapter', 0) > 0;
|
||||
studyOpened.value = core.plugin.skillTree.getSkillLevel(11) > 0;
|
||||
studyOpened.value = skillTree.getSkillLevel(11) > 0;
|
||||
jumpCnt.value =
|
||||
flags.skill2 &&
|
||||
!core.plugin.skillEffects.jumpIgnoreFloor.includes(core.status.floorId)
|
||||
!Mota.Plugin.require('skill_g').jumpIgnoreFloor.includes(
|
||||
core.status.floorId
|
||||
)
|
||||
? 3 - (flags[`jump_${core.status.floorId}`] ?? 0)
|
||||
: void 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user