fix: 报错和部分布局

This commit is contained in:
unanmed 2024-02-04 23:58:14 +08:00
parent f5df2c1416
commit e506a43437
53 changed files with 790 additions and 2477 deletions

View File

@ -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": "状态栏显示项"

View File

@ -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
};
////// 获得勇士原始属性(无装备和衰弱影响) //////

View File

@ -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) {

View File

@ -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) {

View File

@ -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,

View File

@ -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"}},

View File

@ -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",

View File

@ -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为要切换到的楼层IDheroLoc表示勇士切换到的位置
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();
},

View File

@ -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;
}
);
// --------------- 光环处理
}
};

View File

@ -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 {

View File

@ -48,7 +48,7 @@ function show(index: number) {
position: fixed;
overflow: visible;
display: block;
font-family: 'normal';
font-size: 80%;
}
#ui-main {

View File

@ -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 {

View File

@ -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;

View File

@ -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)
);

View File

@ -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;
}

View File

@ -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) {

View File

@ -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;
}

View File

@ -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,

View File

@ -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);

View File

@ -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;

View File

@ -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());
}

View File

@ -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);

View File

@ -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;

View File

@ -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);
});
})();

View File

@ -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);
}
}

View File

@ -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();
}

View File

@ -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);

View File

@ -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,

View File

@ -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;
});
}

View File

@ -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));

View File

@ -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);

View File

@ -12,7 +12,6 @@
}
.antdv-message {
font-family: 'normal';
font-size: 1.6em;
}

View File

@ -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>

View File

@ -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"
>出自&nbsp;&nbsp;&nbsp;&nbsp;{{
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>

View File

@ -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 {

View File

@ -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;
}

View File

@ -141,7 +141,6 @@ onMounted(async () => {
#chapter-text {
position: relative;
font-family: 'normal';
font-size: 5vh;
text-shadow: 0px 0px 5px #fff;
}

View File

@ -1,117 +0,0 @@
<template>
<Box id="complete-box">
<div id="complete">
<span>完成成就&nbsp;&nbsp;&nbsp;&nbsp;{{ 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>

View File

@ -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>

View File

@ -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%;
}

View File

@ -135,7 +135,6 @@ onMounted(() => {
<style lang="less" scoped>
#fixed {
font-family: 'normal';
font-size: 2.5vh;
opacity: 0;
transition: opacity 0.2s linear;

View File

@ -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;

View File

@ -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';

View File

@ -161,7 +161,6 @@ onUnmounted(() => {
<style lang="less" scoped>
#tools {
width: 100%;
font-family: 'normal';
font-size: 3.2vh;
height: 5vh;
position: fixed;

View File

@ -323,7 +323,6 @@ onUnmounted(() => {
#shop {
width: 90vh;
height: 90vh;
font-family: 'normal';
font-size: 150%;
display: flex;
flex-direction: column;

View File

@ -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 `${'&nbsp;'.repeat(12)}${v}`;
else if (
(has(a[i - 1]) &&
v !== '<br>' &&
a[i - 1] === '<br>') ||
i === 0
) {
return `${'&nbsp;'.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>

View File

@ -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>
&nbsp;&nbsp;
<span>{{ chapterDict[chapter] }}</span>
&nbsp;&nbsp;
<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>

View File

@ -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() {

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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;

View File

@ -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;