mirror of
https://github.com/unanmed/HumanBreak.git
synced 2025-04-19 17:16:08 +08:00
fix: 报错和部分布局
This commit is contained in:
parent
f5df2c1416
commit
e506a43437
@ -531,12 +531,10 @@ var data_comment_c456ea59_6018_45ef_8bcc_211a24c627dc = {
|
||||
"金币",
|
||||
"<br>经验",
|
||||
"升级",
|
||||
"<br>升级扣除模式",
|
||||
"<br>钥匙",
|
||||
"绿钥",
|
||||
"<br>破炸",
|
||||
"负面",
|
||||
"<br>技能"
|
||||
"负面"
|
||||
],
|
||||
"key": [
|
||||
"enableFloor",
|
||||
@ -551,12 +549,10 @@ var data_comment_c456ea59_6018_45ef_8bcc_211a24c627dc = {
|
||||
"enableMoney",
|
||||
"enableExp",
|
||||
"enableLevelUp",
|
||||
"levelUpLeftMode",
|
||||
"enableKeys",
|
||||
"enableGreenKey",
|
||||
"enablePZF",
|
||||
"enableDebuff",
|
||||
"enableSkill"
|
||||
"enableDebuff"
|
||||
]
|
||||
},
|
||||
"_data": "状态栏显示项"
|
||||
|
@ -884,7 +884,12 @@ control.prototype._moveAction_popAutomaticRoute = function () {
|
||||
|
||||
////// 让勇士开始移动 //////
|
||||
control.prototype.moveHero = function (direction, callback) {
|
||||
// see src/plugin/game/popup.js
|
||||
// 如果正在移动,直接return
|
||||
if (core.status.heroMoving != 0) return;
|
||||
if (core.isset(direction)) core.setHeroLoc('direction', direction);
|
||||
|
||||
if (callback) return this.moveAction(callback);
|
||||
this._moveHero_moving();
|
||||
};
|
||||
|
||||
control.prototype._moveHero_moving = function () {
|
||||
@ -1444,7 +1449,7 @@ control.prototype.updateCheckBlock = function (floorId) {
|
||||
|
||||
////// 检查并执行领域、夹击、阻击事件 //////
|
||||
control.prototype.checkBlock = function () {
|
||||
// see src/plugin/game/popup.js
|
||||
// see src/plugin/game/enemy/checkblock.js
|
||||
};
|
||||
|
||||
control.prototype._checkBlock_disableQuickShop = function () {
|
||||
@ -1501,7 +1506,46 @@ control.prototype.drawDamage = function (ctx, floorId = core.status.floorId) {
|
||||
};
|
||||
|
||||
control.prototype._drawDamage_draw = function (ctx, onMap) {
|
||||
// Deprecated. See src/plugin/game/fx/checkblock.js
|
||||
if (!core.hasItem('book')) return;
|
||||
|
||||
core.setFont(ctx, 'bold 11px Arial');
|
||||
core.setTextAlign(ctx, 'left');
|
||||
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);
|
||||
});
|
||||
|
||||
core.setTextAlign(ctx, 'center');
|
||||
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);
|
||||
core.setAlpha(ctx, alpha);
|
||||
});
|
||||
};
|
||||
|
||||
// ------ 录像相关 ------ //
|
||||
@ -2334,9 +2378,6 @@ control.prototype._doSL_load = function (id, callback) {
|
||||
id == 'autoSave' ? id : 'save' + id,
|
||||
null,
|
||||
function (data) {
|
||||
if (!main.replayChecking && data) {
|
||||
Mota.require('var', 'fixedUi').closeByName('start');
|
||||
}
|
||||
if (id == 'autoSave' && data != null) {
|
||||
core.saves.autosave.data = data;
|
||||
if (!(core.saves.autosave.data instanceof Array)) {
|
||||
@ -2393,6 +2434,9 @@ control.prototype._doSL_load_afterGet = function (id, data) {
|
||||
}
|
||||
core.ui.closePanel();
|
||||
core.loadData(data, function () {
|
||||
if (!main.replayChecking) {
|
||||
Mota.require('var', 'fixedUi').closeByName('start');
|
||||
}
|
||||
core.removeFlag('__fromLoad__');
|
||||
core.drawTip('读档成功');
|
||||
if (id != 'autoSave') {
|
||||
@ -2812,17 +2856,17 @@ control.prototype.getStatus = function (name) {
|
||||
|
||||
////// 从status中获得属性,如果不存在则从勇士属性中获取 //////
|
||||
control.prototype.getStatusOrDefault = function (status, name) {
|
||||
// Deprecated. See src/plugin/game/hero.ts
|
||||
// Deprecated. See src/game/hero.ts
|
||||
};
|
||||
|
||||
////// 获得勇士实际属性(增幅后的) //////
|
||||
control.prototype.getRealStatus = function (name) {
|
||||
// Deprecated. See src/plugin/game/hero.ts
|
||||
// Deprecated. See src/game/hero.ts
|
||||
};
|
||||
|
||||
////// 从status中获得实际属性(增幅后的),如果不存在则从勇士属性中获取 //////
|
||||
control.prototype.getRealStatusOrDefault = function (status, name) {
|
||||
// Deprecated. See src/plugin/game/hero.ts
|
||||
// Deprecated. See src/game/hero.ts
|
||||
};
|
||||
|
||||
////// 获得勇士原始属性(无装备和衰弱影响) //////
|
||||
|
@ -94,7 +94,7 @@ enemys.prototype.getEnemyValue = function (enemy, name, x, y, floorId) {
|
||||
|
||||
////// 能否获胜 //////
|
||||
enemys.prototype.canBattle = function (enemy, x, y, floorId) {
|
||||
// Deprecated. See src/plugin/game/enemy/battle.ts
|
||||
// Deprecated. See src/game/enemy/battle.ts
|
||||
};
|
||||
|
||||
enemys.prototype.getDamageString = function (enemy, x, y, floorId, hero) {
|
||||
|
@ -30,7 +30,6 @@ events.prototype.startGame = function (hard, seed, route, callback) {
|
||||
}
|
||||
|
||||
if (main.mode != 'play') return;
|
||||
Mota.Plugin.require('skillTree_g').resetSkillLevel();
|
||||
|
||||
// 无动画的开始游戏
|
||||
if (core.flags.startUsingCanvas || route != null) {
|
||||
@ -495,22 +494,22 @@ events.prototype._trigger_ignoreChangeFloor = function (block) {
|
||||
};
|
||||
|
||||
events.prototype._sys_battle = function (data, callback) {
|
||||
// Deprecated. See /src/plugin/game/enemy/battle.ts
|
||||
// Deprecated. See /src/game/enemy/battle.ts
|
||||
};
|
||||
|
||||
////// 战斗 //////
|
||||
events.prototype.battle = function (id, x, y, force, callback) {
|
||||
// Deprecated. See src/plugin/game/enemy/battle.ts
|
||||
// Deprecated. See src/game/enemy/battle.ts
|
||||
};
|
||||
|
||||
////// 战斗前触发的事件 //////
|
||||
events.prototype.beforeBattle = function (enemyId, x, y) {
|
||||
// Deprecated. See src/plugin/game/enemy/battle.ts
|
||||
// Deprecated. See src/game/enemy/battle.ts
|
||||
};
|
||||
|
||||
////// 战斗结束后触发的事件 //////
|
||||
events.prototype.afterBattle = function (enemyId, x, y) {
|
||||
// Deprecated. See src/plugin/game/enemy/battle.ts
|
||||
// Deprecated. See src/game/enemy/battle.ts
|
||||
};
|
||||
|
||||
events.prototype._sys_openDoor = function (data, callback) {
|
||||
|
@ -742,14 +742,23 @@ var data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d =
|
||||
"flags": {
|
||||
"statusBarItems": [
|
||||
"enableFloor",
|
||||
"enableName",
|
||||
"enableLv",
|
||||
"enableHPMax",
|
||||
"enableHP",
|
||||
"enableMana",
|
||||
"enableAtk",
|
||||
"enableDef",
|
||||
"enableMDef",
|
||||
"enableMoney",
|
||||
"enableKeys"
|
||||
"enableExp",
|
||||
"enableLevelUp",
|
||||
"enableKeys",
|
||||
"enableGreenKey",
|
||||
"enablePZF",
|
||||
"enableDebuff"
|
||||
],
|
||||
"extendToolbar": false,
|
||||
"extendToolbar": true,
|
||||
"flyNearStair": true,
|
||||
"flyRecordPosition": false,
|
||||
"itemFirstText": false,
|
||||
|
@ -1,82 +1,82 @@
|
||||
var enemys_fcae963b_31c9_42b4_b48c_bb48d09f3f80 =
|
||||
{
|
||||
"greenSlime": {"name":"绿头怪","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":0},
|
||||
"greenSlime": {"name":"绿头怪","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[]},
|
||||
"redSlime": {"name":"红头怪","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[16,18],"value":10},
|
||||
"blackSlime": {"name":"青头怪","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":0},
|
||||
"blackSlime": {"name":"青头怪","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[]},
|
||||
"slimelord": {"name":"怪王","hp":100,"atk":120,"def":0,"money":10,"exp":0,"point":0,"special":[1,9]},
|
||||
"bat": {"name":"小蝙蝠","hp":100,"atk":120,"def":0,"money":2,"exp":0,"point":0,"special":[1]},
|
||||
"bigBat": {"name":"大蝙蝠","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":0},
|
||||
"bigBat": {"name":"大蝙蝠","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[]},
|
||||
"redBat": {"name":"红蝙蝠","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[]},
|
||||
"vampire": {"name":"冥灵魔王","hp":888,"atk":888,"def":888,"money":888,"exp":888,"point":0,"special":[6],"n":8},
|
||||
"skeleton": {"name":"骷髅人","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":0},
|
||||
"skeletonCaptain": {"name":"骷髅队长","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":0},
|
||||
"zombie": {"name":"兽人","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":0},
|
||||
"zombieKnight": {"name":"兽人武士","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":0},
|
||||
"rock": {"name":"石头人","hp":50,"atk":50,"def":0,"money":3,"exp":0,"point":0,"special":3},
|
||||
"skeleton": {"name":"骷髅人","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[]},
|
||||
"skeletonCaptain": {"name":"骷髅队长","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[]},
|
||||
"zombie": {"name":"兽人","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[]},
|
||||
"zombieKnight": {"name":"兽人武士","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[]},
|
||||
"rock": {"name":"石头人","hp":50,"atk":50,"def":0,"money":3,"exp":0,"point":0,"special":[3]},
|
||||
"bluePriest": {"name":"初级法师","hp":100,"atk":120,"def":0,"money":3,"exp":0,"point":1,"special":[9]},
|
||||
"redPriest": {"name":"高级法师","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":0},
|
||||
"brownWizard": {"name":"初级巫师","hp":100,"atk":120,"def":0,"money":16,"exp":0,"point":0,"special":15,"value":100,"range":2},
|
||||
"redWizard": {"name":"高级巫师","hp":1000,"atk":1200,"def":0,"money":160,"exp":0,"point":0,"special":15,"value":200,"zoneSquare":true},
|
||||
"swordsman": {"name":"双手剑士","hp":100,"atk":120,"def":0,"money":6,"exp":0,"point":0,"special":4},
|
||||
"soldier": {"name":"冥战士","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":0},
|
||||
"yellowKnight": {"name":"金骑士","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":0},
|
||||
"redPriest": {"name":"高级法师","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[]},
|
||||
"brownWizard": {"name":"初级巫师","hp":100,"atk":120,"def":0,"money":16,"exp":0,"point":0,"special":[15],"value":100,"range":2},
|
||||
"redWizard": {"name":"高级巫师","hp":1000,"atk":1200,"def":0,"money":160,"exp":0,"point":0,"special":[15],"value":200,"zoneSquare":true},
|
||||
"swordsman": {"name":"双手剑士","hp":100,"atk":120,"def":0,"money":6,"exp":0,"point":0,"special":[4]},
|
||||
"soldier": {"name":"冥战士","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[]},
|
||||
"yellowKnight": {"name":"金骑士","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[]},
|
||||
"redKnight": {"name":"红骑士","hp":500,"atk":200,"def":50,"money":0,"exp":0,"point":0,"special":[7]},
|
||||
"darkKnight": {"name":"黑骑士","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":0},
|
||||
"blueKnight": {"name":"蓝骑士","hp":100,"atk":120,"def":0,"money":9,"exp":0,"point":0,"special":8},
|
||||
"goldSlime": {"name":"黄头怪","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":0},
|
||||
"poisonSkeleton": {"name":"紫骷髅","hp":50,"atk":60,"def":70,"money":80,"exp":0,"point":0,"special":13},
|
||||
"poisonBat": {"name":"紫蝙蝠","hp":100,"atk":120,"def":0,"money":14,"exp":0,"point":0,"special":13},
|
||||
"skeletonPriest": {"name":"骷髅法师","hp":100,"atk":100,"def":0,"money":0,"exp":0,"point":0,"special":18,"value":20},
|
||||
"skeletonKing": {"name":"骷髅王","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":0},
|
||||
"evilHero": {"name":"迷失勇者","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":0},
|
||||
"demonPriest": {"name":"魔神法师","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":0},
|
||||
"goldHornSlime": {"name":"金角怪","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":0},
|
||||
"silverSlime": {"name":"银头怪","hp":100,"atk":120,"def":0,"money":15,"exp":0,"point":0,"special":14},
|
||||
"whiteHornSlime": {"name":"尖角怪","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":0},
|
||||
"darkKnight": {"name":"黑骑士","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[]},
|
||||
"blueKnight": {"name":"蓝骑士","hp":100,"atk":120,"def":0,"money":9,"exp":0,"point":0,"special":[8]},
|
||||
"goldSlime": {"name":"黄头怪","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[]},
|
||||
"poisonSkeleton": {"name":"紫骷髅","hp":50,"atk":60,"def":70,"money":80,"exp":0,"point":0,"special":[13]},
|
||||
"poisonBat": {"name":"紫蝙蝠","hp":100,"atk":120,"def":0,"money":14,"exp":0,"point":0,"special":[13]},
|
||||
"skeletonPriest": {"name":"骷髅法师","hp":100,"atk":100,"def":0,"money":0,"exp":0,"point":0,"special":[18],"value":20},
|
||||
"skeletonKing": {"name":"骷髅王","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[]},
|
||||
"evilHero": {"name":"迷失勇者","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[]},
|
||||
"demonPriest": {"name":"魔神法师","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[]},
|
||||
"goldHornSlime": {"name":"金角怪","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[]},
|
||||
"silverSlime": {"name":"银头怪","hp":100,"atk":120,"def":0,"money":15,"exp":0,"point":0,"special":[14]},
|
||||
"whiteHornSlime": {"name":"尖角怪","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[]},
|
||||
"redSwordsman": {"name":"剑王","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[]},
|
||||
"poisonZombie": {"name":"绿兽人","hp":100,"atk":120,"def":0,"money":13,"exp":0,"point":0,"special":[12]},
|
||||
"octopus": {"name":"血影","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":0,"bigImage":"dragon_1.png"},
|
||||
"princessEnemy": {"name":"假公主","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":0},
|
||||
"angel": {"name":"天使","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":0},
|
||||
"elemental": {"name":"元素生物","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":0},
|
||||
"octopus": {"name":"血影","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[],"bigImage":"dragon_1.png"},
|
||||
"princessEnemy": {"name":"假公主","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[]},
|
||||
"angel": {"name":"天使","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[]},
|
||||
"elemental": {"name":"元素生物","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[]},
|
||||
"steelGuard": {"name":"铁守卫","hp":50,"atk":50,"def":50,"money":0,"exp":0,"point":0,"special":[18],"value":20},
|
||||
"evilBat": {"name":"邪恶蝙蝠","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":0},
|
||||
"silverSlimelord": {"name":"银怪王","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":0},
|
||||
"goldSlimelord": {"name":"金怪王","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":0},
|
||||
"skeletonWarrior": {"name":"骷髅士兵","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":0},
|
||||
"whiteSlimeman": {"name":"水银战士","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":0},
|
||||
"evilBat": {"name":"邪恶蝙蝠","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[]},
|
||||
"silverSlimelord": {"name":"银怪王","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[]},
|
||||
"goldSlimelord": {"name":"金怪王","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[]},
|
||||
"skeletonWarrior": {"name":"骷髅士兵","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[]},
|
||||
"whiteSlimeman": {"name":"水银战士","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[]},
|
||||
"slimeman": {"name":"影子战士","hp":100,"atk":0,"def":0,"money":11,"exp":0,"point":0,"special":[9],"atkValue":2,"defValue":3},
|
||||
"yellowGateKeeper": {"name":"初级卫兵","hp":100,"atk":120,"def":0,"money":10,"exp":0,"point":0,"special":0},
|
||||
"blueGateKeeper": {"name":"中级卫兵","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":0},
|
||||
"redGateKeeper": {"name":"高级卫兵","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":0},
|
||||
"magicMaster": {"name":"黑暗大法师","hp":100,"atk":120,"def":0,"money":12,"exp":0,"point":0,"special":11,"value":0.3333333333333333,"add":true,"notBomb":true},
|
||||
"devilWarrior": {"name":"魔神武士","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":0},
|
||||
"fairyEnemy": {"name":"仙子","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":0},
|
||||
"dragon": {"name":"魔龙","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":0,"bigImage":"dragon_0.png"},
|
||||
"skeletonKnight": {"name":"骷髅武士","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":0},
|
||||
"skeletonPresbyter": {"name":"骷髅巫师","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":0},
|
||||
"ironRock": {"name":"铁面人","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":0},
|
||||
"grayRock": {"name":"灰色石头人","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":0},
|
||||
"yellowPriest": {"name":"中级法师","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":0},
|
||||
"yellowGateKeeper": {"name":"初级卫兵","hp":100,"atk":120,"def":0,"money":10,"exp":0,"point":0,"special":[]},
|
||||
"blueGateKeeper": {"name":"中级卫兵","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[]},
|
||||
"redGateKeeper": {"name":"高级卫兵","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[]},
|
||||
"magicMaster": {"name":"黑暗大法师","hp":100,"atk":120,"def":0,"money":12,"exp":0,"point":0,"special":[11],"value":0.3333333333333333,"add":true,"notBomb":true},
|
||||
"devilWarrior": {"name":"魔神武士","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[]},
|
||||
"fairyEnemy": {"name":"仙子","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[]},
|
||||
"dragon": {"name":"魔龙","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[],"bigImage":"dragon_0.png"},
|
||||
"skeletonKnight": {"name":"骷髅武士","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[]},
|
||||
"skeletonPresbyter": {"name":"骷髅巫师","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[]},
|
||||
"ironRock": {"name":"铁面人","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[]},
|
||||
"grayRock": {"name":"灰色石头人","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[]},
|
||||
"yellowPriest": {"name":"中级法师","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[]},
|
||||
"evilPrincess": {"name":"痛苦魔女","hp":1000,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[10]},
|
||||
"blademaster": {"name":"剑圣","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":0},
|
||||
"evilFairy": {"name":"黑暗仙子","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":0},
|
||||
"greenKnight": {"name":"强盾骑士","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":0},
|
||||
"bowman": {"name":"初级弓兵","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":0},
|
||||
"watcherSlime": {"name":"邪眼怪","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":0},
|
||||
"blademaster": {"name":"剑圣","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[]},
|
||||
"evilFairy": {"name":"黑暗仙子","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[]},
|
||||
"greenKnight": {"name":"强盾骑士","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[]},
|
||||
"bowman": {"name":"初级弓兵","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[]},
|
||||
"watcherSlime": {"name":"邪眼怪","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[]},
|
||||
"devilKnight": {"name":"恶灵骑士","hp":150,"atk":100,"def":50,"money":0,"exp":0,"point":0,"special":[1,5,7,8]},
|
||||
"grayPriest": {"name":"混沌法师","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":0},
|
||||
"greenGateKeeper": {"name":"卫兵队长","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":0},
|
||||
"ghostSoldier": {"name":"冥队长","hp":200,"atk":100,"def":50,"money":0,"exp":0,"point":0,"special":8},
|
||||
"frostBat": {"name":"寒蝙蝠","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":0},
|
||||
"blackKing": {"name":"黑衣魔王","hp":1000,"atk":500,"def":0,"money":1000,"exp":1000,"point":0,"special":0,"notBomb":true},
|
||||
"yellowKing": {"name":"黄衣魔王","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":0},
|
||||
"greenKing": {"name":"青衣武士","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":0},
|
||||
"redKing": {"name":"红衣魔王","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":0},
|
||||
"blueKing": {"name":"白衣武士","hp":100,"atk":120,"def":0,"money":17,"exp":0,"point":0,"special":16},
|
||||
"keiskeiFairy": {"name":"铃兰花妖","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":0},
|
||||
"tulipFairy": {"name":"郁金香花妖","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":0},
|
||||
"purpleBowman": {"name":"高级弓兵","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":0},
|
||||
"grayPriest": {"name":"混沌法师","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[]},
|
||||
"greenGateKeeper": {"name":"卫兵队长","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[]},
|
||||
"ghostSoldier": {"name":"冥队长","hp":200,"atk":100,"def":50,"money":0,"exp":0,"point":0,"special":[8]},
|
||||
"frostBat": {"name":"寒蝙蝠","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[]},
|
||||
"blackKing": {"name":"黑衣魔王","hp":1000,"atk":500,"def":0,"money":1000,"exp":1000,"point":0,"special":[],"notBomb":true},
|
||||
"yellowKing": {"name":"黄衣魔王","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[]},
|
||||
"greenKing": {"name":"青衣武士","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[]},
|
||||
"redKing": {"name":"红衣魔王","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[]},
|
||||
"blueKing": {"name":"白衣武士","hp":100,"atk":120,"def":0,"money":17,"exp":0,"point":0,"special":[16]},
|
||||
"keiskeiFairy": {"name":"铃兰花妖","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[]},
|
||||
"tulipFairy": {"name":"郁金香花妖","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[]},
|
||||
"purpleBowman": {"name":"高级弓兵","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[]},
|
||||
"bearDown": {"name":"熊出没","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[],"faceIds":{"down":"bearDown","left":"bearLeft","right":"bearRight","up":"bearUp"},"bigImage":"bear.png"},
|
||||
"bearLeft": {"name":"熊出没","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[],"faceIds":{"down":"bearDown","left":"bearLeft","right":"bearRight","up":"bearUp"}},
|
||||
"bearRight": {"name":"熊出没","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[],"faceIds":{"down":"bearDown","left":"bearLeft","right":"bearRight","up":"bearUp"}},
|
||||
|
@ -1,8 +1,8 @@
|
||||
main.floors.empty=
|
||||
{
|
||||
"floorId": "empty",
|
||||
"title": "山脚",
|
||||
"name": "13",
|
||||
"title": "空地图",
|
||||
"name": "空地图",
|
||||
"width": 15,
|
||||
"height": 15,
|
||||
"canFlyTo": false,
|
||||
@ -11,7 +11,7 @@ main.floors.empty=
|
||||
"cannotViewMap": true,
|
||||
"images": [],
|
||||
"ratio": 1,
|
||||
"defaultGround": "grass",
|
||||
"defaultGround": "ground",
|
||||
"bgm": "mount.mp3",
|
||||
"weather": [
|
||||
"sun",
|
||||
|
@ -49,12 +49,10 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = {
|
||||
if (core.hasFlag('hideStatusBar'))
|
||||
core.hideStatusBar(core.hasFlag('showToolbox'));
|
||||
else core.showStatusBar();
|
||||
if (main.mode === 'play' && !main.replayChecking) {
|
||||
Mota.r(() => {
|
||||
Mota.Plugin.require('fly_r').splitArea();
|
||||
Mota.require('var', 'hook').emit('reset');
|
||||
} else {
|
||||
flags.autoSkill ??= true;
|
||||
}
|
||||
});
|
||||
},
|
||||
win: function (reason, norank, noexit) {
|
||||
// 游戏获胜事件
|
||||
@ -66,12 +64,6 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = {
|
||||
core.status.extraEvent = core.clone(core.status.event);
|
||||
}
|
||||
|
||||
if (reason === '智慧之始') {
|
||||
core.status.hero.hp +=
|
||||
core.itemCount('yellowKey') * 5000 +
|
||||
core.itemCount('blueKey') * 15000;
|
||||
}
|
||||
|
||||
// 游戏获胜事件
|
||||
core.ui.closePanel();
|
||||
var replaying = core.isReplaying();
|
||||
@ -113,8 +105,6 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = {
|
||||
// 正在切换楼层过程中执行的操作;此函数的执行时间是“屏幕完全变黑“的那一刻
|
||||
// floorId为要切换到的楼层ID;heroLoc表示勇士切换到的位置
|
||||
|
||||
const { checkLoopMap } = Mota.Plugin.require('loopMap_g');
|
||||
|
||||
flags.floorChanging = true;
|
||||
|
||||
// ---------- 此时还没有进行切换,当前floorId还是原来的 ---------- //
|
||||
@ -170,8 +160,6 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = {
|
||||
if (weather) core.setWeather(weather[0], weather[1]);
|
||||
else core.setWeather();
|
||||
|
||||
checkLoopMap();
|
||||
|
||||
// ...可以新增一些其他内容,比如创建个画布在右上角显示什么内容等等
|
||||
},
|
||||
afterChangeFloor: function (floorId) {
|
||||
@ -322,18 +310,13 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = {
|
||||
values: values,
|
||||
version: core.firstData.version,
|
||||
guid: core.getGuid(),
|
||||
time: new Date().getTime(),
|
||||
skills: Mota.Plugin.require('skillTree_g').saveSkillTree()
|
||||
time: new Date().getTime()
|
||||
};
|
||||
|
||||
return data;
|
||||
},
|
||||
loadData: function (data, callback) {
|
||||
// 读档操作;从存储中读取了内容后的行为
|
||||
if (window.flags && flags.onChase) {
|
||||
flags.chase.end();
|
||||
flags.onChase = true;
|
||||
}
|
||||
// 重置游戏和路线
|
||||
core.resetGame(
|
||||
data.hero,
|
||||
@ -371,8 +354,6 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = {
|
||||
}
|
||||
core.setFlag('__fromLoad__', true);
|
||||
|
||||
Mota.Plugin.require('skillTree_g').loadSkillTree(data.skills);
|
||||
|
||||
// 切换到对应的楼层
|
||||
core.changeFloor(data.floorId, null, data.hero.loc, 0, function () {
|
||||
if (core.hasFlag('__bgm__')) {
|
||||
@ -382,13 +363,6 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = {
|
||||
|
||||
core.removeFlag('__fromLoad__');
|
||||
if (callback) callback();
|
||||
|
||||
if (flags.onChase) {
|
||||
Mota.Plugin.require('chase_r').startChase(flags.chaseIndex);
|
||||
if (flags.chaseIndex === 1) {
|
||||
core.playBgm('escape.mp3', 43.5);
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
updateStatusBar: function () {
|
||||
@ -397,32 +371,58 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = {
|
||||
// 检查等级
|
||||
core.events.checkLvUp();
|
||||
|
||||
// 如果是自定义添加的状态栏,也需要在这里进行设置显示的数值
|
||||
const getHeroStatusOn = Mota.require('fn', 'getHeroStatusOn');
|
||||
|
||||
// 检查HP上限
|
||||
if (core.flags.statusBarItems.indexOf('enableHPMax') >= 0) {
|
||||
core.setStatus(
|
||||
'hp',
|
||||
Math.min(getHeroStatusOn('hpmax'), core.getStatus('hp'))
|
||||
);
|
||||
}
|
||||
|
||||
// 设置生命上限、生命值、攻防护盾金币和经验值
|
||||
var statusList = [
|
||||
'hpmax',
|
||||
'hp',
|
||||
'mana',
|
||||
'atk',
|
||||
'def',
|
||||
'mdef',
|
||||
'money',
|
||||
'exp'
|
||||
];
|
||||
statusList.forEach(function (item) {
|
||||
// 向下取整
|
||||
core.status.hero[item] = Math.floor(core.status.hero[item]);
|
||||
});
|
||||
|
||||
// 设置魔力值; status:manamax 只有在非负时才生效。
|
||||
if (
|
||||
core.status.hero.manamax != null &&
|
||||
core.getRealStatus('manamax') >= 0
|
||||
) {
|
||||
core.status.hero.mana = Math.min(
|
||||
core.status.hero.mana,
|
||||
core.getRealStatus('manamax')
|
||||
);
|
||||
}
|
||||
|
||||
// 难度
|
||||
if (core.statusBar.hard.innerText != core.status.hard) {
|
||||
core.statusBar.hard.innerText = core.status.hard;
|
||||
}
|
||||
var hardColor = core.getFlag('__hardColor__', 'red');
|
||||
var hardColor = core.getFlag('__hardColor__');
|
||||
if (hardColor == null) core.statusBar.hard.innerText = '';
|
||||
if (core.statusBar.hard.getAttribute('_style') != hardColor) {
|
||||
core.statusBar.hard.style.color = hardColor;
|
||||
core.statusBar.hard.setAttribute('_style', hardColor);
|
||||
}
|
||||
|
||||
// 更新全地图显伤
|
||||
// 更新阻激夹域的伤害值
|
||||
core.updateCheckBlock();
|
||||
// updateDamage只能在此处执行!!更新全地图显伤
|
||||
core.updateDamage();
|
||||
|
||||
if (main.replayChecking) return;
|
||||
|
||||
// 已学习的技能
|
||||
// if (
|
||||
// core.plugin.skillTree.getSkillLevel(11) > 0 &&
|
||||
// (core.status.hero.special?.num ?? []).length > 0
|
||||
// ) {
|
||||
// mota.plugin.ui.showStudiedSkill.value = true;
|
||||
// } else {
|
||||
// mota.plugin.ui.showStudiedSkill.value = false;
|
||||
// }
|
||||
},
|
||||
moveOneStep: function (callback) {
|
||||
// 勇士每走一步后执行的操作。callback为行走完毕后的回调
|
||||
@ -432,8 +432,6 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = {
|
||||
// 2, 将楼层属性中的cannotMoveDirectly这个开关勾上,即禁止在该层楼使用瞬移。
|
||||
// 3. 将flag:cannotMoveDirectly置为true,即可使用flag控制在某段剧情范围内禁止瞬移。
|
||||
|
||||
const { checkLoopMap } = Mota.Plugin.require('loopMap_g');
|
||||
|
||||
// 增加步数
|
||||
core.status.hero.steps++;
|
||||
// 更新跟随者状态,并绘制
|
||||
@ -480,136 +478,6 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = {
|
||||
);
|
||||
}
|
||||
|
||||
checkLoopMap();
|
||||
|
||||
// 追猎
|
||||
// todo: 重写
|
||||
if (
|
||||
core.status.checkBlock.haveHunt &&
|
||||
!core
|
||||
.getBlockId(core.status.hero.loc.x, core.status.hero.loc.y)
|
||||
?.endsWith('Portal')
|
||||
) {
|
||||
var x = core.status.hero.loc.x,
|
||||
y = core.status.hero.loc.y;
|
||||
core.status.maps[core.status.floorId].blocks.forEach(function (
|
||||
block
|
||||
) {
|
||||
if (block.x != x && block.y != y) return;
|
||||
var id = block.event.id,
|
||||
enemy = core.material.enemys[id];
|
||||
if (enemy && core.hasSpecial(enemy.special, 12)) {
|
||||
var nx = block.x,
|
||||
ny = block.y;
|
||||
var dx = Math.abs(x - nx),
|
||||
dy = Math.abs(y - ny);
|
||||
if (x == block.x) {
|
||||
if (
|
||||
y > block.y &&
|
||||
!core.noPass(block.x, block.y + 1) &&
|
||||
core.getBlockCls(block.x, block.y + 1) !=
|
||||
'items'
|
||||
) {
|
||||
dy--;
|
||||
ny++;
|
||||
core.insertAction([
|
||||
{
|
||||
type: 'move',
|
||||
loc: [block.x, block.y],
|
||||
time: 200,
|
||||
keep: true,
|
||||
steps: ['down:1']
|
||||
},
|
||||
{
|
||||
type: 'if',
|
||||
condition: dy + '<=1',
|
||||
true: [
|
||||
{ type: 'battle', loc: [nx, ny] }
|
||||
]
|
||||
}
|
||||
]);
|
||||
}
|
||||
if (
|
||||
y < block.y &&
|
||||
!core.noPass(block.x, block.y - 1) &&
|
||||
core.getBlockCls(block.x, block.y - 1) !=
|
||||
'items'
|
||||
) {
|
||||
dy--;
|
||||
ny--;
|
||||
core.insertAction([
|
||||
{
|
||||
type: 'move',
|
||||
loc: [block.x, block.y],
|
||||
time: 200,
|
||||
keep: true,
|
||||
steps: ['up:1']
|
||||
},
|
||||
{
|
||||
type: 'if',
|
||||
condition: dy + '<=1',
|
||||
true: [
|
||||
{ type: 'battle', loc: [nx, ny] }
|
||||
]
|
||||
}
|
||||
]);
|
||||
}
|
||||
} else {
|
||||
if (
|
||||
x > block.x &&
|
||||
!core.noPass(block.x + 1, block.y) &&
|
||||
core.getBlockCls(block.x + 1, block.y) !=
|
||||
'items'
|
||||
) {
|
||||
dx--;
|
||||
nx++;
|
||||
core.insertAction([
|
||||
{
|
||||
type: 'move',
|
||||
loc: [block.x, block.y],
|
||||
time: 200,
|
||||
keep: true,
|
||||
steps: ['right:1']
|
||||
},
|
||||
{
|
||||
type: 'if',
|
||||
condition: dx + '<=1',
|
||||
true: [
|
||||
{ type: 'battle', loc: [nx, ny] }
|
||||
]
|
||||
}
|
||||
]);
|
||||
}
|
||||
if (
|
||||
x < block.x &&
|
||||
!core.noPass(block.x - 1, block.y) &&
|
||||
core.getBlockCls(block.x - 1, block.y) !=
|
||||
'items'
|
||||
) {
|
||||
dx--;
|
||||
nx--;
|
||||
core.insertAction([
|
||||
{
|
||||
type: 'move',
|
||||
loc: [block.x, block.y],
|
||||
time: 200,
|
||||
keep: true,
|
||||
steps: ['left:1']
|
||||
},
|
||||
{
|
||||
type: 'if',
|
||||
condition: dx + '<=1',
|
||||
true: [
|
||||
{ type: 'battle', loc: [nx, ny] }
|
||||
]
|
||||
}
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 如需强行终止行走可以在这里条件判定:
|
||||
// core.stopAutomaticRoute();
|
||||
},
|
||||
|
@ -1,10 +1,4 @@
|
||||
var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = {
|
||||
init: function () {
|
||||
// 对于一部分的常用插件,样板已经内置,同时配有开关,可以在设置里面开关
|
||||
// 以及那些只提供api的插件也是已经内置
|
||||
// 这里内置的插件只有不容易开关的插件
|
||||
this._afterLoadResources = function () {};
|
||||
},
|
||||
fiveLayer: function () {
|
||||
// 注册插件
|
||||
Mota.Plugin.register('fiveLayer_g', { init }, init);
|
||||
@ -225,5 +219,228 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = {
|
||||
};
|
||||
};
|
||||
}
|
||||
},
|
||||
uiRewrite: function () {
|
||||
Mota.Plugin.register('ui_g', { init }, init);
|
||||
|
||||
function init() {
|
||||
const { mainUi, fixedUi } = Mota.requireAll('var');
|
||||
|
||||
ui.prototype.drawBook = function () {
|
||||
if (!core.isReplaying()) return mainUi.open('book');
|
||||
};
|
||||
|
||||
ui.prototype._drawToolbox = function () {
|
||||
if (!core.isReplaying()) return mainUi.open('toolbox');
|
||||
};
|
||||
|
||||
ui.prototype._drawEquipbox = function () {
|
||||
if (!core.isReplaying()) return mainUi.open('equipbox');
|
||||
};
|
||||
|
||||
ui.prototype.drawFly = function () {
|
||||
if (!core.isReplaying()) return mainUi.open('fly');
|
||||
};
|
||||
|
||||
control.prototype.updateStatusBar_update = function () {
|
||||
core.control.updateNextFrame = false;
|
||||
if (!core.isPlaying() || core.hasFlag('__statistics__')) return;
|
||||
core.control.controldata.updateStatusBar();
|
||||
if (!core.control.noAutoEvents) core.checkAutoEvents();
|
||||
core.control._updateStatusBar_setToolboxIcon();
|
||||
core.clearRouteFolding();
|
||||
core.control.noAutoEvents = true;
|
||||
// 更新vue状态栏
|
||||
updateVueStatusBar();
|
||||
Mota.require('var', 'hook').emit('statusBarUpdate');
|
||||
};
|
||||
|
||||
// todo: 多个状态栏分离与控制
|
||||
control.prototype.showStatusBar = function () {
|
||||
if (main.mode == 'editor') return;
|
||||
core.removeFlag('hideStatusBar');
|
||||
if (!fixedUi.hasName('statusBar')) {
|
||||
fixedUi.open('statusBar');
|
||||
}
|
||||
core.dom.tools.hard.style.display = 'block';
|
||||
core.dom.toolBar.style.display = 'block';
|
||||
};
|
||||
|
||||
control.prototype.hideStatusBar = function (showToolbox) {
|
||||
if (main.mode == 'editor') return;
|
||||
|
||||
// 如果原本就是隐藏的,则先显示
|
||||
if (!core.domStyle.showStatusBar) this.showStatusBar();
|
||||
if (core.isReplaying()) showToolbox = true;
|
||||
fixedUi.closeByName('statusBar');
|
||||
|
||||
var toolItems = core.dom.tools;
|
||||
core.setFlag('hideStatusBar', true);
|
||||
core.setFlag('showToolbox', showToolbox || null);
|
||||
if (
|
||||
(!core.domStyle.isVertical && !core.flags.extendToolbar) ||
|
||||
!showToolbox
|
||||
) {
|
||||
for (var i = 0; i < toolItems.length; ++i)
|
||||
toolItems[i].style.display = 'none';
|
||||
}
|
||||
if (!core.domStyle.isVertical && !core.flags.extendToolbar) {
|
||||
core.dom.toolBar.style.display = 'none';
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function updateVueStatusBar() {
|
||||
Mota.r(() => {
|
||||
const status = Mota.require('var', 'status');
|
||||
status.value = !status.value;
|
||||
});
|
||||
}
|
||||
},
|
||||
battle: function () {
|
||||
// 这个插件负责战斗相关内容
|
||||
|
||||
// --------------- 战斗伤害
|
||||
|
||||
const Damage = Mota.require('module', 'Damage');
|
||||
// 这个数组常量控制着在战斗时哪些属性计算真实属性,也就是经过buff加成的属性
|
||||
// 如果有属性不会经过buff加成等,请将其去除,可以提高性能表现
|
||||
Damage.realStatus = ['atk', 'def', 'mdef', 'hpmax'];
|
||||
|
||||
// 复写系统的伤害计算函数即可,全量复写
|
||||
// 函数接受两个参数,分别是怪物信息和勇士信息,返回一个数字作为伤害
|
||||
// 返回null表示不能战斗,返回Infinity也可以
|
||||
Mota.rewrite(Damage, 'calDamageWith', 'full', (info, hero) => {
|
||||
// 获取勇士属性,这几个属性直接从core.status.hero获取
|
||||
const { hp, mana } = core.status.hero;
|
||||
// 获取勇士属性,这几个属性从勇士真实属性获取
|
||||
// 分开获取是因为获取勇士真实属性会对性能造成一定影响
|
||||
let { atk, def, mdef, hpmax } = hero;
|
||||
// 获取怪物信息,是在某点的信息
|
||||
let { hp: monHp, atk: monAtk, def: monDef, special, enemy } = info;
|
||||
|
||||
/** 总伤害 */
|
||||
let damage = 0;
|
||||
/** 勇士单回合伤害 */
|
||||
let heroPerDamage;
|
||||
|
||||
if (special.includes(3)) {
|
||||
// 由于坚固的特性,只能放到这来计算了
|
||||
if (atk > enemy.def) heroPerDamage = 1;
|
||||
else return null;
|
||||
} else {
|
||||
heroPerDamage = atk - monDef;
|
||||
if (heroPerDamage <= 0) return null;
|
||||
}
|
||||
|
||||
/** 怪物单回合伤害 */
|
||||
let enemyPerDamage;
|
||||
|
||||
// 魔攻
|
||||
if (special.includes(2) || special.includes(13)) {
|
||||
enemyPerDamage = monAtk;
|
||||
} else {
|
||||
enemyPerDamage = monAtk - def;
|
||||
if (enemyPerDamage < 0) enemyPerDamage = 0;
|
||||
}
|
||||
|
||||
// 先攻
|
||||
if (special.includes(17)) {
|
||||
damage += enemyPerDamage;
|
||||
}
|
||||
|
||||
// 连击
|
||||
if (special.includes(4)) enemyPerDamage *= 2;
|
||||
if (special.includes(5)) enemyPerDamage *= 3;
|
||||
if (special.includes(6)) enemyPerDamage *= enemy.n;
|
||||
|
||||
/** 战斗回合 */
|
||||
let turn = Math.ceil(monHp / heroPerDamage);
|
||||
|
||||
damage += (turn - 1) * enemyPerDamage;
|
||||
damage -= mdef;
|
||||
if (!core.flags.enableNegativeDamage) damage = Math.max(0, damage);
|
||||
|
||||
return damage;
|
||||
});
|
||||
|
||||
// --------------- 地图伤害
|
||||
// 全量复写地图伤害的计算函数,注意此处不能使用箭头函数,因为这是在原型上的函数,其this指向实例,也即怪物(DamageEnemy实例)
|
||||
// 函数接收两个参数,damage和hero,前者表示要将结果存入的对象,后者是勇士真实属性
|
||||
// 直接将damage返回即可,返回其他值有可能会引起出错
|
||||
// 计算出伤害后直接调用this.setMapDamage即可将伤害传到对象中
|
||||
Mota.rewrite(
|
||||
Mota.require('class', 'DamageEnemy').prototype,
|
||||
'calMapDamage',
|
||||
'full',
|
||||
function (damage = {}, hero = getHeroStatusOn(Damage.realStatus)) {
|
||||
// 功能函数,计算曼哈顿距离,和判断一个值是否存在
|
||||
const { manhattan, has } = Mota.Plugin.require('utils_g');
|
||||
// 判断这个怪物是不是在地图上
|
||||
if (!has(this.x) || !has(this.y) || !has(this.floorId))
|
||||
return damage;
|
||||
const enemy = this.enemy;
|
||||
const floor = core.status.maps[this.floorId];
|
||||
const w = floor.width;
|
||||
const h = floor.height;
|
||||
|
||||
// 突刺
|
||||
if (this.info.special.includes(15)) {
|
||||
const range = enemy.range ?? 1;
|
||||
const startX = Math.max(0, this.x - range);
|
||||
const startY = Math.max(0, this.y - range);
|
||||
const endX = Math.min(floor.width - 1, this.x + range);
|
||||
const endY = Math.min(floor.height - 1, this.y + range);
|
||||
const dam = Math.max((enemy.value ?? 0) - hero.def, 0);
|
||||
|
||||
for (let x = startX; x <= endX; x++) {
|
||||
for (let y = startY; y <= endY; y++) {
|
||||
if (
|
||||
!enemy.zoneSquare &&
|
||||
manhattan(x, y, this.x, this.y) > range
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
const loc = `${x},${y}`;
|
||||
this.setMapDamage(damage, loc, dam, '突刺');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 射击
|
||||
if (this.info.special.includes(24)) {
|
||||
const dirs = ['left', 'down', 'up', 'right'];
|
||||
const dam = Math.max((enemy.atk ?? 0) - hero.def, 0);
|
||||
const objs = core.getMapBlocksObj(this.floorId);
|
||||
|
||||
for (const dir of dirs) {
|
||||
let x = this.x;
|
||||
let y = this.y;
|
||||
const { x: dx, y: dy } = core.utils.scan[dir];
|
||||
while (x >= 0 && y >= 0 && x < w && y < h) {
|
||||
x += dx;
|
||||
y += dy;
|
||||
const loc = `${x},${y}`;
|
||||
const block = objs[loc];
|
||||
if (
|
||||
block &&
|
||||
block.event.noPass &&
|
||||
block.event.cls !== 'enemys' &&
|
||||
block.event.cls !== 'enemy48' &&
|
||||
block.id !== 141 &&
|
||||
block.id !== 151
|
||||
) {
|
||||
break;
|
||||
}
|
||||
this.setMapDamage(damage, loc, dam, '射击');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return damage;
|
||||
}
|
||||
);
|
||||
|
||||
// --------------- 光环处理
|
||||
}
|
||||
};
|
||||
|
@ -149,7 +149,6 @@ body {
|
||||
position: absolute;
|
||||
text-align: center;
|
||||
font-size: 1.4em;
|
||||
font-family: 'normal';
|
||||
display: none;
|
||||
z-index: 310;
|
||||
bottom: 0;
|
||||
@ -450,6 +449,7 @@ p#name {
|
||||
background: white;
|
||||
width: 250px;
|
||||
min-height: 50px;
|
||||
color: #000d;
|
||||
}
|
||||
|
||||
#inputMessage {
|
||||
|
@ -48,7 +48,7 @@ function show(index: number) {
|
||||
position: fixed;
|
||||
overflow: visible;
|
||||
display: block;
|
||||
font-family: 'normal';
|
||||
font-size: 80%;
|
||||
}
|
||||
|
||||
#ui-main {
|
||||
|
@ -43,7 +43,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, onUnmounted, onUpdated, ref, useSlots, watch } from 'vue';
|
||||
import { onMounted, onUnmounted, onUpdated, ref, watch } from 'vue';
|
||||
import { DragOutlined } from '@ant-design/icons-vue';
|
||||
import { isMobile, useDrag, cancelGlobalDrag } from '../plugin/use';
|
||||
import { has } from '../plugin/utils';
|
||||
@ -89,6 +89,8 @@ watch(width, n => emits('update:width', n));
|
||||
watch(height, n => emits('update:height', n));
|
||||
|
||||
async function click() {
|
||||
console.log(1);
|
||||
|
||||
moveSelected.value = true;
|
||||
moveTimeout = window.setTimeout(() => {
|
||||
moveSelected.value = false;
|
||||
@ -231,7 +233,6 @@ onUnmounted(() => {
|
||||
top: 50px;
|
||||
display: flex;
|
||||
overflow: visible;
|
||||
font-family: 'normal';
|
||||
}
|
||||
|
||||
.box-main {
|
||||
|
@ -70,7 +70,6 @@ onUpdated(resize);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
font-family: 'normal';
|
||||
font-size: 150%;
|
||||
user-select: none;
|
||||
}
|
||||
@ -111,7 +110,6 @@ onUpdated(resize);
|
||||
|
||||
.tools {
|
||||
width: 100%;
|
||||
font-family: 'normal';
|
||||
font-size: 3.2vh;
|
||||
height: 5vh;
|
||||
position: fixed;
|
||||
|
@ -8,14 +8,9 @@ mainUi.register(
|
||||
new GameUi('toolbox', UI.Toolbox),
|
||||
new GameUi('equipbox', UI.Equipbox),
|
||||
new GameUi('settings', UI.Settings),
|
||||
new GameUi('desc', UI.Desc),
|
||||
new GameUi('skill', UI.Skill),
|
||||
new GameUi('skillTree', UI.SkillTree),
|
||||
new GameUi('fly', UI.Fly),
|
||||
new GameUi('fixedDetail', UI.FixedDetail),
|
||||
new GameUi('shop', UI.Shop),
|
||||
new GameUi('achievement', UI.Achievement),
|
||||
new GameUi('bgm', UI.BgmList),
|
||||
new GameUi('hotkey', UI.Hotkey),
|
||||
new GameUi('toolEditor', UI.ToolEditor),
|
||||
new GameUi('virtualKey', MiscUI.VirtualKey)
|
||||
@ -29,7 +24,6 @@ fixedUi.register(
|
||||
new GameUi('markedEnemy', UI.Marked),
|
||||
new GameUi('fixed', UI.Fixed),
|
||||
new GameUi('chapter', UI.Chapter),
|
||||
new GameUi('completeAchi', UI.CompleteAchi),
|
||||
new GameUi('start', UI.Start),
|
||||
new GameUi('toolbar', UI.Toolbar)
|
||||
);
|
||||
|
@ -456,9 +456,7 @@ const loading = Mota.require('var', 'loading');
|
||||
loading.once('coreInit', () => {
|
||||
mainSetting.reset({
|
||||
'screen.fullscreen': !!document.fullscreenElement,
|
||||
'screen.halo': !!storage.getValue('screen.showHalo', true),
|
||||
'screen.itemDetail': !!storage.getValue('screen.itemDetail', true),
|
||||
'screen.heroDetail': !!storage.getValue('screen.heroDetail', false),
|
||||
'screen.transition': !!storage.getValue('screen.transition', false),
|
||||
'screen.antiAlias': !!storage.getValue('screen.antiAlias', false),
|
||||
'screen.fontSize': storage.getValue('screen.fontSize', 16),
|
||||
@ -469,9 +467,7 @@ loading.once('coreInit', () => {
|
||||
'audio.bgmVolume': storage.getValue('audio.bgmVolume', 80),
|
||||
'audio.soundEnabled': !!storage.getValue('audio.soundEnabled', true),
|
||||
'audio.soundVolume': storage.getValue('audio.soundVolume', 80),
|
||||
'utils.betterLoad': !!storage.getValue('utils.betterLoad', true),
|
||||
'utils.autoScale': !!storage.getValue('utils.autoScale', true),
|
||||
'fx.paraLight': !!storage.getValue('fx.paraLight', true),
|
||||
'fx.frag': !!storage.getValue('fx.frag', true),
|
||||
'ui.mapScale': storage.getValue(
|
||||
'ui.mapScale',
|
||||
@ -480,13 +476,6 @@ loading.once('coreInit', () => {
|
||||
});
|
||||
});
|
||||
|
||||
const { hook } = Mota.requireAll('var');
|
||||
hook.on('reset', () => {
|
||||
mainSetting.reset({
|
||||
'action.autoSkill': flags.autoSkill ?? true
|
||||
});
|
||||
});
|
||||
|
||||
interface SettingTextData {
|
||||
[x: string]: string[] | SettingTextData;
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { DamageEnemy, ensureFloorDamage, getSingleEnemy } from './damage';
|
||||
import { DamageEnemy, Damage } from './damage';
|
||||
import { findDir, has } from '../../plugin/game/utils';
|
||||
import { loading } from '../game';
|
||||
|
||||
@ -31,6 +31,7 @@ function init() {
|
||||
) {
|
||||
const enemy = getEnemy(x, y, floorId);
|
||||
const { damage } = enemy.calDamage();
|
||||
|
||||
return damage < core.status.hero.hp;
|
||||
};
|
||||
|
||||
@ -173,7 +174,7 @@ function init() {
|
||||
floorId = floorId || core.status.floorId;
|
||||
const enemys: CurrentEnemy[] = [];
|
||||
const used: Record<string, DamageEnemy[]> = {};
|
||||
ensureFloorDamage(floorId);
|
||||
Damage.ensureFloorDamage(floorId);
|
||||
const floor = core.status.maps[floorId];
|
||||
floor.enemy.list.forEach(v => {
|
||||
if (!(v.id in used)) {
|
||||
@ -229,7 +230,7 @@ function init() {
|
||||
|
||||
core.events._action_battle = function (data, x, y, prefix) {
|
||||
if (data.id) {
|
||||
const enemy = getSingleEnemy(data.id as EnemyIds);
|
||||
const enemy = Damage.getSingleEnemy(data.id as EnemyIds);
|
||||
// todo: 与不在地图上的怪物战斗
|
||||
} else {
|
||||
if (data.floorId != core.status.floorId) {
|
||||
|
@ -134,7 +134,7 @@ export class EnemyCollection implements RangeCollection<DamageEnemy> {
|
||||
*/
|
||||
calMapDamage() {
|
||||
this.mapDamage = {};
|
||||
const hero = getHeroStatusOn(realStatus, this.floorId);
|
||||
const hero = getHeroStatusOn(Damage.realStatus, this.floorId);
|
||||
this.list.forEach(v => {
|
||||
v.calMapDamage(this.mapDamage, hero);
|
||||
});
|
||||
@ -264,23 +264,6 @@ export class EnemyCollection implements RangeCollection<DamageEnemy> {
|
||||
alpha: 1
|
||||
});
|
||||
}
|
||||
|
||||
// 电摇嘲讽
|
||||
if (dam.mockery) {
|
||||
dam.mockery.sort((a, b) =>
|
||||
a[0] === b[0] ? a[1] - b[1] : a[0] - b[0]
|
||||
);
|
||||
const [tx, ty] = dam.mockery[0];
|
||||
const dir =
|
||||
x > tx ? '←' : x < tx ? '→' : y > ty ? '↑' : '↓';
|
||||
core.status.damage.extraData.push({
|
||||
text: '嘲' + dir,
|
||||
px: 32 * x + 16,
|
||||
py: 32 * (y + 1) - 14,
|
||||
color: '#fd4',
|
||||
alpha: 1
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -522,7 +505,7 @@ export class DamageEnemy<T extends EnemyIds = EnemyIds> {
|
||||
*/
|
||||
calMapDamage(
|
||||
damage: Record<string, MapDamage> = {},
|
||||
hero: Partial<HeroStatus> = getHeroStatusOn(realStatus)
|
||||
hero: Partial<HeroStatus> = getHeroStatusOn(Damage.realStatus)
|
||||
) {
|
||||
if (!has(this.x) || !has(this.y) || !has(this.floorId)) return damage;
|
||||
const enemy = this.enemy;
|
||||
@ -583,33 +566,10 @@ export class DamageEnemy<T extends EnemyIds = EnemyIds> {
|
||||
}
|
||||
}
|
||||
|
||||
// 电摇嘲讽
|
||||
if (this.info.special.includes(19)) {
|
||||
const objs = core.getMapBlocksObj(this.floorId);
|
||||
for (let nx = 0; nx < w; nx++) {
|
||||
const loc = `${nx},${this.y}` as LocString;
|
||||
const block = objs[loc];
|
||||
if (!block?.event.noPass) {
|
||||
damage[loc] ??= { damage: 0, type: new Set() };
|
||||
damage[loc].mockery ??= [];
|
||||
damage[loc].mockery!.push([this.x, this.y]);
|
||||
}
|
||||
}
|
||||
for (let ny = 0; ny < h; ny++) {
|
||||
const loc = `${this.x},${ny}` as LocString;
|
||||
const block = objs[loc];
|
||||
if (!block?.event.noPass) {
|
||||
damage[loc] ??= { damage: 0, type: new Set() };
|
||||
damage[loc].mockery ??= [];
|
||||
damage[loc].mockery!.push([this.x, this.y]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return damage;
|
||||
}
|
||||
|
||||
private setMapDamage(
|
||||
setMapDamage(
|
||||
damage: Record<string, MapDamage>,
|
||||
loc: string,
|
||||
dam: number,
|
||||
@ -621,8 +581,8 @@ export class DamageEnemy<T extends EnemyIds = EnemyIds> {
|
||||
}
|
||||
|
||||
private calEnemyDamageOf(hero: Partial<HeroStatus>, enemy: EnemyInfo) {
|
||||
const status = getHeroStatusOf(hero, realStatus, this.floorId);
|
||||
let damage = calDamageWith(enemy, status) ?? Infinity;
|
||||
const status = getHeroStatusOf(hero, Damage.realStatus, this.floorId);
|
||||
let damage = Damage.calDamageWith(enemy, status) ?? Infinity;
|
||||
let skill = -1;
|
||||
|
||||
// 自动切换技能
|
||||
@ -631,9 +591,9 @@ export class DamageEnemy<T extends EnemyIds = EnemyIds> {
|
||||
const [unlock, condition] = skills[i];
|
||||
if (!flags[unlock]) continue;
|
||||
flags[condition] = true;
|
||||
const status = getHeroStatusOf(hero, realStatus);
|
||||
const status = getHeroStatusOf(hero, Damage.realStatus);
|
||||
|
||||
const d = calDamageWith(enemy, status) ?? Infinity;
|
||||
const d = Damage.calDamageWith(enemy, status) ?? Infinity;
|
||||
|
||||
if (d < damage) {
|
||||
damage = d;
|
||||
@ -818,10 +778,6 @@ export class DamageEnemy<T extends EnemyIds = EnemyIds> {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算伤害时会用到的勇士属性,攻击防御,其余的不会有buff加成,直接从core.status.hero取
|
||||
*/
|
||||
const realStatus: (keyof HeroStatus)[] = ['atk', 'def'];
|
||||
/**
|
||||
* 主动技能列表
|
||||
*/
|
||||
@ -830,129 +786,129 @@ const skills: [unlock: string, condition: string][] = [
|
||||
['shieldOn', 'shield']
|
||||
];
|
||||
|
||||
/**
|
||||
* 计算怪物伤害
|
||||
* @param info 怪物信息
|
||||
* @param hero 勇士信息
|
||||
*/
|
||||
export function calDamageWith(
|
||||
info: EnemyInfo,
|
||||
hero: Partial<HeroStatus>
|
||||
): number | null {
|
||||
const { hp, hpmax, mana, mdef } = core.status.hero;
|
||||
let { atk, def } = hero as HeroStatus;
|
||||
let { hp: monHp, atk: monAtk, def: monDef, special, enemy } = info;
|
||||
export namespace Damage {
|
||||
/**
|
||||
* 计算伤害时会用到的勇士属性,攻击防御,其余的不会有buff加成,直接从core.status.hero取
|
||||
*/
|
||||
export let realStatus: (keyof HeroStatus)[] = ['atk', 'def'];
|
||||
|
||||
let damage = 0;
|
||||
/**
|
||||
* 计算怪物伤害
|
||||
* @param info 怪物信息
|
||||
* @param hero 勇士信息
|
||||
*/
|
||||
export function calDamageWith(
|
||||
info: EnemyInfo,
|
||||
hero: Partial<HeroStatus>
|
||||
): number | null {
|
||||
const { hp, hpmax, mana, mdef } = core.status.hero;
|
||||
let { atk, def } = hero as HeroStatus;
|
||||
let { hp: monHp, atk: monAtk, def: monDef, special, enemy } = info;
|
||||
|
||||
// 饥渴
|
||||
if (special.includes(7)) {
|
||||
const delta = Math.floor((atk * enemy.hungry!) / 100);
|
||||
atk -= delta;
|
||||
monAtk += delta;
|
||||
let damage = 0;
|
||||
|
||||
// 饥渴
|
||||
if (special.includes(7)) {
|
||||
const delta = Math.floor((atk * enemy.hungry!) / 100);
|
||||
atk -= delta;
|
||||
monAtk += delta;
|
||||
}
|
||||
|
||||
let heroPerDamage: number;
|
||||
|
||||
// 绝对防御
|
||||
if (special.includes(9)) {
|
||||
heroPerDamage = atk + mana - monDef;
|
||||
if (heroPerDamage <= 0) return null;
|
||||
} else if (special.includes(3)) {
|
||||
// 由于坚固的特性,只能放到这来计算了
|
||||
if (atk > enemy.def) heroPerDamage = 1 + mana;
|
||||
else return null;
|
||||
} else {
|
||||
heroPerDamage = atk - monDef;
|
||||
if (heroPerDamage > 0) heroPerDamage += mana;
|
||||
else return null;
|
||||
}
|
||||
|
||||
// 霜冻
|
||||
if (special.includes(20) && !core.hasEquip('I589')) {
|
||||
heroPerDamage *= 1 - enemy.ice! / 100;
|
||||
}
|
||||
|
||||
heroPerDamage *= 1 - info.damageDecline / 100;
|
||||
|
||||
let enemyPerDamage: number;
|
||||
|
||||
// 魔攻
|
||||
if (special.includes(2) || special.includes(13)) {
|
||||
enemyPerDamage = monAtk;
|
||||
} else {
|
||||
enemyPerDamage = monAtk - def;
|
||||
if (enemyPerDamage < 0) enemyPerDamage = 0;
|
||||
}
|
||||
|
||||
// 先攻
|
||||
if (special.includes(17)) {
|
||||
damage += enemyPerDamage;
|
||||
}
|
||||
|
||||
// 连击
|
||||
if (special.includes(4)) enemyPerDamage *= 2;
|
||||
if (special.includes(5)) enemyPerDamage *= 3;
|
||||
if (special.includes(6)) enemyPerDamage *= enemy.n!;
|
||||
|
||||
// 苍蓝刻
|
||||
if (special.includes(28)) {
|
||||
heroPerDamage *= 1 - enemy.paleShield! / 100;
|
||||
}
|
||||
|
||||
let turn = Math.ceil(monHp / heroPerDamage);
|
||||
|
||||
// 致命一击
|
||||
if (special.includes(1)) {
|
||||
const times = Math.floor(turn / 5);
|
||||
damage += ((times * (enemy.crit! - 100)) / 100) * enemyPerDamage;
|
||||
}
|
||||
|
||||
// 勇气之刃
|
||||
if (turn > 1 && special.includes(10)) {
|
||||
damage += (enemy.courage! / 100 - 1) * enemyPerDamage;
|
||||
}
|
||||
|
||||
// 勇气冲锋
|
||||
if (special.includes(11)) {
|
||||
damage += (enemy.charge! / 100) * enemyPerDamage;
|
||||
turn += 5;
|
||||
}
|
||||
|
||||
damage += (turn - 1) * enemyPerDamage;
|
||||
// 无上之盾
|
||||
if (flags.superSheild) {
|
||||
damage -= mdef / 10;
|
||||
}
|
||||
// 生命回复
|
||||
damage -= hpmax * turn;
|
||||
if (flags.hard === 1) damage *= 0.9;
|
||||
|
||||
return damage;
|
||||
}
|
||||
|
||||
let heroPerDamage: number;
|
||||
|
||||
// 绝对防御
|
||||
if (special.includes(9)) {
|
||||
heroPerDamage = atk + mana - monDef;
|
||||
if (heroPerDamage <= 0) return null;
|
||||
} else if (special.includes(3)) {
|
||||
// 由于坚固的特性,只能放到这来计算了
|
||||
if (atk > enemy.def) heroPerDamage = 1 + mana;
|
||||
else return null;
|
||||
} else {
|
||||
heroPerDamage = atk - monDef;
|
||||
if (heroPerDamage > 0) heroPerDamage += mana;
|
||||
else return null;
|
||||
export function ensureFloorDamage(floorId: FloorIds) {
|
||||
const floor = core.status.maps[floorId];
|
||||
floor.enemy ??= new EnemyCollection(floorId);
|
||||
}
|
||||
|
||||
// 霜冻
|
||||
if (special.includes(20) && !core.hasEquip('I589')) {
|
||||
heroPerDamage *= 1 - enemy.ice! / 100;
|
||||
export function getSingleEnemy(id: EnemyIds) {
|
||||
const e = core.material.enemys[id];
|
||||
const enemy = new DamageEnemy(e);
|
||||
enemy.calAttribute();
|
||||
enemy.getRealInfo();
|
||||
enemy.calDamage(core.status.hero);
|
||||
return enemy;
|
||||
}
|
||||
|
||||
heroPerDamage *= 1 - info.damageDecline / 100;
|
||||
|
||||
let enemyPerDamage: number;
|
||||
|
||||
// 魔攻
|
||||
if (special.includes(2) || special.includes(13)) {
|
||||
enemyPerDamage = monAtk;
|
||||
} else {
|
||||
enemyPerDamage = monAtk - def;
|
||||
if (enemyPerDamage < 0) enemyPerDamage = 0;
|
||||
}
|
||||
|
||||
// 先攻
|
||||
if (special.includes(17)) {
|
||||
damage += enemyPerDamage;
|
||||
}
|
||||
|
||||
// 连击
|
||||
if (special.includes(4)) enemyPerDamage *= 2;
|
||||
if (special.includes(5)) enemyPerDamage *= 3;
|
||||
if (special.includes(6)) enemyPerDamage *= enemy.n!;
|
||||
|
||||
// 苍蓝刻
|
||||
if (special.includes(28)) {
|
||||
heroPerDamage *= 1 - enemy.paleShield! / 100;
|
||||
}
|
||||
|
||||
let turn = Math.ceil(monHp / heroPerDamage);
|
||||
|
||||
// 致命一击
|
||||
if (special.includes(1)) {
|
||||
const times = Math.floor(turn / 5);
|
||||
damage += ((times * (enemy.crit! - 100)) / 100) * enemyPerDamage;
|
||||
}
|
||||
|
||||
// 勇气之刃
|
||||
if (turn > 1 && special.includes(10)) {
|
||||
damage += (enemy.courage! / 100 - 1) * enemyPerDamage;
|
||||
}
|
||||
|
||||
// 勇气冲锋
|
||||
if (special.includes(11)) {
|
||||
damage += (enemy.charge! / 100) * enemyPerDamage;
|
||||
turn += 5;
|
||||
}
|
||||
|
||||
damage += (turn - 1) * enemyPerDamage;
|
||||
// 无上之盾
|
||||
if (flags.superSheild) {
|
||||
damage -= mdef / 10;
|
||||
}
|
||||
// 生命回复
|
||||
damage -= hpmax * turn;
|
||||
if (flags.hard === 1) damage *= 0.9;
|
||||
|
||||
return damage;
|
||||
}
|
||||
|
||||
export function ensureFloorDamage(floorId: FloorIds) {
|
||||
const floor = core.status.maps[floorId];
|
||||
floor.enemy ??= new EnemyCollection(floorId);
|
||||
}
|
||||
|
||||
export function getSingleEnemy(id: EnemyIds) {
|
||||
const e = core.material.enemys[id];
|
||||
const enemy = new DamageEnemy(e);
|
||||
enemy.calAttribute();
|
||||
enemy.getRealInfo();
|
||||
enemy.calDamage(core.status.hero);
|
||||
return enemy;
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface PluginDeclaration {
|
||||
damage: {
|
||||
Enemy: typeof DamageEnemy;
|
||||
Collection: typeof EnemyCollection;
|
||||
};
|
||||
}
|
||||
|
||||
interface Floor {
|
||||
enemy: EnemyCollection;
|
||||
}
|
||||
|
@ -138,7 +138,12 @@ class GameListener extends EventEmitter<ListenerEvent> {
|
||||
|
||||
// hover & leave & mouseMove
|
||||
data.addEventListener('mousemove', e => {
|
||||
if (core.status.lockControl || !core.isPlaying()) return;
|
||||
if (
|
||||
core.status.lockControl ||
|
||||
!core.isPlaying() ||
|
||||
!core.status.floorId
|
||||
)
|
||||
return;
|
||||
this.emit('mouseMove', e);
|
||||
const {
|
||||
x: px,
|
||||
@ -164,7 +169,12 @@ class GameListener extends EventEmitter<ListenerEvent> {
|
||||
}
|
||||
});
|
||||
data.addEventListener('mouseleave', e => {
|
||||
if (core.status.lockControl || !core.isPlaying()) return;
|
||||
if (
|
||||
core.status.lockControl ||
|
||||
!core.isPlaying() ||
|
||||
!core.status.floorId
|
||||
)
|
||||
return;
|
||||
const blocks = core.getMapBlocksObj();
|
||||
const lastBlock = blocks[`${lastHoverX},${lastHoverY}`];
|
||||
if (!!lastBlock) {
|
||||
@ -175,7 +185,12 @@ class GameListener extends EventEmitter<ListenerEvent> {
|
||||
});
|
||||
// click
|
||||
data.addEventListener('click', e => {
|
||||
if (core.status.lockControl || !core.isPlaying()) return;
|
||||
if (
|
||||
core.status.lockControl ||
|
||||
!core.isPlaying() ||
|
||||
!core.status.floorId
|
||||
)
|
||||
return;
|
||||
const {
|
||||
x: px,
|
||||
y: py,
|
||||
|
@ -54,7 +54,6 @@ 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)])
|
||||
@ -74,35 +73,10 @@ function getRealStatus(
|
||||
let s = (status?.[name] ?? core.status.hero[name]) as number;
|
||||
if (s === null || s === void 0) {
|
||||
throw new ReferenceError(
|
||||
`Wrong hero status property name is delivered: ${name}`
|
||||
`Incorrect hero status property name is delivered: ${name}`
|
||||
);
|
||||
}
|
||||
|
||||
// 永夜、极昼
|
||||
if (name === 'atk' || name === 'def') {
|
||||
s += window.flags?.[`night_${floorId}`] ?? 0;
|
||||
}
|
||||
|
||||
// 技能
|
||||
if (flags.bladeOn && flags.blade) {
|
||||
const level = getSkillLevel(2);
|
||||
if (name === 'atk') {
|
||||
s *= 1 + 0.1 * level;
|
||||
}
|
||||
if (name === 'def') {
|
||||
s *= 1 - 0.1 * level;
|
||||
}
|
||||
}
|
||||
if (flags.shield && flags.shieldOn) {
|
||||
const level = getSkillLevel(10);
|
||||
if (name === 'atk') {
|
||||
s *= 1 - 0.1 * level;
|
||||
}
|
||||
if (name === 'def') {
|
||||
s *= 1 + 0.1 * level;
|
||||
}
|
||||
}
|
||||
|
||||
// buff
|
||||
if (typeof s === 'number')
|
||||
s *= core.getBuff(name as keyof NumbericHeroStatus);
|
||||
|
@ -1,6 +1,6 @@
|
||||
import './system';
|
||||
import '../plugin/game/index';
|
||||
import { DamageEnemy, EnemyCollection } from './enemy/damage';
|
||||
import { Damage, DamageEnemy, EnemyCollection } from './enemy/damage';
|
||||
import { EventEmitter, IndexedEventEmitter } from '@/core/common/eventEmitter';
|
||||
import { Range } from '@/plugin/game/range';
|
||||
import { specials } from './enemy/special';
|
||||
@ -24,6 +24,7 @@ Mota.register('var', 'hook', hook);
|
||||
Mota.register('var', 'gameListener', gameListener);
|
||||
Mota.register('var', 'loading', loading);
|
||||
// ----- 模块注册
|
||||
Mota.register('module', 'Damage', Damage);
|
||||
|
||||
main.loading = loading;
|
||||
|
||||
|
@ -46,6 +46,7 @@ import type * as statusBarTools from '@/plugin/ui/statusBar';
|
||||
import type * as toolboxTools from '@/plugin/ui/toolbox';
|
||||
import type * as battle from './enemy/battle';
|
||||
import type * as hero from './hero';
|
||||
import type { Damage } from './enemy/damage';
|
||||
|
||||
interface ClassInterface {
|
||||
// 渲染进程与游戏进程通用
|
||||
@ -124,6 +125,7 @@ interface ModuleInterface {
|
||||
typeof flyTools &
|
||||
typeof statusBarTools &
|
||||
typeof toolboxTools;
|
||||
Damage: typeof Damage;
|
||||
}
|
||||
|
||||
interface SystemInterfaceMap {
|
||||
@ -156,21 +158,14 @@ interface PluginInterface {
|
||||
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 {
|
||||
@ -550,7 +545,7 @@ function rewrite<O, K extends SelectKey<O, _Func>, T = O>(
|
||||
}
|
||||
|
||||
/**
|
||||
* 在渲染进程包裹下执行一段代码,该段代码不会在录像验证中执行,因此里面的内容一定不会引起录像报错
|
||||
* 在渲染进程包裹下执行一段代码,该段代码不会在录像验证及编辑器中执行,因此里面的内容一定不会引起录像报错
|
||||
* 一般特效,或者是ui显示、内容显示、交互监听等内容应当在渲染进程包裹下执行。
|
||||
* 无法获取到执行内容的返回值,因为渲染进程中的值不应当直接出现在游戏进程中,否则很可能导致录像出错,
|
||||
* 如果需要其返回值,应当直接在函数后面新增内容,而不是在游戏进程中使用
|
||||
@ -561,7 +556,7 @@ function r<T = undefined>(
|
||||
fn: (this: T, packages: PackageInterface) => void,
|
||||
thisArg?: T
|
||||
) {
|
||||
if (!main.replayChecking || main.mode === 'editor')
|
||||
if (!main.replayChecking && main.mode === 'play')
|
||||
fn.call(thisArg as T, MPackage.requireAll());
|
||||
}
|
||||
|
||||
|
@ -111,15 +111,6 @@ const def = ref<HTMLCanvasElement>();
|
||||
const enemy = detailInfo.enemy!;
|
||||
const ceil = Math.ceil;
|
||||
|
||||
const x = ref(props.fromBook ? void 0 : flags.mouseLoc[0]);
|
||||
const y = ref(props.fromBook ? void 0 : flags.mouseLoc[1]);
|
||||
x.value = has(x.value)
|
||||
? Math.round(x.value + core.bigmap.offsetX / 32)
|
||||
: void 0;
|
||||
y.value = has(y.value)
|
||||
? Math.round(y.value + core.bigmap.offsetY / 32)
|
||||
: void 0;
|
||||
|
||||
let originCri = getCriticalDamage(enemy, 0, 0);
|
||||
let originDef = getDefDamage(enemy, 0, 0);
|
||||
|
||||
|
@ -28,7 +28,6 @@ export function init() {
|
||||
Mota.rewrite(core.events, 'afterBattle', 'add', (_, enemy, x, y) => {
|
||||
// 打怪特效
|
||||
const setting = Mota.require('var', 'mainSetting');
|
||||
console.log(setting.getValue('fx.frag'));
|
||||
|
||||
if (setting.getValue('fx.frag') && has(x) && has(y)) {
|
||||
const frame = core.status.globalAnimateStatus % 2;
|
||||
|
@ -1,129 +0,0 @@
|
||||
///<reference path="../../../../src/types/core.d.ts" />
|
||||
export {};
|
||||
|
||||
/* @__PURE__ */ (function () {
|
||||
if (main.mode !== 'play' || main.replayChecking) return;
|
||||
|
||||
/**
|
||||
* 热重载css
|
||||
* @param {string} data
|
||||
*/
|
||||
function reloadCss(data) {
|
||||
const css = document.getElementById('mota-css');
|
||||
css.remove();
|
||||
const link = document.createElement('link');
|
||||
link.rel = 'stylesheet';
|
||||
link.type = 'text/css';
|
||||
link.href = data;
|
||||
link.id = 'mota-css';
|
||||
document.head.appendChild(link);
|
||||
console.log(`Css hot reload: ${data}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* 热重载楼层
|
||||
* @param {string} data
|
||||
*/
|
||||
async function reloadFloor(data) {
|
||||
// 如果被砍层了直接忽略
|
||||
if (
|
||||
core.status.maps &&
|
||||
(core.status.maps[data].deleted ||
|
||||
core.status.maps[data].forceDelete)
|
||||
)
|
||||
return;
|
||||
// 首先重新加载main.floors对应的楼层
|
||||
await import(
|
||||
/* @vite-ignore */ `/forceTem/project/floors/${data}.js?v=${Date.now()}`
|
||||
);
|
||||
// 然后写入core.floors并解析
|
||||
core.floors[data] = main.floors[data];
|
||||
const floor = core.loadFloor(data);
|
||||
if (core.isPlaying()) {
|
||||
core.status.maps[data] = floor;
|
||||
delete core.status.mapBlockObjs[data];
|
||||
core.extractBlocks(data);
|
||||
if (data === core.status.floorId) {
|
||||
core.drawMap(data);
|
||||
let weather = core.getFlag('__weather__', null);
|
||||
if (!weather && core.status.thisMap.weather)
|
||||
weather = core.status.thisMap.weather;
|
||||
if (weather) core.setWeather(weather[0], weather[1]);
|
||||
else core.setWeather();
|
||||
}
|
||||
core.updateStatusBar(true, true);
|
||||
}
|
||||
console.log(`Floor hot reload: ${data}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* 属性热重载,包括全塔属性等
|
||||
* @param {string} data
|
||||
*/
|
||||
async function reloadData(data) {
|
||||
const script = document.createElement('script');
|
||||
script.src = `/forceTem/project/${data}.js?v=${Date.now()}`;
|
||||
document.body.appendChild(script);
|
||||
await new Promise(res => {
|
||||
script.onload = () => res('success');
|
||||
});
|
||||
|
||||
let after;
|
||||
if (data === 'data') after = data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d;
|
||||
if (data === 'enemys')
|
||||
after = enemys_fcae963b_31c9_42b4_b48c_bb48d09f3f80;
|
||||
if (data === 'icons')
|
||||
after = icons_4665ee12_3a1f_44a4_bea3_0fccba634dc1;
|
||||
if (data === 'items')
|
||||
after = items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a;
|
||||
if (data === 'maps') after = maps_90f36752_8815_4be8_b32b_d7fad1d0542e;
|
||||
if (data === 'events')
|
||||
after = events_c12a15a8_c380_4b28_8144_256cba95f760;
|
||||
|
||||
if (data === 'enemys') {
|
||||
core.enemys.enemys = after;
|
||||
for (var enemyId in after) {
|
||||
core.enemys.enemys[enemyId].id = enemyId;
|
||||
}
|
||||
core.material.enemys = core.getEnemys();
|
||||
} else if (data === 'icons') {
|
||||
core.icons.icons = after;
|
||||
core.material.icons = core.getIcons();
|
||||
} else if (data === 'items') {
|
||||
core.items.items = after;
|
||||
for (var itemId in after) {
|
||||
core.items.items[itemId].id = itemId;
|
||||
}
|
||||
core.material.items = core.getItems();
|
||||
} else if (data === 'maps') {
|
||||
core.maps.blocksInfo = after;
|
||||
core.status.mapBlockObjs = {};
|
||||
core.status.number2block = {};
|
||||
Object.values(core.status.maps).forEach(v => delete v.blocks);
|
||||
core.extractBlocks();
|
||||
core.setWeather(
|
||||
core.animateFrame.weather.type,
|
||||
core.animateFrame.weather.level
|
||||
);
|
||||
core.drawMap();
|
||||
} else if (data === 'events') {
|
||||
core.events.commonEvent = after.commonEvent;
|
||||
} else if (data === 'data') {
|
||||
location.reload();
|
||||
}
|
||||
core.updateStatusBar(true, true);
|
||||
console.log(`Data hot reload: ${data}`);
|
||||
}
|
||||
|
||||
const ws = new WebSocket('ws://127.0.0.1:3000');
|
||||
ws.addEventListener('open', () => {
|
||||
console.log(`Web socket connect successfully`);
|
||||
});
|
||||
ws.addEventListener('message', e => {
|
||||
const data = JSON.parse(e.data);
|
||||
if (data.type === 'reload') location.reload();
|
||||
if (data.type === 'floorHotReload') reloadFloor(data.floor);
|
||||
if (data.type === 'dataHotReload') reloadData(data.data);
|
||||
if (data.type === 'cssHotReload') reloadCss(data.path);
|
||||
});
|
||||
})();
|
@ -1,5 +1,3 @@
|
||||
import { drawHalo } from '../fx/halo';
|
||||
|
||||
export function init() {
|
||||
// 伤害弹出
|
||||
// 复写阻激夹域检测
|
||||
@ -10,13 +8,13 @@ export function init() {
|
||||
const info = core.status.thisMap.enemy.mapDamage[loc];
|
||||
const damage = info?.damage;
|
||||
if (damage) {
|
||||
if (!main.replayChecking) {
|
||||
Mota.r(() => {
|
||||
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(',') || '伤害';
|
||||
@ -33,190 +31,5 @@ export function init() {
|
||||
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
|
||||
)
|
||||
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();
|
||||
}
|
||||
|
||||
if (callback) return this.moveAction(callback);
|
||||
this._moveHero_moving();
|
||||
};
|
||||
}
|
||||
|
||||
function checkMockery(loc: string, force: boolean = false) {
|
||||
if (core.status.lockControl && !force) return;
|
||||
const mockery = core.status.thisMap.enemy.mapDamage[loc]?.mockery;
|
||||
if (mockery) {
|
||||
mockery.sort((a, b) => (a[0] === b[0] ? a[1] - b[1] : a[0] - b[0]));
|
||||
const action = [];
|
||||
const [tx, ty] = mockery[0];
|
||||
let { x, y } = core.status.hero.loc;
|
||||
const dir = x > tx ? 'left' : x < tx ? 'right' : y > ty ? 'up' : 'down';
|
||||
const { x: dx, y: dy } = core.utils.scan[dir];
|
||||
|
||||
action.push({ type: 'changePos', direction: dir });
|
||||
const blocks = core.getMapBlocksObj();
|
||||
while (1) {
|
||||
x += dx;
|
||||
y += dy;
|
||||
const block = blocks[`${x},${y}`];
|
||||
if (block) {
|
||||
if (
|
||||
[
|
||||
'animates',
|
||||
'autotile',
|
||||
'tileset',
|
||||
'npcs',
|
||||
'npc48',
|
||||
'terrains'
|
||||
].includes(block.event.cls)
|
||||
) {
|
||||
action.push(
|
||||
{
|
||||
type: 'hide',
|
||||
loc: [[x, y]],
|
||||
remove: true,
|
||||
time: 0
|
||||
},
|
||||
{
|
||||
type: 'function',
|
||||
function: `function() { core.removeGlobalAnimate(${x}, ${y}) }`
|
||||
},
|
||||
{
|
||||
type: 'animate',
|
||||
name: 'hand',
|
||||
loc: [x, y],
|
||||
async: true
|
||||
}
|
||||
);
|
||||
}
|
||||
if (block.event.cls.startsWith('enemy')) {
|
||||
action.push({ type: 'moveAction' });
|
||||
}
|
||||
}
|
||||
action.push({ type: 'moveAction' });
|
||||
if (x === tx && y === ty) break;
|
||||
}
|
||||
action.push({
|
||||
type: 'function',
|
||||
function: `function() { core.checkBlock(true); }`
|
||||
});
|
||||
action.push({ type: 'stopAsync' });
|
||||
core.insertAction(action);
|
||||
}
|
||||
}
|
||||
|
@ -1,65 +0,0 @@
|
||||
const haloColor: Record<number, string[]> = {
|
||||
21: ['cyan'],
|
||||
25: ['purple'],
|
||||
26: ['blue'],
|
||||
27: ['red']
|
||||
};
|
||||
|
||||
export function drawHalo(
|
||||
ctx: CanvasRenderingContext2D,
|
||||
onMap: boolean,
|
||||
floorId: FloorIds
|
||||
) {
|
||||
if (main.replayChecking) return;
|
||||
const setting = Mota.require('var', 'mainSetting');
|
||||
if (!setting.getValue('screen.showHalo', true)) return;
|
||||
const list = core.status.maps[floorId].enemy.haloList.concat(
|
||||
Object.keys(flags[`melt_${floorId}`] ?? {}).map(v => {
|
||||
const [x, y] = v.split(',').map(v => parseInt(v));
|
||||
return {
|
||||
type: 'square',
|
||||
data: {
|
||||
x,
|
||||
y,
|
||||
d: 3
|
||||
},
|
||||
special: 25
|
||||
};
|
||||
})
|
||||
);
|
||||
ctx.save();
|
||||
for (const halo of list) {
|
||||
if (halo.type === 'square') {
|
||||
const { x, y, d } = halo.data;
|
||||
const [color, border] = haloColor[halo.special];
|
||||
const r = Math.floor(d / 2);
|
||||
let left = x - r,
|
||||
right = x + r,
|
||||
top = y - r,
|
||||
bottom = y + r;
|
||||
if (onMap && core.bigmap.v2) {
|
||||
left -= core.bigmap.posX;
|
||||
top -= core.bigmap.posY;
|
||||
right -= core.bigmap.posX;
|
||||
bottom -= core.bigmap.posY;
|
||||
if (
|
||||
right < -1 ||
|
||||
left > core._PX_ / 32 + 1 ||
|
||||
top < -1 ||
|
||||
bottom > core._PY_ / 32 + 1
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
ctx.fillStyle = color;
|
||||
ctx.strokeStyle = border ?? color;
|
||||
ctx.lineWidth = 1;
|
||||
ctx.globalAlpha = 0.1;
|
||||
ctx.fillRect(left * 32, top * 32, d * 32, d * 32);
|
||||
ctx.globalAlpha = 0.6;
|
||||
ctx.strokeRect(left * 32, top * 32, d * 32, d * 32);
|
||||
}
|
||||
}
|
||||
|
||||
ctx.restore();
|
||||
}
|
@ -1,6 +1,13 @@
|
||||
import { ensureFloorDamage } from '@/game/enemy/damage';
|
||||
import { Damage } from '@/game/enemy/damage';
|
||||
|
||||
export function init() {
|
||||
const origin = core.control.updateStatusBar;
|
||||
core.updateStatusBar = core.control.updateStatusBar = function () {
|
||||
if (core.getFlag('__statistics__')) return;
|
||||
// @ts-ignore
|
||||
else return origin.apply(core.control, arguments);
|
||||
};
|
||||
|
||||
core.control.updateDamage = function (floorId = core.status.floorId, ctx) {
|
||||
if (!floorId || core.status.gameOver || main.mode !== 'play') return;
|
||||
const onMap = ctx == null;
|
||||
@ -17,7 +24,7 @@ export function init() {
|
||||
if (width * height > core.bigmap.threshold) return;
|
||||
}
|
||||
// 计算伤害
|
||||
ensureFloorDamage(floorId);
|
||||
Damage.ensureFloorDamage(floorId);
|
||||
|
||||
floor.enemy.extract();
|
||||
floor.enemy.calDamage(true);
|
||||
|
@ -1,10 +1,7 @@
|
||||
/* @__PURE__ */ import './dev/hotReload.js'; // 仅开发会用到
|
||||
import * as heroFourFrames from './fx/heroFourFrames';
|
||||
import * as itemDetail from './fx/itemDetail';
|
||||
import * as replay from './replay';
|
||||
import * as ui from './ui';
|
||||
import * as rewrite from './fx/rewrite';
|
||||
import * as halo from './fx/halo';
|
||||
import * as removeMap from './removeMap';
|
||||
import * as shop from './shop';
|
||||
import * as utils from './utils';
|
||||
@ -18,11 +15,8 @@ Mota.Plugin.register('removeMap_g', removeMap);
|
||||
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('halo_g', halo);
|
||||
Mota.Plugin.register('remainEnemy_g', remainEnemy);
|
||||
Mota.Plugin.register('checkBlock_g', checkBlock, checkBlock.init);
|
||||
// todo: 这几个不应该放到插件
|
||||
Mota.Plugin.register('ui_g', ui, ui.init);
|
||||
|
||||
// export {
|
||||
// halo,
|
||||
|
@ -1,75 +1 @@
|
||||
// @ts-nocheck
|
||||
|
||||
export function init() {
|
||||
const { mainUi, fixedUi } = Mota.requireAll('var');
|
||||
|
||||
ui.prototype.drawBook = function () {
|
||||
if (!core.isReplaying()) return mainUi.open('book');
|
||||
};
|
||||
|
||||
ui.prototype._drawToolbox = function () {
|
||||
if (!core.isReplaying()) return mainUi.open('toolbox');
|
||||
};
|
||||
|
||||
ui.prototype._drawEquipbox = function () {
|
||||
if (!core.isReplaying()) return mainUi.open('equipbox');
|
||||
};
|
||||
|
||||
ui.prototype.drawFly = function () {
|
||||
if (!core.isReplaying()) return mainUi.open('fly');
|
||||
};
|
||||
|
||||
control.prototype.updateStatusBar_update = function () {
|
||||
core.control.updateNextFrame = false;
|
||||
if (!core.isPlaying() || core.hasFlag('__statistics__')) return;
|
||||
core.control.controldata.updateStatusBar();
|
||||
if (!core.control.noAutoEvents) core.checkAutoEvents();
|
||||
core.control._updateStatusBar_setToolboxIcon();
|
||||
core.clearRouteFolding();
|
||||
core.control.noAutoEvents = true;
|
||||
// 更新vue状态栏
|
||||
updateVueStatusBar();
|
||||
Mota.require('var', 'hook').emit('statusBarUpdate');
|
||||
};
|
||||
|
||||
// todo: 多个状态栏分离与控制
|
||||
control.prototype.showStatusBar = function () {
|
||||
if (main.mode == 'editor') return;
|
||||
core.removeFlag('hideStatusBar');
|
||||
if (!fixedUi.hasName('statusBar')) {
|
||||
fixedUi.open('statusBar');
|
||||
}
|
||||
core.dom.tools.hard.style.display = 'block';
|
||||
core.dom.toolBar.style.display = 'block';
|
||||
};
|
||||
|
||||
control.prototype.hideStatusBar = function (showToolbox) {
|
||||
if (main.mode == 'editor') return;
|
||||
|
||||
// 如果原本就是隐藏的,则先显示
|
||||
if (!core.domStyle.showStatusBar) this.showStatusBar();
|
||||
if (core.isReplaying()) showToolbox = true;
|
||||
fixedUi.closeByName('statusBar');
|
||||
|
||||
var toolItems = core.dom.tools;
|
||||
core.setFlag('hideStatusBar', true);
|
||||
core.setFlag('showToolbox', showToolbox || null);
|
||||
if (
|
||||
(!core.domStyle.isVertical && !core.flags.extendToolbar) ||
|
||||
!showToolbox
|
||||
) {
|
||||
for (var i = 0; i < toolItems.length; ++i)
|
||||
toolItems[i].style.display = 'none';
|
||||
}
|
||||
if (!core.domStyle.isVertical && !core.flags.extendToolbar) {
|
||||
core.dom.toolBar.style.display = 'none';
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function updateVueStatusBar() {
|
||||
Mota.r(() => {
|
||||
const status = Mota.require('var', 'status');
|
||||
status.value = !status.value;
|
||||
});
|
||||
}
|
||||
|
@ -174,6 +174,7 @@ export function getMapData(
|
||||
const floor = core.floors[now];
|
||||
const change = floor.changeFloor;
|
||||
for (const [loc, ev] of Object.entries(change)) {
|
||||
if (!ev) continue;
|
||||
const target = ev.floorId as FloorIds;
|
||||
if (target.startsWith(':')) continue;
|
||||
const [x, y] = loc.split(',').map(v => parseInt(v));
|
||||
|
@ -66,6 +66,14 @@ export function useDrag(
|
||||
onup && onup(e);
|
||||
};
|
||||
|
||||
const touchUp = (e: TouchEvent) => {
|
||||
const ele = global ? document : e.target;
|
||||
if (ele) {
|
||||
(ele as HTMLElement).removeEventListener('touchmove', touchFn);
|
||||
}
|
||||
onup && onup(e);
|
||||
};
|
||||
|
||||
const md = (e: MouseEvent) => {
|
||||
const ele = global ? document : e.target;
|
||||
if (ele) {
|
||||
@ -93,10 +101,6 @@ export function useDrag(
|
||||
|
||||
const target = global ? document : ele;
|
||||
|
||||
const touchUp = (e: TouchEvent) => {
|
||||
onup && onup(e);
|
||||
};
|
||||
|
||||
if (target instanceof Array) {
|
||||
target.forEach(v => {
|
||||
v.addEventListener('mouseup', mouseUp);
|
||||
|
@ -12,7 +12,6 @@
|
||||
}
|
||||
|
||||
.antdv-message {
|
||||
font-family: 'normal';
|
||||
font-size: 1.6em;
|
||||
}
|
||||
|
||||
|
@ -1,339 +0,0 @@
|
||||
<template>
|
||||
<div id="achievement">
|
||||
<div id="tools">
|
||||
<span id="back" class="button-text tools" @click="exit"
|
||||
><left-outlined />返回游戏</span
|
||||
>
|
||||
</div>
|
||||
<div id="column">
|
||||
<div class="achievement-column" v-for="c of column">
|
||||
<span
|
||||
class="column-text button-text"
|
||||
:active="selectedColumn === c"
|
||||
@click="selectedColumn = c"
|
||||
>{{ columnName[c] }}</span
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<a-divider dashed id="divider"></a-divider>
|
||||
<div id="list">
|
||||
<div id="achievement-list" :style="{ left: `-${offset}%` }">
|
||||
<div v-for="t of column" class="achievement-one">
|
||||
<Scroll class="list-scroll" :width="isMobile ? 10 : 20">
|
||||
<div class="list-div">
|
||||
<div
|
||||
v-for="a of getAllAchievements(t)"
|
||||
class="list-one"
|
||||
>
|
||||
<div
|
||||
class="list-content"
|
||||
:complete="a.complete"
|
||||
>
|
||||
<span class="list-name">{{ a.name }}</span>
|
||||
<span
|
||||
class="list-text"
|
||||
v-html="a.text"
|
||||
></span>
|
||||
<div class="list-end">
|
||||
<div class="end-info">
|
||||
<span
|
||||
class="complete"
|
||||
:complete="a.complete"
|
||||
>完成情况:
|
||||
{{
|
||||
a.complete
|
||||
? '已完成'
|
||||
: '未完成'
|
||||
}}</span
|
||||
>
|
||||
<span class="point"
|
||||
>成就点数: {{ a.point }}</span
|
||||
>
|
||||
</div>
|
||||
<div
|
||||
v-if="a.progress"
|
||||
class="list-progress"
|
||||
>
|
||||
<a-progress
|
||||
:percent="a.percent"
|
||||
:strokeColor="{
|
||||
'0%': '#108ee9',
|
||||
'100%': '#87d068'
|
||||
}"
|
||||
:strokeWidth="height / 150"
|
||||
:format="
|
||||
() =>
|
||||
a.usePercent
|
||||
? `${a.percent}%`
|
||||
: a.progress
|
||||
"
|
||||
></a-progress>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<a-divider id="divider" dashed></a-divider>
|
||||
</div>
|
||||
</div>
|
||||
</Scroll>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="total-progress">
|
||||
<a-progress
|
||||
id="point-progress"
|
||||
:percent="(nowPoint / totalPoint) * 100"
|
||||
:strokeColor="{
|
||||
'0%': '#108ee9',
|
||||
'100%': '#87d068'
|
||||
}"
|
||||
:strokeWidth="height / 150"
|
||||
:showInfo="false"
|
||||
></a-progress>
|
||||
<span id="point-number"
|
||||
>成就点: {{ nowPoint }} / {{ totalPoint }}</span
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, ref } from 'vue';
|
||||
import { LeftOutlined } from '@ant-design/icons-vue';
|
||||
import list from '../data/achievement.json';
|
||||
import {
|
||||
Achievement,
|
||||
getNowPoint,
|
||||
hasCompletedAchievement
|
||||
} from '../plugin/ui/achievement';
|
||||
import Scroll from '../components/scroll.vue';
|
||||
import { isMobile } from '../plugin/use';
|
||||
|
||||
const props = defineProps<{
|
||||
num: number;
|
||||
}>();
|
||||
|
||||
type AchievementList = typeof list;
|
||||
type AchievementType = keyof AchievementList;
|
||||
|
||||
interface ResolvedAchievement {
|
||||
name: string;
|
||||
text: string;
|
||||
complete: boolean;
|
||||
point: number;
|
||||
/** number / number */
|
||||
progress?: string;
|
||||
percent?: number;
|
||||
usePercent?: boolean;
|
||||
}
|
||||
|
||||
const column: AchievementType[] = ['normal', 'challenge', 'explore'];
|
||||
const columnName = {
|
||||
normal: '普通成就',
|
||||
challenge: '挑战成就',
|
||||
explore: '探索成就'
|
||||
};
|
||||
|
||||
const selectedColumn = ref<AchievementType>('normal');
|
||||
|
||||
const offset = computed(() => {
|
||||
return column.indexOf(selectedColumn.value) * 100;
|
||||
});
|
||||
|
||||
const height = window.innerHeight;
|
||||
const width = window.innerWidth;
|
||||
|
||||
const totalPoint = Object.values(list)
|
||||
.map((v: Achievement[]) =>
|
||||
v.reduce((prev, curr) => {
|
||||
return curr.point + prev;
|
||||
}, 0)
|
||||
)
|
||||
.reduce((prev, curr) => prev + curr);
|
||||
const nowPoint = getNowPoint();
|
||||
|
||||
/**
|
||||
* 获取一个类型的所有成就
|
||||
* @param type 成就类型
|
||||
*/
|
||||
function getAllAchievements(type: AchievementType): ResolvedAchievement[] {
|
||||
return list[type].map<ResolvedAchievement>((v: Achievement, i) => {
|
||||
const complete = hasCompletedAchievement(type, i);
|
||||
const text = v.hide && !complete ? v.hide : v.text.join('');
|
||||
const res: ResolvedAchievement = {
|
||||
text,
|
||||
name: v.name,
|
||||
point: v.point,
|
||||
complete
|
||||
};
|
||||
if (v.progress) {
|
||||
const p = eval('`' + v.progress + '`') as string;
|
||||
res.progress = p;
|
||||
res.percent = Math.floor(eval(p) * 100);
|
||||
if (v.percent) res.usePercent = true;
|
||||
}
|
||||
return res;
|
||||
});
|
||||
}
|
||||
|
||||
function exit() {
|
||||
Mota.require('var', 'mainUi').close(props.num);
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
#achievement {
|
||||
width: 90vh;
|
||||
height: 90vh;
|
||||
font-family: 'normal';
|
||||
font-size: 150%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
#divider {
|
||||
margin: 1% 0;
|
||||
border-color: #ddd4;
|
||||
}
|
||||
|
||||
#tools {
|
||||
height: 5vh;
|
||||
font-size: 3.2vh;
|
||||
}
|
||||
|
||||
#column {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-around;
|
||||
margin-top: 3%;
|
||||
font-size: 130%;
|
||||
}
|
||||
|
||||
.list-scroll {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#list {
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
height: max-content;
|
||||
}
|
||||
|
||||
#achievement-list {
|
||||
position: relative;
|
||||
width: 300%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
transition: left 0.4s ease;
|
||||
}
|
||||
|
||||
.achievement-one {
|
||||
width: 90vh;
|
||||
}
|
||||
|
||||
.list-div {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.list-one {
|
||||
width: 70%;
|
||||
|
||||
.list-content {
|
||||
height: 18vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
border: 2px double rgba(132, 132, 132, 0.17);
|
||||
border-radius: 10px;
|
||||
margin: 2% 0 2.5% 0;
|
||||
background-color: rgba(59, 59, 59, 0.281);
|
||||
}
|
||||
|
||||
.list-content[complete='true'] {
|
||||
background-color: rgba(239, 255, 63, 0.205);
|
||||
}
|
||||
|
||||
.list-name {
|
||||
border-bottom: 1px solid #ddd4;
|
||||
}
|
||||
|
||||
.list-text {
|
||||
font-size: 100%;
|
||||
padding: 0 20px;
|
||||
}
|
||||
|
||||
.list-end {
|
||||
width: 90%;
|
||||
height: 95%;
|
||||
display: flex;
|
||||
flex-direction: column-reverse;
|
||||
font-size: 90%;
|
||||
|
||||
.end-info {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
align-items: end;
|
||||
}
|
||||
|
||||
.complete {
|
||||
color: lightcoral;
|
||||
}
|
||||
|
||||
.complete[complete='true'] {
|
||||
color: lightgreen;
|
||||
}
|
||||
}
|
||||
|
||||
.list-progress {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
|
||||
.progress {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#total-progress {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
|
||||
#point-progress {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#point-number {
|
||||
font-size: 70%;
|
||||
margin-left: 2%;
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 600px) {
|
||||
#achievement {
|
||||
width: 90vw;
|
||||
height: 90vh;
|
||||
}
|
||||
|
||||
.list-one {
|
||||
width: 90%;
|
||||
|
||||
.list-content {
|
||||
height: 15vh;
|
||||
}
|
||||
|
||||
.list-end {
|
||||
margin-bottom: 0.8vh;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
@ -1,90 +0,0 @@
|
||||
<template>
|
||||
<Colomn @close="exit" :width="60" :height="80" :left="30" :right="70"
|
||||
><template #left>
|
||||
<div id="bgm-list">
|
||||
<span
|
||||
v-for="(bgm, i) of list"
|
||||
class="selectable"
|
||||
:selected="selected === i"
|
||||
@click="select(i)"
|
||||
>
|
||||
{{ bgm!.area }}
|
||||
</span>
|
||||
</div></template
|
||||
>
|
||||
<template #right
|
||||
><div>
|
||||
<div id="bgm-name">
|
||||
<img id="bgm-image" :src="list[selected]!.img" />
|
||||
<span>{{ name }}</span>
|
||||
<span v-if="list[selected]!.from"
|
||||
>出自 {{
|
||||
list[selected]!.from
|
||||
}}</span
|
||||
>
|
||||
</div>
|
||||
<span v-html="content"></span></div></template
|
||||
></Colomn>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, onMounted, ref } from 'vue';
|
||||
import Colomn from '../components/colomn.vue';
|
||||
import bgm from '../data/bgm.json';
|
||||
import { splitText } from '../plugin/utils';
|
||||
import { mainUi } from '@/core/main/init/ui';
|
||||
|
||||
const props = defineProps<{
|
||||
num: number;
|
||||
}>();
|
||||
|
||||
interface Bgm {
|
||||
img: string;
|
||||
area: string;
|
||||
name: string;
|
||||
desc: string[];
|
||||
from?: string;
|
||||
}
|
||||
|
||||
const list = bgm as Partial<Record<BgmIds, Bgm>>;
|
||||
|
||||
const selected = ref<BgmIds>('title.mp3');
|
||||
|
||||
const content = computed(() => {
|
||||
return eval('`' + splitText(list[selected.value]!.desc) + '`');
|
||||
});
|
||||
const name = computed(() => list[selected.value]!.name);
|
||||
|
||||
function exit() {
|
||||
mainUi.close(props.num);
|
||||
}
|
||||
|
||||
function select(id: BgmIds) {
|
||||
selected.value = id;
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
#bgm-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
#bgm-name {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
#bgm-image {
|
||||
margin-top: 5%;
|
||||
border: 1px solid #fff;
|
||||
width: 33vw;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 600px) {
|
||||
#bgm-image {
|
||||
width: 70vw;
|
||||
}
|
||||
}
|
||||
</style>
|
@ -188,7 +188,6 @@ onUnmounted(() => {
|
||||
user-select: none;
|
||||
width: 80%;
|
||||
height: 100%;
|
||||
font-family: 'normal';
|
||||
overflow: hidden;
|
||||
transition: opacity 0.6s linear;
|
||||
display: flex;
|
||||
@ -208,7 +207,6 @@ onUnmounted(() => {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
font-family: 'normal';
|
||||
}
|
||||
|
||||
.enemy {
|
||||
|
@ -167,12 +167,11 @@ onUnmounted(() => {
|
||||
opacity: 0;
|
||||
position: absolute;
|
||||
left: 14%;
|
||||
font-family: 'normal';
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
width: 72%;
|
||||
height: 90%;
|
||||
height: 100%;
|
||||
transition: all 0.6s ease;
|
||||
user-select: none;
|
||||
}
|
||||
|
@ -141,7 +141,6 @@ onMounted(async () => {
|
||||
|
||||
#chapter-text {
|
||||
position: relative;
|
||||
font-family: 'normal';
|
||||
font-size: 5vh;
|
||||
text-shadow: 0px 0px 5px #fff;
|
||||
}
|
||||
|
@ -1,117 +0,0 @@
|
||||
<template>
|
||||
<Box id="complete-box">
|
||||
<div id="complete">
|
||||
<span>完成成就 {{ achi.name }}</span>
|
||||
<a-progress
|
||||
id="progress"
|
||||
:percent="progress * 100"
|
||||
:strokeColor="{
|
||||
'0%': '#108ee9',
|
||||
'100%': '#87d068'
|
||||
}"
|
||||
:strokeWidth="height / 200"
|
||||
:showInfo="false"
|
||||
></a-progress>
|
||||
<span id="point-number">成就点: {{ now }} / {{ totalPoint }}</span>
|
||||
</div>
|
||||
</Box>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { sleep, Ticker } from 'mutate-animate';
|
||||
import { computed, onMounted, ref } from 'vue';
|
||||
import Box from '../components/box.vue';
|
||||
import list from '../data/achievement.json';
|
||||
import {
|
||||
AchievementType,
|
||||
getNowPoint,
|
||||
totalPoint
|
||||
} from '../plugin/ui/achievement';
|
||||
import { GameUi } from '@/core/main/custom/ui';
|
||||
import { fixedUi } from '@/core/main/init/ui';
|
||||
|
||||
const height = window.innerHeight;
|
||||
|
||||
const props = defineProps<{
|
||||
num: number;
|
||||
ui: GameUi;
|
||||
complete: string;
|
||||
}>();
|
||||
|
||||
const c = props.complete.split(',');
|
||||
const type = c[0] as AchievementType;
|
||||
const index = parseInt(c[1]);
|
||||
|
||||
const achi = list[type][index];
|
||||
const point = achi.point;
|
||||
|
||||
const nowPoint = getNowPoint() - point;
|
||||
const now = ref(nowPoint);
|
||||
const progress = computed(() => now.value / totalPoint);
|
||||
|
||||
onMounted(async () => {
|
||||
await sleep(500);
|
||||
const ticker = new Ticker();
|
||||
const time = Date.now();
|
||||
ticker.add(() => {
|
||||
const nowTime = Date.now();
|
||||
if (nowTime - time > 1000) {
|
||||
now.value = nowPoint + point;
|
||||
ticker.destroy();
|
||||
}
|
||||
const ratio = (nowTime - time) / 1000;
|
||||
now.value = Math.floor(nowPoint + point * ratio);
|
||||
});
|
||||
await sleep(4600);
|
||||
fixedUi.close(props.num);
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
#complete-box {
|
||||
width: 30vw;
|
||||
height: 13vh;
|
||||
left: 35vw;
|
||||
position: fixed;
|
||||
background-color: #000d;
|
||||
animation: ani 5s ease 0s 1 forwards running;
|
||||
z-index: 10000;
|
||||
}
|
||||
|
||||
#complete {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
font-family: 'normal';
|
||||
font-size: 2.2vh;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
#progress {
|
||||
width: 90%;
|
||||
}
|
||||
|
||||
@keyframes ani {
|
||||
0% {
|
||||
top: -30vh;
|
||||
}
|
||||
20% {
|
||||
top: 4vh;
|
||||
}
|
||||
80% {
|
||||
top: 4vh;
|
||||
}
|
||||
100% {
|
||||
top: -30vh;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 600px) {
|
||||
#complete-box {
|
||||
width: 90vw;
|
||||
left: 5%;
|
||||
}
|
||||
}
|
||||
</style>
|
@ -1,79 +0,0 @@
|
||||
<template>
|
||||
<Colomn @close="exit" :width="80" :height="80" :left="30" :right="70"
|
||||
><template #left
|
||||
><div id="desc-list">
|
||||
<div
|
||||
v-for="(data, k) in desc"
|
||||
class="selectable desc-item"
|
||||
:selected="selected === k"
|
||||
:show="show(data.condition)"
|
||||
@click="click(k)"
|
||||
>
|
||||
<span v-if="show(data.condition)">{{ data.text }}</span>
|
||||
</div>
|
||||
</div></template
|
||||
>
|
||||
<template #right><span v-html="content"></span></template
|
||||
></Colomn>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, onUnmounted, ref } from 'vue';
|
||||
import desc from '../data/desc.json';
|
||||
import { splitText } from '../plugin/utils';
|
||||
import Colomn from '../components/colomn.vue';
|
||||
import { GameUi } from '@/core/main/custom/ui';
|
||||
import { gameKey } from '@/core/main/init/hotkey';
|
||||
import { mainUi } from '@/core/main/init/ui';
|
||||
|
||||
const props = defineProps<{
|
||||
num: number;
|
||||
ui: GameUi;
|
||||
}>();
|
||||
|
||||
type DescKey = keyof typeof desc;
|
||||
|
||||
const selected = ref(Object.keys(desc)[0] as DescKey);
|
||||
|
||||
function exit() {
|
||||
mainUi.close(props.num);
|
||||
}
|
||||
|
||||
const content = computed(() => {
|
||||
return eval('`' + splitText(desc[selected.value].desc) + '`');
|
||||
});
|
||||
|
||||
function click(key: DescKey) {
|
||||
if (!eval(desc[key].condition)) return;
|
||||
selected.value = key;
|
||||
}
|
||||
|
||||
function show(condition: string) {
|
||||
return eval(condition);
|
||||
}
|
||||
|
||||
gameKey.use(props.ui.symbol);
|
||||
gameKey
|
||||
.realize('exit', () => {
|
||||
exit();
|
||||
})
|
||||
.realize('desc', () => {
|
||||
exit();
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
gameKey.dispose(props.ui.symbol);
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
#desc-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.desc-item[show='false'] {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
</style>
|
@ -484,8 +484,6 @@ onUnmounted(() => {
|
||||
font-size: 3.2vh;
|
||||
height: 5vh;
|
||||
justify-content: space-between;
|
||||
font-family: 'normal';
|
||||
|
||||
.tools {
|
||||
white-space: nowrap;
|
||||
}
|
||||
@ -496,7 +494,6 @@ onUnmounted(() => {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
font-family: 'normal';
|
||||
font-size: 150%;
|
||||
}
|
||||
|
||||
@ -518,7 +515,6 @@ onUnmounted(() => {
|
||||
|
||||
.select {
|
||||
width: 100%;
|
||||
font-family: 'normal';
|
||||
font-size: 75%;
|
||||
}
|
||||
|
||||
|
@ -135,7 +135,6 @@ onMounted(() => {
|
||||
|
||||
<style lang="less" scoped>
|
||||
#fixed {
|
||||
font-family: 'normal';
|
||||
font-size: 2.5vh;
|
||||
opacity: 0;
|
||||
transition: opacity 0.2s linear;
|
||||
|
@ -659,7 +659,6 @@ onUnmounted(() => {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
font-size: 150%;
|
||||
font-family: 'normal';
|
||||
display: flex;
|
||||
align-items: center;
|
||||
user-select: none;
|
||||
@ -667,7 +666,6 @@ onUnmounted(() => {
|
||||
|
||||
#tools {
|
||||
width: 100%;
|
||||
font-family: 'normal';
|
||||
font-size: 3.2vh;
|
||||
height: 5vh;
|
||||
position: fixed;
|
||||
|
@ -1,10 +1,6 @@
|
||||
export { default as Achievement } from './achievement.vue';
|
||||
export { default as BgmList } from './bgmList.vue';
|
||||
export { default as Book } from './book.vue';
|
||||
export { default as BookDetail } from './bookDetail.vue';
|
||||
export { default as Chapter } from './chapter.vue';
|
||||
export { default as CompleteAchi } from './completeAchievement.vue';
|
||||
export { default as Desc } from './desc.vue';
|
||||
export { default as Equipbox } from './equipbox.vue';
|
||||
export { default as Fixed } from './fixed.vue';
|
||||
export { default as FixedDetail } from './fixedDetail.vue';
|
||||
@ -12,12 +8,8 @@ export { default as Fly } from './fly.vue';
|
||||
export { default as Marked } from './markedEnemy.vue';
|
||||
export { default as Settings } from './settings.vue';
|
||||
export { default as Shop } from './shop.vue';
|
||||
export { default as Skill } from './skill.vue';
|
||||
export { default as SkillTree } from './skillTree.vue';
|
||||
export { default as Start } from './start.vue';
|
||||
export { default as StatusBar } from './statusBar.vue';
|
||||
export { default as Studied } from './studied.vue';
|
||||
export { default as Study } from './study.vue';
|
||||
export { default as Toolbox } from './toolbox.vue';
|
||||
export { default as Hotkey } from './hotkey.vue';
|
||||
export { default as Toolbar } from './toolbar.vue';
|
||||
|
@ -161,7 +161,6 @@ onUnmounted(() => {
|
||||
<style lang="less" scoped>
|
||||
#tools {
|
||||
width: 100%;
|
||||
font-family: 'normal';
|
||||
font-size: 3.2vh;
|
||||
height: 5vh;
|
||||
position: fixed;
|
||||
|
@ -323,7 +323,6 @@ onUnmounted(() => {
|
||||
#shop {
|
||||
width: 90vh;
|
||||
height: 90vh;
|
||||
font-family: 'normal';
|
||||
font-size: 150%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
@ -1,81 +0,0 @@
|
||||
<template>
|
||||
<Column @close="exit" :width="70" :height="70"
|
||||
><template #left
|
||||
><div id="skill-list">
|
||||
<span
|
||||
v-for="(v, k) in skills"
|
||||
class="selectable skill-item"
|
||||
:selected="k === selected"
|
||||
:selectable="skillOpened(k)"
|
||||
@click="select(k)"
|
||||
>{{ v.text }}</span
|
||||
>
|
||||
</div></template
|
||||
>
|
||||
<template #right><span v-html="content"></span></template
|
||||
></Column>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, ref } from 'vue';
|
||||
import skills from '../data/skill.json';
|
||||
import { has } from '../plugin/utils';
|
||||
import Column from '../components/colomn.vue';
|
||||
import { mainUi } from '@/core/main/init/ui';
|
||||
|
||||
const props = defineProps<{
|
||||
num: number;
|
||||
}>();
|
||||
|
||||
type Skills = keyof typeof skills;
|
||||
|
||||
const selected = ref<Skills>('none');
|
||||
|
||||
function skillOpened(skill: Skills) {
|
||||
return eval(skills[skill].opened) as boolean;
|
||||
}
|
||||
|
||||
function select(skill: Skills) {
|
||||
if (!skillOpened(skill)) return;
|
||||
selected.value = skill;
|
||||
}
|
||||
|
||||
const content = computed(() => {
|
||||
return eval(
|
||||
'`' +
|
||||
skills[selected.value].desc
|
||||
.map((v, i, a) => {
|
||||
if (/^\d+\./.test(v)) return `${' '.repeat(12)}${v}`;
|
||||
else if (
|
||||
(has(a[i - 1]) &&
|
||||
v !== '<br>' &&
|
||||
a[i - 1] === '<br>') ||
|
||||
i === 0
|
||||
) {
|
||||
return `${' '.repeat(8)}${v}`;
|
||||
} else return v;
|
||||
})
|
||||
.join('')
|
||||
.replace(
|
||||
/level:(\d+)/g,
|
||||
'Mota.Plugin.require("skillTree_g").getSkillLevel($1)'
|
||||
) +
|
||||
'`'
|
||||
);
|
||||
});
|
||||
|
||||
function exit() {
|
||||
mainUi.close(props.num);
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
#skill-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.skill-item[selectable='false'] {
|
||||
color: gray;
|
||||
}
|
||||
</style>
|
@ -1,436 +0,0 @@
|
||||
<template>
|
||||
<div id="skill-tree">
|
||||
<div id="tools">
|
||||
<span id="back" class="button-text tools" @click="exit"
|
||||
><left-outlined />返回游戏</span
|
||||
>
|
||||
</div>
|
||||
<span id="skill-title">{{ skill.title }}</span>
|
||||
<a-divider dashed style="border-color: #ddd4" id="divider"></a-divider>
|
||||
<div id="skill-info">
|
||||
<Scroll id="skill-desc" :no-scroll="true">
|
||||
<span v-html="desc"></span>
|
||||
</Scroll>
|
||||
<div id="skill-effect">
|
||||
<span v-if="level > 0" v-html="effect[0]"></span>
|
||||
<span v-if="level < skill.max" v-html="effect[1]"></span>
|
||||
</div>
|
||||
</div>
|
||||
<a-divider
|
||||
dashed
|
||||
style="border-color: #ddd4"
|
||||
id="divider-split"
|
||||
></a-divider>
|
||||
<div id="skill-bottom">
|
||||
<canvas id="skill-canvas"></canvas>
|
||||
<a-divider
|
||||
dashed
|
||||
style="border-color: #ddd4"
|
||||
:type="isMobile ? 'horizontal' : 'vertical'"
|
||||
id="divider-vertical"
|
||||
></a-divider>
|
||||
<div id="skill-upgrade-info">
|
||||
<span id="skill-level"
|
||||
>当前等级:{{ level }} / {{ skill.max }}</span
|
||||
>
|
||||
<a-divider dashed class="upgrade-divider"></a-divider>
|
||||
<span
|
||||
v-if="level < skill.max"
|
||||
id="skill-consume"
|
||||
:style="{ color: consume <= mdef ? '#fff' : '#f44' }"
|
||||
>升级花费:{{ consume }}</span
|
||||
>
|
||||
<span v-else id="skill-consume" style="color: gold"
|
||||
>已满级</span
|
||||
>
|
||||
<a-divider dashed class="upgrade-divider"></a-divider>
|
||||
<Scroll id="front-scroll" :no-scroll="true"
|
||||
><div id="skill-front">
|
||||
<span>前置技能</span>
|
||||
<span
|
||||
v-for="str of front"
|
||||
:style="{
|
||||
color: str.startsWith('a') ? '#fff' : '#f44'
|
||||
}"
|
||||
>{{ str.slice(1) }}</span
|
||||
>
|
||||
</div></Scroll
|
||||
>
|
||||
<a-divider dashed class="upgrade-divider"></a-divider>
|
||||
<div id="skill-chapter">
|
||||
<span class="button-text" @click="selectChapter(-1)"
|
||||
><LeftOutlined
|
||||
/></span>
|
||||
|
||||
<span>{{ chapterDict[chapter] }}</span>
|
||||
|
||||
<span class="button-text" @click="selectChapter(1)"
|
||||
><RightOutlined
|
||||
/></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, onMounted, onUnmounted, ref, watch } from 'vue';
|
||||
import { LeftOutlined, RightOutlined } from '@ant-design/icons-vue';
|
||||
import Scroll from '../components/scroll.vue';
|
||||
import { has, splitText, tip } from '../plugin/utils';
|
||||
import { isMobile } from '../plugin/use';
|
||||
import { sleep } from 'mutate-animate';
|
||||
import { gameKey } from '@/core/main/init/hotkey';
|
||||
import { GameUi } from '@/core/main/custom/ui';
|
||||
import { mainUi } from '@/core/main/init/ui';
|
||||
|
||||
const props = defineProps<{
|
||||
num: number;
|
||||
ui: GameUi;
|
||||
}>();
|
||||
|
||||
const skillTree = Mota.Plugin.require('skillTree_g');
|
||||
|
||||
let canvas: HTMLCanvasElement;
|
||||
let ctx: CanvasRenderingContext2D;
|
||||
|
||||
const selected = ref(0);
|
||||
const chapter = ref<Chapter>('chapter1');
|
||||
const update = ref(false);
|
||||
|
||||
const chapterDict = {
|
||||
chapter1: '第一章',
|
||||
chapter2: '第二章'
|
||||
};
|
||||
|
||||
flags.skillTree ??= 0;
|
||||
|
||||
const s = Mota.Plugin.require('skillTree_g').skills;
|
||||
|
||||
const chapterList = Object.keys(s) as Chapter[];
|
||||
|
||||
selected.value = s[chapterList[flags.skillTree]][0].index;
|
||||
chapter.value = chapterList[flags.skillTree];
|
||||
|
||||
watch(selected, draw);
|
||||
watch(update, () => (mdef.value = core.status.hero.mdef));
|
||||
|
||||
const mdef = ref(core.status.hero.mdef);
|
||||
|
||||
const skill = computed(() => {
|
||||
update.value;
|
||||
return skillTree.getSkillFromIndex(selected.value)!;
|
||||
});
|
||||
|
||||
const skills = computed(() => {
|
||||
return s[chapter.value];
|
||||
});
|
||||
|
||||
const desc = computed(() => {
|
||||
return eval(
|
||||
'`' +
|
||||
splitText(skill.value.desc).replace(/level(:\d+)?/g, (str, $1) => {
|
||||
if ($1) return `skillTree.getSkillLevel(${$1})`;
|
||||
else return `skillTree.getSkillLevel(${skill.value.index})`;
|
||||
}) +
|
||||
'`'
|
||||
);
|
||||
});
|
||||
|
||||
const effect = computed(() => {
|
||||
return [0, 1].map(v => {
|
||||
return eval(
|
||||
'`' +
|
||||
`${v === 0 ? '当前效果:' : '下一级效果:'}` +
|
||||
skill.value.effect
|
||||
.join('')
|
||||
.replace(/level(:\d+)?/g, (str, $1) => {
|
||||
if ($1)
|
||||
return `(skillTree.getSkillLevel(${$1}) + ${v})`;
|
||||
else
|
||||
return `(skillTree.getSkillLevel(${skill.value.index}) + ${v})`;
|
||||
}) +
|
||||
'`'
|
||||
);
|
||||
}) as [string, string];
|
||||
});
|
||||
|
||||
const dict = computed(() => {
|
||||
const dict: Record<number, number> = {};
|
||||
const all = skills.value;
|
||||
all.forEach((v, i) => {
|
||||
dict[v.index] = i;
|
||||
});
|
||||
return dict;
|
||||
});
|
||||
|
||||
const front = computed(() => {
|
||||
return skill.value.front.map(v => {
|
||||
return `${skillTree.getSkillLevel(v[0]) >= v[1] ? 'a' : 'b'}${
|
||||
v[1]
|
||||
}级 ${skills.value[dict.value[v[0]]].title}`;
|
||||
});
|
||||
});
|
||||
|
||||
const consume = computed(() => {
|
||||
update.value;
|
||||
return skillTree.getSkillConsume(selected.value);
|
||||
});
|
||||
|
||||
const level = computed(() => {
|
||||
update.value;
|
||||
return skillTree.getSkillLevel(selected.value);
|
||||
});
|
||||
|
||||
function exit() {
|
||||
mainUi.close(props.num);
|
||||
}
|
||||
|
||||
function resize() {
|
||||
const style = getComputedStyle(canvas);
|
||||
canvas.width = parseFloat(style.width) * devicePixelRatio;
|
||||
canvas.height = parseFloat(style.height) * devicePixelRatio;
|
||||
}
|
||||
|
||||
function draw() {
|
||||
const d = dict.value;
|
||||
const w = canvas.width;
|
||||
const per = w / 11;
|
||||
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||
skills.value.forEach(v => {
|
||||
const [x, y] = v.loc.map(v => v * 2 - 1);
|
||||
// 技能连线
|
||||
v.front.forEach(([skill], i) => {
|
||||
const s = skills.value[d[skill]];
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(x * per + per / 2, y * per + per / 2);
|
||||
ctx.lineTo(
|
||||
...(s.loc.map(v => (v * 2 - 1) * per + per / 2) as LocArr)
|
||||
);
|
||||
if (skillTree.getSkillLevel(s.index) < v.front[i][1])
|
||||
ctx.strokeStyle = '#aaa';
|
||||
else if (skillTree.getSkillLevel(s.index) === s.max)
|
||||
ctx.strokeStyle = '#ff0';
|
||||
else ctx.strokeStyle = '#0f8';
|
||||
ctx.lineWidth = devicePixelRatio;
|
||||
ctx.stroke();
|
||||
});
|
||||
});
|
||||
skills.value.forEach(v => {
|
||||
const [x, y] = v.loc.map(v => v * 2 - 1);
|
||||
const level = skillTree.getSkillLevel(v.index);
|
||||
// 技能图标
|
||||
ctx.save();
|
||||
ctx.lineWidth = per * 0.06;
|
||||
if (selected.value === v.index) {
|
||||
ctx.strokeStyle = '#ff0';
|
||||
ctx.lineWidth *= 2;
|
||||
} else if (level === 0) ctx.strokeStyle = '#888';
|
||||
else if (level === v.max) ctx.strokeStyle = '#F7FF68';
|
||||
else ctx.strokeStyle = '#00FF69';
|
||||
ctx.strokeRect(x * per, y * per, per, per);
|
||||
const img =
|
||||
core.material.images.images[`skill${v.index}.png` as ImageIds];
|
||||
ctx.drawImage(img, x * per, y * per, per, per);
|
||||
if (selected.value === v.index) {
|
||||
ctx.fillStyle = '#ff04';
|
||||
ctx.fillRect(x * per, y * per, per, per);
|
||||
}
|
||||
ctx.restore();
|
||||
});
|
||||
}
|
||||
|
||||
function click(e: MouseEvent) {
|
||||
const px = e.offsetX;
|
||||
const py = e.offsetY;
|
||||
const w = canvas.width / devicePixelRatio;
|
||||
const per = w / 11;
|
||||
const x = Math.floor(px / per);
|
||||
const y = Math.floor(py / per);
|
||||
if (x % 2 !== 1 || y % 2 !== 1) return;
|
||||
const sx = Math.floor(x / 2) + 1;
|
||||
const sy = Math.floor(y / 2) + 1;
|
||||
const skill = skills.value.find(v => v.loc[0] === sx && v.loc[1] === sy);
|
||||
if (!skill) return;
|
||||
if (selected.value !== skill.index) selected.value = skill.index;
|
||||
else {
|
||||
upgrade(skill.index);
|
||||
}
|
||||
}
|
||||
|
||||
function upgrade(index: number) {
|
||||
const success = skillTree.upgradeSkill(index);
|
||||
if (!success) tip('error', '升级失败!');
|
||||
else {
|
||||
tip('success', '升级成功!');
|
||||
update.value = !update.value;
|
||||
core.status.route.push(`skill:${selected.value}`);
|
||||
}
|
||||
}
|
||||
|
||||
gameKey.use(props.ui.symbol);
|
||||
gameKey
|
||||
.realize('exit', () => {
|
||||
exit();
|
||||
})
|
||||
.realize('confirm', () => {
|
||||
upgrade(selected.value);
|
||||
})
|
||||
.realize('skillTree', () => {
|
||||
exit();
|
||||
});
|
||||
|
||||
onMounted(async () => {
|
||||
canvas = document.getElementById('skill-canvas') as HTMLCanvasElement;
|
||||
ctx = canvas.getContext('2d')!;
|
||||
resize();
|
||||
draw();
|
||||
|
||||
await sleep(50);
|
||||
canvas.addEventListener('click', click);
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
gameKey.dispose(props.ui.symbol);
|
||||
});
|
||||
|
||||
function selectChapter(delta: number) {
|
||||
const now = chapterList.indexOf(chapter.value);
|
||||
const to = now + delta;
|
||||
|
||||
if (has(chapterList[to]) && flags.chapter > to) {
|
||||
selected.value = s[chapterList[to]][0].index;
|
||||
chapter.value = chapterList[to];
|
||||
update.value = !update.value;
|
||||
flags.skillTree = to;
|
||||
draw();
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
#skill-tree {
|
||||
width: 90vh;
|
||||
height: 90vh;
|
||||
font-family: 'normal';
|
||||
font-size: 150%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
#skill-title {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
font-size: 130%;
|
||||
height: 5vh;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
#tools {
|
||||
height: 5vh;
|
||||
font-size: 3.2vh;
|
||||
}
|
||||
|
||||
#skill-info {
|
||||
height: 24vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
#divider {
|
||||
width: 100%;
|
||||
margin: 1vh 0;
|
||||
}
|
||||
|
||||
#divider-split {
|
||||
margin: 1vh 0 0 0;
|
||||
}
|
||||
|
||||
#divider-vertical {
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#skill-bottom {
|
||||
height: 53vh;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
#skill-canvas {
|
||||
height: 53vh;
|
||||
width: 53vh;
|
||||
}
|
||||
|
||||
#skill-effect {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
#skill-consume {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
height: 4vh;
|
||||
}
|
||||
|
||||
#skill-upgrade-info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
padding-top: 1vh;
|
||||
}
|
||||
|
||||
.upgrade-divider {
|
||||
margin: 1vh 0;
|
||||
border-color: #ddd4;
|
||||
}
|
||||
|
||||
#front-scroll {
|
||||
width: 100%;
|
||||
height: 39vh;
|
||||
}
|
||||
|
||||
#skill-front {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 600px) {
|
||||
#skill-tree {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
font-size: 100%;
|
||||
padding: 5%;
|
||||
}
|
||||
|
||||
#skill-title {
|
||||
width: 100%;
|
||||
font-size: 130%;
|
||||
height: 5vw;
|
||||
}
|
||||
|
||||
#divider-vertical {
|
||||
height: auto;
|
||||
}
|
||||
|
||||
#skill-bottom {
|
||||
height: auto;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
#skill-canvas {
|
||||
height: 35vh;
|
||||
width: 35vh;
|
||||
}
|
||||
|
||||
#front-scroll {
|
||||
height: 18vh;
|
||||
}
|
||||
}
|
||||
</style>
|
@ -109,7 +109,6 @@ function resize() {
|
||||
|
||||
nextFrame(() => {
|
||||
const scale = core.domStyle.scale;
|
||||
console.log(scale);
|
||||
const h = core._PY_;
|
||||
const height = h * scale;
|
||||
const width = height * 1.5;
|
||||
@ -169,7 +168,6 @@ function bgm() {
|
||||
core.triggerBgm();
|
||||
soundChecked.value = !soundChecked.value;
|
||||
mainSetting.setValue('audio.bgmEnabled', soundChecked.value);
|
||||
console.log(mainSetting.getValue('audio.bgmEnabled'));
|
||||
}
|
||||
|
||||
async function setFullscreen() {
|
||||
|
@ -12,116 +12,164 @@
|
||||
:no-scroll="true"
|
||||
>
|
||||
<div id="status-div">
|
||||
<span
|
||||
id="status-floor"
|
||||
@click.stop="viewMap"
|
||||
class="button-text"
|
||||
>{{ floor }}</span
|
||||
<div
|
||||
v-if="items.includes('enableFloor')"
|
||||
class="status-item"
|
||||
>
|
||||
<span id="status-lv">{{ lvName }}</span>
|
||||
<div id="status-skill" class="status-item">
|
||||
<img
|
||||
src="/project/images/skill.png"
|
||||
class="status-icon"
|
||||
/>
|
||||
<span>{{ skill }}</span>
|
||||
<span
|
||||
v-if="has(spring)"
|
||||
id="status-spring"
|
||||
class="status-extra"
|
||||
>剩余{{ spring }}</span
|
||||
>
|
||||
<span class="status-icon">
|
||||
<img :src="icons.floor.src" />
|
||||
</span>
|
||||
<span class="status-value">{{ floor }}</span>
|
||||
</div>
|
||||
<div id="status-hp" class="status-item">
|
||||
<img src="/project/images/hp.png" class="status-icon" />
|
||||
<span class="status-item-bold">{{
|
||||
format(hero.hp!)
|
||||
}}</span>
|
||||
<span
|
||||
id="status-hpmax"
|
||||
class="status-extra status-item-bold"
|
||||
>+{{ format(hero.hpmax!) }}/t</span
|
||||
>
|
||||
<span
|
||||
v-if="has(jumpCnt)"
|
||||
id="status-jump"
|
||||
class="status-extra"
|
||||
>跳跃剩余{{ jumpCnt }}</span
|
||||
>
|
||||
<div
|
||||
v-if="items.includes('enableName')"
|
||||
class="status-item"
|
||||
>
|
||||
<span class="status-icon">
|
||||
<img v-if="icons.name" :src="icons.icons.src" />
|
||||
</span>
|
||||
<span class="status-value">{{ hero.name }}</span>
|
||||
</div>
|
||||
<div id="status-atk" class="status-item">
|
||||
<img
|
||||
src="/project/images/atk.png"
|
||||
class="status-icon"
|
||||
/>
|
||||
<span class="status-item-bold">{{
|
||||
format(hero.atk!)
|
||||
}}</span>
|
||||
<span
|
||||
id="status-mana"
|
||||
class="status-extra status-item-bold"
|
||||
>+{{ format(hero.mana!) }}</span
|
||||
>
|
||||
<div v-if="items.includes('enableLv')" class="status-item">
|
||||
<span class="status-icon">
|
||||
<img :src="icons.lv.src" />
|
||||
</span>
|
||||
<span class="status-value">{{ lvName }}</span>
|
||||
</div>
|
||||
<div id="status-def" class="status-item status-item-bold">
|
||||
<img
|
||||
src="/project/images/def.png"
|
||||
class="status-icon"
|
||||
/>
|
||||
<span>{{ format(hero.def!) }}</span>
|
||||
</div>
|
||||
<div id="status-mdef" class="status-item status-item-bold">
|
||||
<img src="/project/images/IQ.png" class="status-icon" />
|
||||
<span>{{ format(hero.mdef!) }}</span>
|
||||
</div>
|
||||
<div id="status-money" class="status-item status-item-bold">
|
||||
<img
|
||||
src="/project/images/money.png"
|
||||
class="status-icon"
|
||||
/>
|
||||
<span>{{ format(hero.money!) }}</span>
|
||||
</div>
|
||||
<div id="status-exp" class="status-item status-item-bold">
|
||||
<img
|
||||
src="/project/images/exp.png"
|
||||
class="status-icon"
|
||||
/>
|
||||
<span>{{ format(up) }}</span>
|
||||
</div>
|
||||
<div id="status-key" class="status-item status-item-bold">
|
||||
<span style="color: #fca; padding-left: 10%">{{
|
||||
keys[0]?.toString().padStart(2, '0')
|
||||
}}</span>
|
||||
<span style="color: #aad">{{
|
||||
keys[1]?.toString().padStart(2, '0')
|
||||
}}</span>
|
||||
<span style="color: #f88; padding-right: 10%">{{
|
||||
keys[2]?.toString().padStart(2, '0')
|
||||
<div
|
||||
v-if="items.includes('enableHPMax')"
|
||||
class="status-item"
|
||||
>
|
||||
<span class="status-icon">
|
||||
<img :src="icons.hpmax.src" />
|
||||
</span>
|
||||
<span class="status-value">{{
|
||||
format(hero.hpmax ?? 0)
|
||||
}}</span>
|
||||
</div>
|
||||
<div v-if="skillOpened" class="status-item">
|
||||
<span
|
||||
id="skill-tree"
|
||||
class="button-text"
|
||||
@click.stop="openSkillTree"
|
||||
>技能树</span
|
||||
<div v-if="items.includes('enableHP')" class="status-item">
|
||||
<span class="status-icon">
|
||||
<img :src="icons.hp.src" />
|
||||
</span>
|
||||
<span class="status-value">{{
|
||||
format(hero.hp ?? 0)
|
||||
}}</span>
|
||||
</div>
|
||||
<div
|
||||
v-if="items.includes('enableMana')"
|
||||
class="status-item"
|
||||
>
|
||||
<span class="status-icon">
|
||||
<img :src="icons.mana.src" />
|
||||
</span>
|
||||
<span class="status-value"
|
||||
>{{ format(hero.mana ?? 0) }} /
|
||||
{{ format(hero.manamax ?? 0) }}</span
|
||||
>
|
||||
</div>
|
||||
<div v-if="skillOpened" class="status-item">
|
||||
<div v-if="items.includes('enableAtk')" class="status-item">
|
||||
<span class="status-icon">
|
||||
<img :src="icons.atk.src" />
|
||||
</span>
|
||||
<span class="status-value">{{
|
||||
format(hero.atk ?? 0)
|
||||
}}</span>
|
||||
</div>
|
||||
<div v-if="items.includes('enableDef')" class="status-item">
|
||||
<span class="status-icon">
|
||||
<img :src="icons.def.src" />
|
||||
</span>
|
||||
<span class="status-value">{{
|
||||
format(hero.def ?? 0)
|
||||
}}</span>
|
||||
</div>
|
||||
<div
|
||||
v-if="items.includes('enableMDef')"
|
||||
class="status-item"
|
||||
>
|
||||
<span class="status-icon">
|
||||
<img :src="icons.mdef.src" />
|
||||
</span>
|
||||
<span class="status-value">{{
|
||||
format(hero.mdef ?? 0)
|
||||
}}</span>
|
||||
</div>
|
||||
<div
|
||||
v-if="items.includes('enableMoney')"
|
||||
class="status-item"
|
||||
>
|
||||
<span class="status-icon">
|
||||
<img :src="icons.money.src" />
|
||||
</span>
|
||||
<span class="status-value">{{
|
||||
format(hero.money ?? 0)
|
||||
}}</span>
|
||||
</div>
|
||||
<div
|
||||
v-if="
|
||||
items.includes('enableExp') &&
|
||||
!items.includes('enableLevelUp')
|
||||
"
|
||||
class="status-item"
|
||||
>
|
||||
<span class="status-icon">
|
||||
<img :src="icons.exp.src" />
|
||||
</span>
|
||||
<span class="status-value">{{
|
||||
format(hero.exp ?? 0)
|
||||
}}</span>
|
||||
</div>
|
||||
<div
|
||||
v-if="
|
||||
items.includes('enableExp') &&
|
||||
items.includes('enableLevelUp')
|
||||
"
|
||||
class="status-item"
|
||||
>
|
||||
<span class="status-icon">
|
||||
<img :src="icons.up.src" />
|
||||
</span>
|
||||
<span class="status-value">{{ format(up ?? 0) }}</span>
|
||||
</div>
|
||||
<div
|
||||
v-if="items.includes('enableKeys')"
|
||||
class="status-item"
|
||||
id="status-key"
|
||||
>
|
||||
<span
|
||||
id="status-skill"
|
||||
class="button-text"
|
||||
@click.stop="openSkill"
|
||||
>查看技能</span
|
||||
class="status-value status-key"
|
||||
v-for="(color, i) of keyColor"
|
||||
:color="color"
|
||||
>{{
|
||||
keys[i]?.toString().padStart(2, '0') ?? '00'
|
||||
}}</span
|
||||
>
|
||||
</div>
|
||||
<div v-if="studyOpened" class="status-item">
|
||||
<div
|
||||
v-if="items.includes('enablePZF')"
|
||||
class="status-item status-pzf"
|
||||
>
|
||||
<span
|
||||
id="status-study"
|
||||
class="button-text"
|
||||
@click.stop="openStudy"
|
||||
>学习</span
|
||||
class="status-value status-pzf-value"
|
||||
:index="i"
|
||||
v-for="(name, i) of pzfName"
|
||||
>
|
||||
{{ name }} {{ pzf[i] ?? 0 }}
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
v-if="items.includes('enableDebuff')"
|
||||
class="status-item status-debuff"
|
||||
>
|
||||
<template v-for="(name, i) of debuffName">
|
||||
<span
|
||||
:index="i"
|
||||
class="status-value status-debuff-value"
|
||||
v-if="debuff[i]"
|
||||
>
|
||||
{{ name }}
|
||||
</span>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</Scroll>
|
||||
@ -135,9 +183,9 @@ import Box from '../components/box.vue';
|
||||
import Scroll from '../components/scroll.vue';
|
||||
import { status } from '../plugin/ui/statusBar';
|
||||
import { isMobile } from '../plugin/use';
|
||||
import { has } from '../plugin/utils';
|
||||
|
||||
const skillTree = Mota.Plugin.require('skillTree_g');
|
||||
const items = core.flags.statusBarItems;
|
||||
const icons = core.statusBar.icons;
|
||||
|
||||
const width = ref(
|
||||
isMobile ? window.innerWidth - 60 : window.innerWidth * 0.175
|
||||
@ -151,27 +199,28 @@ watch(height, n => (updateStatus.value = !updateStatus.value));
|
||||
|
||||
const hero = shallowReactive<Partial<HeroStatus>>({});
|
||||
const keys = shallowReactive<number[]>([]);
|
||||
const pzf = shallowReactive<number[]>([]);
|
||||
const debuff = shallowReactive<boolean[]>([]);
|
||||
const floor = ref<string>();
|
||||
const lvName = ref<string>();
|
||||
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(skillTree.getSkillLevel(11) > 0);
|
||||
const jumpCnt = ref<number>();
|
||||
const keyColor = ['yellow', 'blue', 'red'];
|
||||
const pzfName = ['破', '炸', '飞'];
|
||||
const debuffName = ['毒', '衰', '咒'];
|
||||
if (items.includes('enableGreenKey')) keyColor.push('green');
|
||||
/**
|
||||
* 要展示的勇士属性
|
||||
*/
|
||||
const toShow: (keyof NumbericHeroStatus)[] = [
|
||||
'hp', // 生命
|
||||
'atk', // 攻击
|
||||
'def', // 防御
|
||||
'mdef', // 智力
|
||||
'hpmax', // 生命回复
|
||||
'mana', // 额外攻击
|
||||
'money', // 金币
|
||||
'exp', // 经验
|
||||
'lv' // 等级
|
||||
'atk',
|
||||
'def',
|
||||
'mdef',
|
||||
'hpmax',
|
||||
'mana',
|
||||
'money',
|
||||
'exp',
|
||||
'lv',
|
||||
'manamax'
|
||||
];
|
||||
|
||||
watch(status, update);
|
||||
@ -183,53 +232,23 @@ function update() {
|
||||
toShow.forEach(v => {
|
||||
hero[v] = Mota.requireAll('fn').getHeroStatusOn(v);
|
||||
});
|
||||
hero.name = core.status.hero.name;
|
||||
hero.hp = core.status.hero.hp;
|
||||
keys[0] = core.itemCount('yellowKey');
|
||||
keys[1] = core.itemCount('blueKey');
|
||||
keys[2] = core.itemCount('redKey');
|
||||
keys[3] = core.itemCount('greenKey');
|
||||
debuff[0] = core.getFlag('poison');
|
||||
debuff[1] = core.getFlag('weak');
|
||||
debuff[2] = core.getFlag('curse');
|
||||
pzf[0] = core.itemCount('pickaxe');
|
||||
pzf[1] = core.itemCount('bomb');
|
||||
pzf[2] = core.itemCount('centerFly');
|
||||
floor.value = core.status.thisMap?.title;
|
||||
lvName.value = core.getLvName(hero.lv);
|
||||
if (flags.autoSkill) {
|
||||
skill.value = '自动切换';
|
||||
} else {
|
||||
if (flags.blade && flags.bladeOn) {
|
||||
skill.value = '断灭之刃';
|
||||
} else if (flags.shield && flags.shieldOn) {
|
||||
skill.value = '铸剑为盾';
|
||||
} else {
|
||||
skill.value = '无';
|
||||
}
|
||||
}
|
||||
up.value = core.getNextLvUpNeed() ?? 0;
|
||||
if (core.hasFlag('spring')) {
|
||||
spring.value = 50 - (flags.springCount ?? 0);
|
||||
} else {
|
||||
spring.value = void 0;
|
||||
}
|
||||
skillOpened.value = core.getFlag('chapter', 0) > 0;
|
||||
studyOpened.value = skillTree.getSkillLevel(11) > 0;
|
||||
jumpCnt.value =
|
||||
flags.skill2 &&
|
||||
!Mota.Plugin.require('skill_g').jumpIgnoreFloor.includes(
|
||||
core.status.floorId
|
||||
)
|
||||
? 3 - (flags[`jump_${core.status.floorId}`] ?? 0)
|
||||
: void 0;
|
||||
}
|
||||
|
||||
function openSkillTree() {
|
||||
core.useItem('skill1');
|
||||
}
|
||||
|
||||
function openSkill() {
|
||||
core.useItem('cross');
|
||||
}
|
||||
|
||||
function viewMap() {
|
||||
core.ui._drawViewMaps();
|
||||
}
|
||||
|
||||
function openStudy() {}
|
||||
|
||||
onMounted(() => {
|
||||
update();
|
||||
});
|
||||
@ -244,11 +263,12 @@ onMounted(() => {
|
||||
}
|
||||
|
||||
.status-item {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
max-width: 17.5vw;
|
||||
font-size: 200%;
|
||||
font-size: 150%;
|
||||
width: 100%;
|
||||
margin-bottom: 1vh;
|
||||
margin-bottom: 14px;
|
||||
text-shadow: 3px 2px 3px #000, 0px 0px 3px #111;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
@ -260,12 +280,14 @@ onMounted(() => {
|
||||
}
|
||||
|
||||
.status-icon {
|
||||
width: 2.8vw;
|
||||
height: 2.8vw;
|
||||
margin-right: 10%;
|
||||
margin-left: 10%;
|
||||
}
|
||||
|
||||
.status-value {
|
||||
transform: translateY(2px);
|
||||
}
|
||||
|
||||
#status-header {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
@ -280,85 +302,44 @@ onMounted(() => {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#status-floor {
|
||||
max-width: 17.5vw;
|
||||
font-size: 200%;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
text-shadow: 3px 2px 3px #000, 0px 0px 3px #111;
|
||||
}
|
||||
|
||||
#status-lv {
|
||||
max-width: 17.5vw;
|
||||
font-size: 200%;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
text-shadow: 3px 2px 3px #000, 0px 0px 3px #111;
|
||||
}
|
||||
|
||||
.status-extra {
|
||||
position: absolute;
|
||||
right: 10%;
|
||||
bottom: 0;
|
||||
font-size: 75%;
|
||||
}
|
||||
|
||||
#status-mana {
|
||||
line-height: 0;
|
||||
color: rgb(255, 211, 211);
|
||||
}
|
||||
|
||||
#status-hpmax {
|
||||
line-height: 0;
|
||||
color: rgb(167, 255, 167);
|
||||
}
|
||||
|
||||
#status-spring {
|
||||
line-height: 0;
|
||||
color: rgb(167, 255, 167);
|
||||
top: 0;
|
||||
font-size: 75%;
|
||||
}
|
||||
|
||||
#status-jump {
|
||||
line-height: 0;
|
||||
top: 0;
|
||||
font-size: 75%;
|
||||
}
|
||||
|
||||
#status-key {
|
||||
#status-key,
|
||||
.status-pzf,
|
||||
.status-debuff {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-around;
|
||||
}
|
||||
|
||||
#skill-tree,
|
||||
#status-skill {
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
.status-key[color='yellow'] {
|
||||
color: #fca;
|
||||
}
|
||||
.status-key[color='blue'] {
|
||||
color: #aad;
|
||||
}
|
||||
.status-key[color='red'] {
|
||||
color: #f88;
|
||||
}
|
||||
.status-key[color='green'] {
|
||||
color: #8f8;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 600px) {
|
||||
.status-item {
|
||||
max-width: 40vw;
|
||||
font-size: 120%;
|
||||
}
|
||||
.status-pzf-value[index='0'] {
|
||||
color: #bc6e27;
|
||||
}
|
||||
.status-pzf-value[index='1'] {
|
||||
color: #fa14b9;
|
||||
}
|
||||
.status-pzf-value[index='2'] {
|
||||
color: #8db600;
|
||||
}
|
||||
|
||||
#status-floor {
|
||||
max-width: 40vw;
|
||||
font-size: 120%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#status-lv {
|
||||
max-width: 40vw;
|
||||
font-size: 120%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.status-icon {
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
}
|
||||
.status-debuff-value[index='0'] {
|
||||
color: #affca8;
|
||||
}
|
||||
.status-debuff-value[index='1'] {
|
||||
color: #feccd0;
|
||||
}
|
||||
.status-debuff-value[index='2'] {
|
||||
color: #c2f4e7;
|
||||
}
|
||||
</style>
|
||||
|
@ -1,82 +0,0 @@
|
||||
<template>
|
||||
<div id="studied">
|
||||
<Box
|
||||
:resizable="true"
|
||||
:dragable="true"
|
||||
v-model:width="width"
|
||||
v-model:height="height"
|
||||
v-model:left="left"
|
||||
v-model:top="top"
|
||||
>
|
||||
<Scroll :no-scroll="true" style="height: 100%">
|
||||
<div id="studied-main">
|
||||
<div
|
||||
v-for="(num, i) of studied"
|
||||
:key="i"
|
||||
></div></div></Scroll
|
||||
></Box>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, onMounted, onUpdated, reactive, ref, watch } from 'vue';
|
||||
import Box from '../components/box.vue';
|
||||
import { status } from '../plugin/ui/statusBar';
|
||||
import { RightOutlined } from '@ant-design/icons-vue';
|
||||
import Scroll from '../components/scroll.vue';
|
||||
|
||||
watch(status, n => {});
|
||||
|
||||
let main: HTMLDivElement;
|
||||
|
||||
const width = ref(200);
|
||||
const height = ref(0);
|
||||
const left = ref(window.innerWidth - 300);
|
||||
const top = ref(window.innerHeight - 300);
|
||||
|
||||
const folded = reactive<boolean[]>([]);
|
||||
|
||||
const studied = computed(() => {
|
||||
status.value;
|
||||
return core.status.hero.special?.num ?? [];
|
||||
});
|
||||
|
||||
const last = computed(() => {
|
||||
status.value;
|
||||
return core.status.hero.special?.last ?? [];
|
||||
});
|
||||
|
||||
async function calHeight() {
|
||||
await new Promise<void>(resolve => {
|
||||
requestAnimationFrame(() => {
|
||||
const style = getComputedStyle(main);
|
||||
height.value = parseFloat(style.height);
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
onUpdated(() => {
|
||||
calHeight();
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
main = document.getElementById('studied-main') as HTMLDivElement;
|
||||
calHeight();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
#studied {
|
||||
font-family: 'normal';
|
||||
font-size: 1vw;
|
||||
}
|
||||
|
||||
#studied-fold {
|
||||
transition: transform 0.2s ease-out;
|
||||
}
|
||||
|
||||
#studied-fold.folded {
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
</style>
|
@ -1,14 +0,0 @@
|
||||
<template>
|
||||
<div id="study"></div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref } from 'vue';
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
#study {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
@ -303,7 +303,6 @@ onUnmounted(() => {
|
||||
<style lang="less" scoped>
|
||||
#tools {
|
||||
width: 100%;
|
||||
font-family: 'normal';
|
||||
font-size: 3.2vh;
|
||||
height: 5vh;
|
||||
position: fixed;
|
||||
@ -317,7 +316,6 @@ onUnmounted(() => {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
font-family: 'normal';
|
||||
font-size: 150%;
|
||||
user-select: none;
|
||||
align-self: center;
|
||||
|
@ -264,7 +264,6 @@ onUnmounted(() => {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
font-family: 'normal';
|
||||
font-size: 150%;
|
||||
user-select: none;
|
||||
}
|
||||
@ -273,7 +272,6 @@ onUnmounted(() => {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
font-family: 'normal';
|
||||
font-size: 3.2vh;
|
||||
height: 5vh;
|
||||
justify-content: space-between;
|
||||
|
Loading…
Reference in New Issue
Block a user