mirror of
https://github.com/unanmed/HumanBreak.git
synced 2025-01-31 15:09:26 +08:00
技能树
This commit is contained in:
parent
05fe01abfa
commit
d7bc60cdd2
@ -673,7 +673,7 @@ var data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d =
|
|||||||
"ignoreChangeFloor": true,
|
"ignoreChangeFloor": true,
|
||||||
"canGoDeadZone": false,
|
"canGoDeadZone": false,
|
||||||
"enableMoveDirectly": true,
|
"enableMoveDirectly": true,
|
||||||
"enableRouteFolding": false,
|
"enableRouteFolding": true,
|
||||||
"disableShopOnDamage": false,
|
"disableShopOnDamage": false,
|
||||||
"blurFg": true,
|
"blurFg": true,
|
||||||
"extendToolbar": true,
|
"extendToolbar": true,
|
||||||
|
@ -1408,7 +1408,8 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = {
|
|||||||
values: values,
|
values: values,
|
||||||
version: core.firstData.version,
|
version: core.firstData.version,
|
||||||
guid: core.getGuid(),
|
guid: core.getGuid(),
|
||||||
time: new Date().getTime()
|
time: new Date().getTime(),
|
||||||
|
skills: core.saveSkillTree()
|
||||||
};
|
};
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
@ -1454,6 +1455,7 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = {
|
|||||||
core.setFlag('__fromLoad__', true);
|
core.setFlag('__fromLoad__', true);
|
||||||
|
|
||||||
// TODO:增加自己的一些读档处理
|
// TODO:增加自己的一些读档处理
|
||||||
|
core.loadSkillTree(data.skills);
|
||||||
|
|
||||||
// 切换到对应的楼层
|
// 切换到对应的楼层
|
||||||
core.changeFloor(data.floorId, null, data.hero.loc, 0, function () {
|
core.changeFloor(data.floorId, null, data.hero.loc, 0, function () {
|
||||||
|
@ -1513,572 +1513,6 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
intelligenceTree: function () {
|
|
||||||
// 智慧加点
|
|
||||||
var list;
|
|
||||||
var levels;
|
|
||||||
var currPage = 1,
|
|
||||||
selector = [1, 1];
|
|
||||||
// 获取技能等级
|
|
||||||
this.getSkillLevel = function () {
|
|
||||||
if (!flags.levels) flags.levels = [];
|
|
||||||
for (var i = 0; i < 10; i++) {
|
|
||||||
if (flags.levels[i] == null) flags.levels[i] = 0;
|
|
||||||
}
|
|
||||||
return flags.levels;
|
|
||||||
};
|
|
||||||
// 初始化
|
|
||||||
this.initializeList = function (changePage) {
|
|
||||||
// 初始化等级
|
|
||||||
levels = core.clone(core.getSkillLevel());
|
|
||||||
// 技能定义 0索引 1名称 2描述 3等级 4消耗 5前置技能[索引,等级,索引,等级] 6位置(5×5) 7最大等级 8页码数 9效果
|
|
||||||
list = [
|
|
||||||
[
|
|
||||||
0,
|
|
||||||
'力量',
|
|
||||||
'力量就是根本!可以通过智慧增加力量',
|
|
||||||
0,
|
|
||||||
10 * levels[0] + 10,
|
|
||||||
null,
|
|
||||||
[1, 2],
|
|
||||||
10,
|
|
||||||
1,
|
|
||||||
'攻击+' + levels[0] * 2
|
|
||||||
],
|
|
||||||
[
|
|
||||||
1,
|
|
||||||
'致命一击',
|
|
||||||
'爆发出全部力量攻击敌人',
|
|
||||||
0,
|
|
||||||
30 * levels[1] + 30,
|
|
||||||
[0, 5],
|
|
||||||
[2, 1],
|
|
||||||
10,
|
|
||||||
1,
|
|
||||||
'每回合额外伤害+' + levels[1] * 5
|
|
||||||
],
|
|
||||||
[
|
|
||||||
2,
|
|
||||||
'断灭之刃',
|
|
||||||
'\\r[#dddd44]主动技能\\r[],开启后会在战斗时会额外增加一定量的攻击, 但同时减少一定量的防御,快捷键1',
|
|
||||||
0,
|
|
||||||
200 * levels[2] + 400,
|
|
||||||
[1, 5],
|
|
||||||
[4, 1],
|
|
||||||
5,
|
|
||||||
1,
|
|
||||||
levels[2] * 10 +
|
|
||||||
'%攻击加成,减少' +
|
|
||||||
levels[2] * 10 +
|
|
||||||
'%的防御'
|
|
||||||
],
|
|
||||||
[
|
|
||||||
3,
|
|
||||||
'坚韧',
|
|
||||||
'由智慧转化出坚韧!',
|
|
||||||
0,
|
|
||||||
10 * levels[3] + 10,
|
|
||||||
null,
|
|
||||||
[1, 4],
|
|
||||||
10,
|
|
||||||
1,
|
|
||||||
'防御+' + levels[3] * 2
|
|
||||||
],
|
|
||||||
[
|
|
||||||
4,
|
|
||||||
'回春',
|
|
||||||
'让智慧化为治愈之泉水!',
|
|
||||||
0,
|
|
||||||
20 + levels[4] * 20,
|
|
||||||
[3, 5],
|
|
||||||
[2, 5],
|
|
||||||
25,
|
|
||||||
1,
|
|
||||||
'每回合回复' + 1 * levels[4] + '生命'
|
|
||||||
],
|
|
||||||
[
|
|
||||||
5,
|
|
||||||
'治愈之泉',
|
|
||||||
'让生命变得更多一些吧!每吃50瓶血瓶就增加当前生命回复10%的生命回复',
|
|
||||||
0,
|
|
||||||
1500,
|
|
||||||
[4, 25],
|
|
||||||
[4, 5],
|
|
||||||
1,
|
|
||||||
1,
|
|
||||||
'50瓶血10%生命回复'
|
|
||||||
],
|
|
||||||
[
|
|
||||||
6,
|
|
||||||
'坚固之盾',
|
|
||||||
'让护甲更加坚硬一些吧!',
|
|
||||||
0,
|
|
||||||
50 + levels[6] * 50,
|
|
||||||
[3, 5],
|
|
||||||
[2, 3],
|
|
||||||
10,
|
|
||||||
1,
|
|
||||||
'防御+' + 10 * levels[6]
|
|
||||||
],
|
|
||||||
[
|
|
||||||
7,
|
|
||||||
'无上之盾',
|
|
||||||
'\\r[#dddd44]第一章终极技能\\r[],战斗时智慧会充当等量护盾',
|
|
||||||
0,
|
|
||||||
2500,
|
|
||||||
[6, 10, 5, 1, 2, 2],
|
|
||||||
[5, 3],
|
|
||||||
1,
|
|
||||||
1,
|
|
||||||
'战斗时智慧会充当护盾'
|
|
||||||
]
|
|
||||||
];
|
|
||||||
// 深拷贝list
|
|
||||||
list = core.clone(list);
|
|
||||||
var acted = false;
|
|
||||||
for (var i in list) {
|
|
||||||
list[i][3] = levels[i];
|
|
||||||
if (!list[i][5]) list[i][5] = [];
|
|
||||||
// 根据页码获取光标应该在的位置
|
|
||||||
if (changePage && !acted) {
|
|
||||||
if (list[i][8] == currPage) {
|
|
||||||
selector = list[i][6];
|
|
||||||
acted = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
// 升级效果
|
|
||||||
this.treeEffect = function (index) {
|
|
||||||
index = parseInt(index);
|
|
||||||
switch (index) {
|
|
||||||
case 0: // 力量 +2攻击
|
|
||||||
core.status.hero.atk += 2;
|
|
||||||
break;
|
|
||||||
case 1: // 致命一击 +5额外攻击
|
|
||||||
core.status.hero.mana += 5;
|
|
||||||
break;
|
|
||||||
case 2: // 断灭之刃
|
|
||||||
core.setFlag('bladeOn', true);
|
|
||||||
break;
|
|
||||||
case 3: // 坚韧 +2防御
|
|
||||||
core.status.hero.def += 2;
|
|
||||||
break;
|
|
||||||
case 4: // 回春 +1回复
|
|
||||||
core.status.hero.hpmax += 1;
|
|
||||||
break;
|
|
||||||
case 5: // 治愈之泉
|
|
||||||
core.setFlag('spring', true);
|
|
||||||
break;
|
|
||||||
case 6: // 坚固之盾 +10防御
|
|
||||||
core.status.hero.def += 10;
|
|
||||||
break;
|
|
||||||
case 7: // 无上之盾
|
|
||||||
core.setFlag('superSheild', true);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
core.status.hero.mdef -= list[index][4];
|
|
||||||
};
|
|
||||||
// 由光标位置获得索引
|
|
||||||
this.getIdBySelector = function (x, y, page) {
|
|
||||||
for (var i in list) {
|
|
||||||
if (
|
|
||||||
list[i][8] == page &&
|
|
||||||
x == list[i][6][0] &&
|
|
||||||
y == list[i][6][1]
|
|
||||||
) {
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
// 绘制技能树界面
|
|
||||||
this.drawTree = function (changePage) {
|
|
||||||
// 初始化
|
|
||||||
if (!changePage) changePage = false;
|
|
||||||
core.initializeList(changePage);
|
|
||||||
var id = core.getIdBySelector(selector[0], selector[1], currPage);
|
|
||||||
var name = list[id][1],
|
|
||||||
description = list[id][2],
|
|
||||||
level = levels[id],
|
|
||||||
cost = list[id][4],
|
|
||||||
foreSkill = list[id][5],
|
|
||||||
max = list[id][7],
|
|
||||||
effect = list[id][9];
|
|
||||||
// 先建画布
|
|
||||||
core.createCanvas('tree', 0, 0, 480, 480, 130);
|
|
||||||
// 背景
|
|
||||||
core.fillRect('tree', 0, 0, 480, 480, [0, 0, 0, 0.95]);
|
|
||||||
core.drawLine('tree', 0, 172, 480, 172, [200, 200, 200, 0.95], 1);
|
|
||||||
core.drawLine('tree', 308, 172, 308, 480, [200, 200, 200, 0.95], 1);
|
|
||||||
core.drawLine('tree', 308, 450, 480, 450, [200, 200, 200, 0.95], 1);
|
|
||||||
core.drawLine('tree', 308, 220, 480, 220, [200, 200, 200, 0.95], 1);
|
|
||||||
core.drawLine('tree', 308, 413, 480, 413, [200, 200, 200, 0.95], 1);
|
|
||||||
for (var i = 0; i <= 239; i++) {
|
|
||||||
core.drawLine(
|
|
||||||
'tree',
|
|
||||||
i,
|
|
||||||
40,
|
|
||||||
480 - i,
|
|
||||||
40,
|
|
||||||
[0, 255, 107, 0.002],
|
|
||||||
2
|
|
||||||
);
|
|
||||||
}
|
|
||||||
// 每一项技能图标
|
|
||||||
for (var i in list) {
|
|
||||||
if (list[i][8] != currPage) continue;
|
|
||||||
// 技能间的线
|
|
||||||
for (var j = 0; j < list[i][5].length; j += 2) {
|
|
||||||
if (!list[i][5]) break;
|
|
||||||
if (levels[list[i][5][j]] < list[i][5][j + 1])
|
|
||||||
core.drawLine(
|
|
||||||
'tree',
|
|
||||||
list[list[i][5][j]][6][0] * 56 - 14,
|
|
||||||
list[list[i][5][j]][6][1] * 56 + 158,
|
|
||||||
list[i][6][0] * 56 - 14,
|
|
||||||
list[i][6][1] * 56 + 158,
|
|
||||||
'#aaaaaa',
|
|
||||||
1
|
|
||||||
);
|
|
||||||
else
|
|
||||||
core.drawLine(
|
|
||||||
'tree',
|
|
||||||
list[list[i][5][j]][6][0] * 56 - 14,
|
|
||||||
list[list[i][5][j]][6][1] * 56 + 158,
|
|
||||||
list[i][6][0] * 56 - 14,
|
|
||||||
list[i][6][1] * 56 + 158,
|
|
||||||
'#00FF88',
|
|
||||||
1
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 图标
|
|
||||||
for (var i in list) {
|
|
||||||
// 图标
|
|
||||||
core.drawImage(
|
|
||||||
'tree',
|
|
||||||
'skill' + i + '.png',
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
114,
|
|
||||||
114,
|
|
||||||
list[i][6][0] * 56 - 28,
|
|
||||||
list[i][6][1] * 56 + 144,
|
|
||||||
28,
|
|
||||||
28
|
|
||||||
);
|
|
||||||
// 方框
|
|
||||||
if (levels[i] == 0)
|
|
||||||
core.strokeRect(
|
|
||||||
'tree',
|
|
||||||
list[i][6][0] * 56 - 28,
|
|
||||||
list[i][6][1] * 56 + 144,
|
|
||||||
28,
|
|
||||||
28,
|
|
||||||
'#888888',
|
|
||||||
1
|
|
||||||
);
|
|
||||||
else if (levels[i] == list[i][7])
|
|
||||||
core.strokeRect(
|
|
||||||
'tree',
|
|
||||||
list[i][6][0] * 56 - 28,
|
|
||||||
list[i][6][1] * 56 + 144,
|
|
||||||
28,
|
|
||||||
28,
|
|
||||||
'#F7FF68',
|
|
||||||
1
|
|
||||||
);
|
|
||||||
else
|
|
||||||
core.strokeRect(
|
|
||||||
'tree',
|
|
||||||
list[i][6][0] * 56 - 28,
|
|
||||||
list[i][6][1] * 56 + 144,
|
|
||||||
28,
|
|
||||||
28,
|
|
||||||
'#00FF69',
|
|
||||||
1
|
|
||||||
);
|
|
||||||
// 光标
|
|
||||||
core.strokeRect(
|
|
||||||
'tree',
|
|
||||||
selector[0] * 56 - 28,
|
|
||||||
selector[1] * 56 + 144,
|
|
||||||
28,
|
|
||||||
28,
|
|
||||||
'#ffff00',
|
|
||||||
1
|
|
||||||
);
|
|
||||||
}
|
|
||||||
// 说明
|
|
||||||
core.setTextAlign('tree', 'center');
|
|
||||||
core.fillText('tree', name, 240, 30, '#00FFD5', '28px normal');
|
|
||||||
core.setTextAlign('tree', 'left');
|
|
||||||
core.drawTextContent('tree', ' ' + description, {
|
|
||||||
left: 10,
|
|
||||||
top: 42,
|
|
||||||
maxWidth: 460,
|
|
||||||
font: 'normal',
|
|
||||||
fontSize: 18
|
|
||||||
});
|
|
||||||
// 效果
|
|
||||||
if (level != 0)
|
|
||||||
core.drawTextContent('tree', '当前效果:' + effect, {
|
|
||||||
left: 10,
|
|
||||||
top: 122,
|
|
||||||
maxWidth: 460,
|
|
||||||
font: 'normal',
|
|
||||||
fontSize: 18
|
|
||||||
});
|
|
||||||
if (level != max) {
|
|
||||||
flags.levels[id] += 1;
|
|
||||||
core.initializeList(false);
|
|
||||||
effect = list[id][9];
|
|
||||||
core.drawTextContent('tree', '下一级效果:' + effect, {
|
|
||||||
left: 10,
|
|
||||||
top: 147,
|
|
||||||
maxWidth: 460,
|
|
||||||
font: 'normal',
|
|
||||||
fontSize: 18
|
|
||||||
});
|
|
||||||
flags.levels[id]--;
|
|
||||||
core.initializeList(false);
|
|
||||||
effect = list[id][9];
|
|
||||||
}
|
|
||||||
core.setTextAlign('tree', 'center');
|
|
||||||
// 等级
|
|
||||||
core.fillText(
|
|
||||||
'tree',
|
|
||||||
'等级:' + level + '/' + max,
|
|
||||||
394,
|
|
||||||
190,
|
|
||||||
'#ffffff',
|
|
||||||
'18px normal'
|
|
||||||
);
|
|
||||||
// 升级
|
|
||||||
if (level != max)
|
|
||||||
core.fillText(
|
|
||||||
'tree',
|
|
||||||
'升级花费:' + cost,
|
|
||||||
394,
|
|
||||||
210,
|
|
||||||
'#ffffff',
|
|
||||||
'18px normal'
|
|
||||||
);
|
|
||||||
// 退出
|
|
||||||
core.fillText('tree', '退出', 394, 470, '#ffffff', '18px normal');
|
|
||||||
// 页码数
|
|
||||||
var text = core.replaceNumberWithChinese(currPage);
|
|
||||||
core.fillText(
|
|
||||||
'tree',
|
|
||||||
'第' + text + '章',
|
|
||||||
394,
|
|
||||||
440,
|
|
||||||
'#ffffff',
|
|
||||||
'24px normal'
|
|
||||||
);
|
|
||||||
if (currPage != 1)
|
|
||||||
core.fillText('tree', '<', 334, 440, '#ffffff', '24px normal');
|
|
||||||
if (currPage != flags.chapter)
|
|
||||||
core.fillText('tree', '>', 454, 440, '#ffffff', '24px normal');
|
|
||||||
// 前置技能
|
|
||||||
core.fillText(
|
|
||||||
'tree',
|
|
||||||
'前置技能',
|
|
||||||
394,
|
|
||||||
245,
|
|
||||||
'#ffffff',
|
|
||||||
'20px normal'
|
|
||||||
);
|
|
||||||
if (foreSkill.length > 0) {
|
|
||||||
for (var i = 0; i < foreSkill.length; i += 2) {
|
|
||||||
core.fillText(
|
|
||||||
'tree',
|
|
||||||
foreSkill[i + 1] + '级 ' + list[foreSkill[i]][1],
|
|
||||||
394,
|
|
||||||
270 + 10 * i
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
// 升级操作
|
|
||||||
this.upgradeTree = function (index) {
|
|
||||||
// 执行操作
|
|
||||||
if (levels[index] == list[index][7]) {
|
|
||||||
core.playSound('操作失败');
|
|
||||||
core.insertAction(['该技能已满级!']);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// 判断前置技能
|
|
||||||
var fore = list[index][5];
|
|
||||||
for (var i = 0; i < fore.length; i += 2) {
|
|
||||||
if (levels[fore[i]] < fore[i + 1]) {
|
|
||||||
core.playSound('操作失败');
|
|
||||||
core.insertAction(['前置技能未满足!']);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (core.status.hero.mdef < list[index][4]) {
|
|
||||||
core.playSound('操作失败');
|
|
||||||
core.insertAction(['智慧点不足!']);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
flags.levels[index]++;
|
|
||||||
core.treeEffect(index);
|
|
||||||
// 刷新
|
|
||||||
core.drawTree(false);
|
|
||||||
core.updateStatusBar();
|
|
||||||
core.updateDamage();
|
|
||||||
// 音效
|
|
||||||
core.playSound('tree.mp3');
|
|
||||||
core.insertAction([{ type: 'sleep', time: 100, noSkip: true }]);
|
|
||||||
};
|
|
||||||
// 上下左右
|
|
||||||
this.moveSelector = function (keycode, times) {
|
|
||||||
times = times || 0;
|
|
||||||
core.playSound('光标移动');
|
|
||||||
if (keycode == 37 || keycode == 39) {
|
|
||||||
// left right
|
|
||||||
if (times > 3) {
|
|
||||||
// 正左右没有东西 移动至下一列
|
|
||||||
selector[0] -= 3 * (keycode - 38);
|
|
||||||
for (var i in list) {
|
|
||||||
if (list[i][8] != currPage) continue;
|
|
||||||
if (list[i][6][0] == selector[0]) {
|
|
||||||
selector = list[i][6];
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
selector[0] -= keycode - 38;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
selector[0] += keycode - 38;
|
|
||||||
for (var i in list) {
|
|
||||||
// 正左右有技能 移动至最近的技能
|
|
||||||
if (list[i][8] != currPage) continue;
|
|
||||||
if (
|
|
||||||
list[i][6][0] == selector[0] &&
|
|
||||||
list[i][6][1] == selector[1]
|
|
||||||
) {
|
|
||||||
selector = list[i][6];
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return core.moveSelector(keycode, times + 1);
|
|
||||||
} else {
|
|
||||||
// up down
|
|
||||||
if (times > 3) {
|
|
||||||
selector[1] -= 3 * (keycode - 39);
|
|
||||||
for (var i in list) {
|
|
||||||
if (list[i][8] != currPage) continue;
|
|
||||||
if (list[i][6][1] == selector[1]) {
|
|
||||||
selector = list[i][6];
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
selector[1] -= keycode - 39;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
selector[1] += keycode - 39;
|
|
||||||
for (var i in list) {
|
|
||||||
if (list[i][8] != currPage) continue;
|
|
||||||
if (
|
|
||||||
list[i][6][1] == selector[1] &&
|
|
||||||
list[i][6][0] == selector[0]
|
|
||||||
) {
|
|
||||||
selector = list[i][6];
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return core.moveSelector(keycode, times + 1);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
// 由点击位置获取光标位置
|
|
||||||
this.getSelectorByLoc = function (px, py) {
|
|
||||||
if (px % 56 < 28 || (py - 172) % 56 < 28) return;
|
|
||||||
var x = Math.ceil(px / 56),
|
|
||||||
y = Math.ceil((py - 172) / 56);
|
|
||||||
if (selector[0] == x && selector[1] == y) {
|
|
||||||
var id = core.getIdBySelector(
|
|
||||||
selector[0],
|
|
||||||
selector[1],
|
|
||||||
currPage
|
|
||||||
);
|
|
||||||
core.upgradeTree(id);
|
|
||||||
} else {
|
|
||||||
for (var i in list) {
|
|
||||||
if (list[i][8] != currPage) continue;
|
|
||||||
if (list[i][6][0] == x && list[i][6][1] == y) {
|
|
||||||
selector = [x, y];
|
|
||||||
core.playSound('光标移动');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
// 键盘操作
|
|
||||||
this.treeKeyboard = function (keycode) {
|
|
||||||
var id = core.getIdBySelector(selector[0], selector[1], currPage);
|
|
||||||
switch (keycode) {
|
|
||||||
case 13:
|
|
||||||
case 32: // 确认升级
|
|
||||||
core.upgradeTree(id);
|
|
||||||
break;
|
|
||||||
case 27:
|
|
||||||
case 88: // 退出
|
|
||||||
core.playSound('取消');
|
|
||||||
core.insertAction({ type: 'break' });
|
|
||||||
break;
|
|
||||||
case 37:
|
|
||||||
case 38:
|
|
||||||
case 39:
|
|
||||||
case 40: // 移动光标
|
|
||||||
core.moveSelector(keycode);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
// 点击操作
|
|
||||||
this.treeClick = function (px, py) {
|
|
||||||
if (px >= 308 && py >= 450) {
|
|
||||||
core.playSound('取消');
|
|
||||||
core.insertAction({ type: 'break' });
|
|
||||||
}
|
|
||||||
if (px <= 308 && py >= 172) {
|
|
||||||
core.getSelectorByLoc(px, py);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
// 操作
|
|
||||||
this.actTree = function () {
|
|
||||||
if (flags.type == 0) return this.treeKeyboard(flags.keycode);
|
|
||||||
else return this.treeClick(flags.px, flags.py);
|
|
||||||
};
|
|
||||||
// 开启
|
|
||||||
this.openTree = function () {
|
|
||||||
// 插入事件
|
|
||||||
core.initializeList(true);
|
|
||||||
core.playSound('打开界面');
|
|
||||||
core.insertAction([
|
|
||||||
{
|
|
||||||
type: 'while',
|
|
||||||
condition: 'true',
|
|
||||||
data: [
|
|
||||||
{
|
|
||||||
type: 'function',
|
|
||||||
function: '() => { core.plugin.drawTree(false); }'
|
|
||||||
},
|
|
||||||
{ type: 'wait' },
|
|
||||||
{
|
|
||||||
type: 'function',
|
|
||||||
function: '() => { core.plugin.actTree(); }'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'function',
|
|
||||||
function: "() => { core.deleteCanvas('tree');}"
|
|
||||||
}
|
|
||||||
]);
|
|
||||||
};
|
|
||||||
},
|
|
||||||
skills: function () {
|
skills: function () {
|
||||||
// 所有的主动技能效果
|
// 所有的主动技能效果
|
||||||
var ignoreInJump = {
|
var ignoreInJump = {
|
||||||
@ -6145,12 +5579,128 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = {
|
|||||||
flags[setting] = v;
|
flags[setting] = v;
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
core.registerReplayAction('upgradeSkill', name => {
|
||||||
|
if (!name.startsWith('skill:')) return false;
|
||||||
|
const skill = parseInt(name.slice(6));
|
||||||
|
core.upgradeSkill(skill);
|
||||||
|
});
|
||||||
},
|
},
|
||||||
skillTree: function () {
|
skillTree: function () {
|
||||||
/**
|
/**
|
||||||
* @type {number[]}
|
* @type {number[]}
|
||||||
*/
|
*/
|
||||||
const levels = [];
|
let levels = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {Record<Chapter, Skill[]>}
|
||||||
|
*/
|
||||||
|
const skills = {
|
||||||
|
chapter1: [
|
||||||
|
{
|
||||||
|
index: 0,
|
||||||
|
title: '力量',
|
||||||
|
desc: [
|
||||||
|
'力量就是根本!可以通过智慧增加力量,每级增加2点攻击。'
|
||||||
|
],
|
||||||
|
consume: '10 * level + 10',
|
||||||
|
front: [],
|
||||||
|
loc: [1, 2],
|
||||||
|
max: 10,
|
||||||
|
effect: ['攻击 + ${level * 2}']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
index: 1,
|
||||||
|
title: '致命一击',
|
||||||
|
desc: ['爆发出全部力量攻击敌人,每级增加5点额外攻击。'],
|
||||||
|
consume: '30 * level + 30',
|
||||||
|
front: [[0, 5]],
|
||||||
|
loc: [2, 1],
|
||||||
|
max: 10,
|
||||||
|
effect: ['额外攻击 + ${level * 5}']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
index: 2,
|
||||||
|
title: '断灭之刃',
|
||||||
|
desc: [
|
||||||
|
'<span style="color: gold">主动技能,快捷键1</span>,',
|
||||||
|
'开启后会在战斗时会额外增加一定量的攻击,但同时减少一定量的防御。'
|
||||||
|
],
|
||||||
|
consume: '200 * level + 400',
|
||||||
|
front: [[1, 5]],
|
||||||
|
loc: [4, 1],
|
||||||
|
max: 5,
|
||||||
|
effect: ['增加${level * 10}%攻击,减少${level * 10}%防御']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
index: 3,
|
||||||
|
title: '坚韧',
|
||||||
|
desc: ['由智慧转化出坚韧!每级增加2点防御'],
|
||||||
|
consume: '10 * level + 10',
|
||||||
|
front: [],
|
||||||
|
loc: [1, 4],
|
||||||
|
max: 10,
|
||||||
|
effect: ['防御 + ${level * 2}']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
index: 4,
|
||||||
|
title: '回春',
|
||||||
|
desc: ['让智慧化为治愈之泉水!每级增加1点生命回复'],
|
||||||
|
consume: '20 * level + 20',
|
||||||
|
front: [[3, 5]],
|
||||||
|
loc: [2, 5],
|
||||||
|
max: 25,
|
||||||
|
effect: ['生命回复 + ${level}']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
index: 5,
|
||||||
|
title: '治愈之泉',
|
||||||
|
desc: [
|
||||||
|
'让生命变得更多一些吧!每吃50瓶血瓶就增加当前生命回复10%的生命回复'
|
||||||
|
],
|
||||||
|
consume: '1500',
|
||||||
|
front: [[4, 25]],
|
||||||
|
loc: [4, 5],
|
||||||
|
max: 1,
|
||||||
|
effect: ['50瓶血10%生命回复']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
index: 6,
|
||||||
|
title: '坚固之盾',
|
||||||
|
desc: ['让护甲更加坚硬一些吧!每级增加10点防御'],
|
||||||
|
consume: '50 + level * 50',
|
||||||
|
front: [[3, 5]],
|
||||||
|
loc: [2, 3],
|
||||||
|
max: 10,
|
||||||
|
effect: ['防御 + ${level * 10}']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
index: 7,
|
||||||
|
title: '无上之盾',
|
||||||
|
desc: [
|
||||||
|
'<span style="color: #dd4">第一章终极技能</span>,战斗时智慧会充当等量护盾'
|
||||||
|
],
|
||||||
|
consume: '50 + level * 50',
|
||||||
|
front: [
|
||||||
|
[6, 10],
|
||||||
|
[5, 1],
|
||||||
|
[2, 2]
|
||||||
|
],
|
||||||
|
loc: [5, 3],
|
||||||
|
max: 1,
|
||||||
|
effect: ['战斗时智慧会充当护盾']
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
core.plugin.skills = skills;
|
||||||
|
|
||||||
|
this.getSkillFromIndex = function (index) {
|
||||||
|
for (const [, skill] of Object.entries(skills)) {
|
||||||
|
const s = skill.find(v => v.index === index);
|
||||||
|
if (s) return s;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取技能等级
|
* 获取技能等级
|
||||||
@ -6159,5 +5709,86 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = {
|
|||||||
this.getSkillLevel = function (skill) {
|
this.getSkillLevel = function (skill) {
|
||||||
return (levels[skill] ??= 0);
|
return (levels[skill] ??= 0);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
this.getSkillConsume = function (skill) {
|
||||||
|
return eval(
|
||||||
|
this.getSkillFromIndex(skill).consume.replace(
|
||||||
|
/level(:\d+)?/g,
|
||||||
|
(str, $1) => {
|
||||||
|
if ($1) return `core.getSkillLevel(${$1})`;
|
||||||
|
else return `core.getSkillLevel(${skill})`;
|
||||||
|
}
|
||||||
|
)
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.openTree = function () {
|
||||||
|
if (main.replayChecking) return;
|
||||||
|
core.plugin.skillTreeOpened.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 能否升级某个技能
|
||||||
|
* @param {number} skill
|
||||||
|
*/
|
||||||
|
function canUpgrade(skill) {
|
||||||
|
const consume = core.getSkillConsume(skill);
|
||||||
|
if (consume > core.status.hero.mdef) return false;
|
||||||
|
const level = core.getSkillLevel(skill);
|
||||||
|
const s = core.getSkillFromIndex(skill);
|
||||||
|
if (level === s.max) return false;
|
||||||
|
const front = s.front;
|
||||||
|
for (const [skill, level] of front) {
|
||||||
|
if (core.getSkillLevel(skill) < level) return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 实际升级效果
|
||||||
|
* @param {number} skill
|
||||||
|
*/
|
||||||
|
this.upgradeSkill = function (skill) {
|
||||||
|
if (!canUpgrade(skill)) return false;
|
||||||
|
switch (skill) {
|
||||||
|
case 0: // 力量 +2攻击
|
||||||
|
core.status.hero.atk += 2;
|
||||||
|
break;
|
||||||
|
case 1: // 致命一击 +5额外攻击
|
||||||
|
core.status.hero.mana += 5;
|
||||||
|
break;
|
||||||
|
case 2: // 断灭之刃
|
||||||
|
core.setFlag('bladeOn', true);
|
||||||
|
break;
|
||||||
|
case 3: // 坚韧 +2防御
|
||||||
|
core.status.hero.def += 2;
|
||||||
|
break;
|
||||||
|
case 4: // 回春 +1回复
|
||||||
|
core.status.hero.hpmax += 1;
|
||||||
|
break;
|
||||||
|
case 5: // 治愈之泉
|
||||||
|
core.setFlag('spring', true);
|
||||||
|
break;
|
||||||
|
case 6: // 坚固之盾 +10防御
|
||||||
|
core.status.hero.def += 10;
|
||||||
|
break;
|
||||||
|
case 7: // 无上之盾
|
||||||
|
core.setFlag('superSheild', true);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
const consume = core.getSkillConsume(skill);
|
||||||
|
core.status.hero.mdef -= consume;
|
||||||
|
levels[skill]++;
|
||||||
|
core.updateStatusBar();
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
this.saveSkillTree = function () {
|
||||||
|
return levels.slice();
|
||||||
|
};
|
||||||
|
|
||||||
|
this.loadSkillTree = function (data) {
|
||||||
|
levels = data ?? [];
|
||||||
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -11,6 +11,8 @@
|
|||||||
</Scroll>
|
</Scroll>
|
||||||
<a-divider
|
<a-divider
|
||||||
class="divider"
|
class="divider"
|
||||||
|
dashed
|
||||||
|
style="border-color: #ddd4"
|
||||||
:type="isMobile ? 'horizontal' : 'vertical'"
|
:type="isMobile ? 'horizontal' : 'vertical'"
|
||||||
></a-divider>
|
></a-divider>
|
||||||
<Scroll class="column-right" :id="`column-right-${id}`"
|
<Scroll class="column-right" :id="`column-right-${id}`"
|
||||||
|
@ -85,7 +85,8 @@
|
|||||||
"本塔的怪物手册功能很多,下面一一介绍。",
|
"本塔的怪物手册功能很多,下面一一介绍。",
|
||||||
"<br>",
|
"<br>",
|
||||||
"<br>",
|
"<br>",
|
||||||
"怪物手册打开的时候有一个0.6秒的动画,如果不想要可以在开头捡的系统设置里面关闭。",
|
"怪物手册打开的时候有一个0.6秒的动画,如果不想要可以在开头捡的系统设置里面关闭。注意,本塔中几乎所有ui的关闭按钮",
|
||||||
|
"都在左上角",
|
||||||
"<br>",
|
"<br>",
|
||||||
"<br>",
|
"<br>",
|
||||||
"打开怪物手册后,怪物手册的布局与样板自带的类似。与样板不同的是,这里的怪物手册不再是翻页式结构。",
|
"打开怪物手册后,怪物手册的布局与样板自带的类似。与样板不同的是,这里的怪物手册不再是翻页式结构。",
|
||||||
|
@ -6,6 +6,7 @@ import Equipbox from '../ui/equipbox.vue';
|
|||||||
import Settings from '../ui/settings.vue';
|
import Settings from '../ui/settings.vue';
|
||||||
import Desc from '../ui/desc.vue';
|
import Desc from '../ui/desc.vue';
|
||||||
import Skill from '../ui/skill.vue';
|
import Skill from '../ui/skill.vue';
|
||||||
|
import SkillTree from '../ui/skillTree.vue';
|
||||||
|
|
||||||
export const bookOpened = ref(false);
|
export const bookOpened = ref(false);
|
||||||
export const toolOpened = ref(false);
|
export const toolOpened = ref(false);
|
||||||
@ -14,6 +15,7 @@ export const showStatusBar = ref(false);
|
|||||||
export const settingsOpened = ref(false);
|
export const settingsOpened = ref(false);
|
||||||
export const descOpened = ref(false);
|
export const descOpened = ref(false);
|
||||||
export const skillOpened = ref(false);
|
export const skillOpened = ref(false);
|
||||||
|
export const skillTreeOpened = ref(false);
|
||||||
|
|
||||||
export const transition = ref(true);
|
export const transition = ref(true);
|
||||||
export const noClosePanel = ref(false);
|
export const noClosePanel = ref(false);
|
||||||
@ -27,7 +29,8 @@ const UI_LIST: [Ref<boolean>, Component][] = [
|
|||||||
[equipOpened, Equipbox],
|
[equipOpened, Equipbox],
|
||||||
[settingsOpened, Settings],
|
[settingsOpened, Settings],
|
||||||
[descOpened, Desc],
|
[descOpened, Desc],
|
||||||
[skillOpened, Skill]
|
[skillOpened, Skill],
|
||||||
|
[skillTreeOpened, SkillTree]
|
||||||
];
|
];
|
||||||
|
|
||||||
/** ui栈 */
|
/** ui栈 */
|
||||||
@ -59,7 +62,8 @@ export default function init() {
|
|||||||
showStatusBar,
|
showStatusBar,
|
||||||
settingsOpened,
|
settingsOpened,
|
||||||
descOpened,
|
descOpened,
|
||||||
skillOpened
|
skillOpened,
|
||||||
|
skillTreeOpened
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,3 +133,21 @@ export function tip(
|
|||||||
class: 'antdv-message'
|
class: 'antdv-message'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置文字分段换行等
|
||||||
|
* @param str 文字
|
||||||
|
*/
|
||||||
|
export function splitText(str: string[]) {
|
||||||
|
return str
|
||||||
|
.map((v, i, a) => {
|
||||||
|
if (/^\d+\./.test(v)) return `${' '.repeat(12)}${v}`;
|
||||||
|
else if (
|
||||||
|
(has(a[i - 1]) && v !== '<br>' && a[i - 1] === '<br>') ||
|
||||||
|
i === 0
|
||||||
|
) {
|
||||||
|
return `${' '.repeat(8)}${v}`;
|
||||||
|
} else return v;
|
||||||
|
})
|
||||||
|
.join('');
|
||||||
|
}
|
||||||
|
53
src/types/plugin.d.ts
vendored
53
src/types/plugin.d.ts
vendored
@ -14,7 +14,11 @@ type CanParseCss = keyof {
|
|||||||
: never]: CSSStyleDeclaration[P];
|
: never]: CSSStyleDeclaration[P];
|
||||||
};
|
};
|
||||||
|
|
||||||
interface PluginDeclaration extends PluginUtils, PluginUis, PluginUse {
|
interface PluginDeclaration
|
||||||
|
extends PluginUtils,
|
||||||
|
PluginUis,
|
||||||
|
PluginUse,
|
||||||
|
SkillTree {
|
||||||
/**
|
/**
|
||||||
* 添加函数 例:添加弹出文字,像这个就可以使用core.addPop或core.plugin.addPop调用
|
* 添加函数 例:添加弹出文字,像这个就可以使用core.addPop或core.plugin.addPop调用
|
||||||
* @param px 弹出的横坐标
|
* @param px 弹出的横坐标
|
||||||
@ -142,6 +146,9 @@ interface PluginUis {
|
|||||||
/** 技能查看界面是否打开 */
|
/** 技能查看界面是否打开 */
|
||||||
readonly skillOpened: Ref<boolean>;
|
readonly skillOpened: Ref<boolean>;
|
||||||
|
|
||||||
|
/** 技能树界面是否打开 */
|
||||||
|
readonly skillTreeOpened: Ref<boolean>;
|
||||||
|
|
||||||
/** ui栈 */
|
/** ui栈 */
|
||||||
readonly uiStack: Ref<Component[]>;
|
readonly uiStack: Ref<Component[]>;
|
||||||
|
|
||||||
@ -201,11 +208,55 @@ interface PluginUse {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface SkillTree {
|
interface SkillTree {
|
||||||
|
skills: Record<Chapter, Skill[]>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取技能等级
|
* 获取技能等级
|
||||||
* @param skill 技能索引
|
* @param skill 技能索引
|
||||||
*/
|
*/
|
||||||
getSkillLevel(skill: number): number;
|
getSkillLevel(skill: number): number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据索引获取技能
|
||||||
|
* @param index 索引
|
||||||
|
*/
|
||||||
|
getSkillFromIndex(index: number): Skill;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取技能的消耗
|
||||||
|
* @param skill 技能
|
||||||
|
*/
|
||||||
|
getSkillConsume(skill: number): number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 升级技能
|
||||||
|
* @param skill 技能索引
|
||||||
|
*/
|
||||||
|
upgradeSkill(skill: number): boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存技能树等级
|
||||||
|
*/
|
||||||
|
saveSkillTree(): number[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加载技能树等级
|
||||||
|
* @param data 等级信息
|
||||||
|
*/
|
||||||
|
loadSkillTree(data: number[]): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
type Chapter = 'chapter1';
|
||||||
|
|
||||||
|
interface Skill {
|
||||||
|
index: number;
|
||||||
|
title: string;
|
||||||
|
desc: string[];
|
||||||
|
consume: string;
|
||||||
|
front: LocArr[];
|
||||||
|
loc: LocArr;
|
||||||
|
max: number;
|
||||||
|
effect: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
type Forward<T> = {
|
type Forward<T> = {
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { computed, ref } from 'vue';
|
import { computed, ref } from 'vue';
|
||||||
import desc from '../data/desc.json';
|
import desc from '../data/desc.json';
|
||||||
import { has } from '../plugin/utils';
|
import { has, splitText } from '../plugin/utils';
|
||||||
import Colomn from '../components/colomn.vue';
|
import Colomn from '../components/colomn.vue';
|
||||||
|
|
||||||
type DescKey = keyof typeof desc;
|
type DescKey = keyof typeof desc;
|
||||||
@ -30,17 +30,7 @@ function exit() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const content = computed(() => {
|
const content = computed(() => {
|
||||||
return desc[selected.value].desc
|
return splitText(desc[selected.value].desc);
|
||||||
.map((v, i, a) => {
|
|
||||||
if (/^\d+\./.test(v)) return `${' '.repeat(12)}${v}`;
|
|
||||||
else if (
|
|
||||||
(has(a[i - 1]) && v !== '<br>' && a[i - 1] === '<br>') ||
|
|
||||||
i === 0
|
|
||||||
) {
|
|
||||||
return `${' '.repeat(8)}${v}`;
|
|
||||||
} else return v;
|
|
||||||
})
|
|
||||||
.join('');
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -49,7 +49,7 @@ import {
|
|||||||
autoScale
|
autoScale
|
||||||
} from '../plugin/settings';
|
} from '../plugin/settings';
|
||||||
import settingInfo from '../data/settings.json';
|
import settingInfo from '../data/settings.json';
|
||||||
import { has } from '../plugin/utils';
|
import { has, splitText } from '../plugin/utils';
|
||||||
import Column from '../components/colomn.vue';
|
import Column from '../components/colomn.vue';
|
||||||
|
|
||||||
type Settings = typeof settingInfo;
|
type Settings = typeof settingInfo;
|
||||||
@ -57,17 +57,7 @@ type Settings = typeof settingInfo;
|
|||||||
const selected = ref<keyof Settings>('transition');
|
const selected = ref<keyof Settings>('transition');
|
||||||
|
|
||||||
const descText = computed(() => {
|
const descText = computed(() => {
|
||||||
return settingInfo[selected.value].desc
|
return splitText(settingInfo[selected.value].desc);
|
||||||
.map((v, i, a) => {
|
|
||||||
if (/^\d+\./.test(v)) return `${' '.repeat(12)}${v}`;
|
|
||||||
else if (
|
|
||||||
(has(a[i - 1]) && v !== '<br>' && a[i - 1] === '<br>') ||
|
|
||||||
i === 0
|
|
||||||
) {
|
|
||||||
return `${' '.repeat(8)}${v}`;
|
|
||||||
} else return v;
|
|
||||||
})
|
|
||||||
.join('');
|
|
||||||
});
|
});
|
||||||
|
|
||||||
function exit() {
|
function exit() {
|
||||||
|
@ -1,14 +1,334 @@
|
|||||||
<template>
|
<template>
|
||||||
<div id="skill-tree"></div>
|
<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-consume"
|
||||||
|
:style="{ color: consume <= mdef ? '#fff' : '#f44' }"
|
||||||
|
>升级花费:{{ consume }}</span
|
||||||
|
>
|
||||||
|
<a-divider dashed class="upgrade-divider"></a-divider>
|
||||||
|
<Scroll id="front-scroll" :no-scroll="true"
|
||||||
|
><div id="skill-front">
|
||||||
|
<span>前置技能</span>
|
||||||
|
<span
|
||||||
|
v-for="str of front"
|
||||||
|
:style="{
|
||||||
|
color: str.startsWith('a') ? '#fff' : '#f44'
|
||||||
|
}"
|
||||||
|
>{{ str.slice(1) }}</span
|
||||||
|
>
|
||||||
|
</div></Scroll
|
||||||
|
>
|
||||||
|
<a-divider dashed class="upgrade-divider"></a-divider>
|
||||||
|
<div id="skill-chapter">
|
||||||
|
<span class="button-text" @click="selectChapter(-1)"
|
||||||
|
><LeftOutlined
|
||||||
|
/></span>
|
||||||
|
|
||||||
|
<span>{{ chapterDict[chapter] }}</span>
|
||||||
|
|
||||||
|
<span class="button-text" @click="selectChapter(1)"
|
||||||
|
><RightOutlined
|
||||||
|
/></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref } from 'vue';
|
import { computed, onMounted, 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';
|
||||||
|
|
||||||
|
let canvas: HTMLCanvasElement;
|
||||||
|
let ctx: CanvasRenderingContext2D;
|
||||||
|
|
||||||
|
const selected = ref(0);
|
||||||
|
const chapter = ref<Chapter>('chapter1');
|
||||||
|
const update = ref(false);
|
||||||
|
|
||||||
|
const chapterDict = {
|
||||||
|
chapter1: '第一章'
|
||||||
|
};
|
||||||
|
|
||||||
|
const chapterList = Object.keys(core.plugin.skills) as Chapter[];
|
||||||
|
|
||||||
|
watch(selected, draw);
|
||||||
|
watch(update, () => (mdef.value = core.status.hero.mdef));
|
||||||
|
|
||||||
|
const mdef = ref(core.status.hero.mdef);
|
||||||
|
|
||||||
|
const skill = computed(() => {
|
||||||
|
update.value;
|
||||||
|
return core.getSkillFromIndex(selected.value);
|
||||||
|
});
|
||||||
|
|
||||||
|
const skills = computed(() => {
|
||||||
|
return core.plugin.skills[chapter.value];
|
||||||
|
});
|
||||||
|
|
||||||
|
const desc = computed(() => {
|
||||||
|
return eval(
|
||||||
|
'`' +
|
||||||
|
splitText(skill.value.desc).replace(/level(:\d+)?/g, (str, $1) => {
|
||||||
|
if ($1) return `core.getSkillLevel(${$1})`;
|
||||||
|
else return `core.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 `(core.getSkillLevel(${$1}) + ${v})`;
|
||||||
|
else
|
||||||
|
return `(core.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 `${core.getSkillLevel(v[0]) >= v[1] ? 'a' : 'b'}${v[1]}级 ${
|
||||||
|
skills.value[dict.value[v[0]]].title
|
||||||
|
}`;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
const consume = computed(() => {
|
||||||
|
update.value;
|
||||||
|
return core.getSkillConsume(selected.value);
|
||||||
|
});
|
||||||
|
|
||||||
|
const level = computed(() => {
|
||||||
|
update.value;
|
||||||
|
return core.getSkillLevel(selected.value);
|
||||||
|
});
|
||||||
|
|
||||||
|
function exit() {
|
||||||
|
core.plugin.skillTreeOpened.value = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
skills.value.forEach(v => {
|
||||||
|
const [x, y] = v.loc.map(v => v * 2 - 1);
|
||||||
|
// 技能连线
|
||||||
|
v.front.forEach(([skill]) => {
|
||||||
|
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 (core.getSkillLevel(s.index) === 0) ctx.strokeStyle = '#aaa';
|
||||||
|
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 = core.getSkillLevel(v.index);
|
||||||
|
// 技能图标
|
||||||
|
if (selected.value === v.index) ctx.strokeStyle = '#ff0';
|
||||||
|
else if (level === 0) ctx.strokeStyle = '#888';
|
||||||
|
else if (level === v.max) ctx.strokeStyle = '#F7FF68';
|
||||||
|
else ctx.strokeStyle = '#00FF69';
|
||||||
|
ctx.lineWidth = per * 0.03;
|
||||||
|
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);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
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 {
|
||||||
|
const success = core.upgradeSkill(skill.index);
|
||||||
|
if (!success) tip('error', '升级失败!');
|
||||||
|
else {
|
||||||
|
tip('success', '升级成功!');
|
||||||
|
update.value = !update.value;
|
||||||
|
core.status.route.push(`skill:${selected.value}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
canvas = document.getElementById('skill-canvas') as HTMLCanvasElement;
|
||||||
|
ctx = canvas.getContext('2d')!;
|
||||||
|
resize();
|
||||||
|
draw();
|
||||||
|
canvas.addEventListener('click', click);
|
||||||
|
});
|
||||||
|
|
||||||
|
function selectChapter(delta: number) {
|
||||||
|
const now = chapterList.indexOf(chapter.value);
|
||||||
|
const to = now + delta;
|
||||||
|
if (has(chapterList[to])) {
|
||||||
|
chapter.value = chapterList[to];
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
#skill-tree {
|
#skill-tree {
|
||||||
|
width: 90vh;
|
||||||
|
height: 90vh;
|
||||||
|
font-family: 'normal';
|
||||||
|
font-size: 2.8vh;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
#skill-title {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 4vh;
|
||||||
|
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 1vh 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#divider-split {
|
||||||
|
margin: 1vh 0 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#divider-vertical {
|
||||||
height: 100%;
|
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 1vh 0;
|
||||||
|
border-color: #ddd4;
|
||||||
|
}
|
||||||
|
|
||||||
|
#front-scroll {
|
||||||
|
width: 100%;
|
||||||
|
height: 39vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
#skill-front {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
Loading…
Reference in New Issue
Block a user