HumanBreak/packages-user/data-state/src/mechanism/skillTree.ts

440 lines
12 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

let levels: number[] = [];
export type Chapter = 'chapter1' | 'chapter2';
export interface Skill {
index: number;
title: string;
desc: string[];
consume: (level: number) => number;
front: [skill: number, level: number][];
loc: LocArr;
max: number;
effect: (level: number) => string[];
}
/**
* @type {Record<Chapter, Skill[]>}
*/
export const skills: Record<Chapter, Skill[]> = {
chapter1: [
{
index: 0,
title: '力量',
desc: ['力量就是根本可以通过智慧增加力量每级增加2点攻击。'],
consume: level => 10 * level + 10,
front: [],
loc: [1, 2],
max: 10,
effect: level => [`攻击 + ${level * 2}`]
},
{
index: 1,
title: '致命一击',
desc: ['爆发出全部力量攻击敌人每级增加5点额外攻击。'],
consume: level => 30 * level + 30,
front: [[0, 5]],
loc: [2, 1],
max: 10,
effect: level => [`额外攻击 + ${level * 5}`]
},
{
index: 2,
title: '断灭之刃',
desc: [
'<span style="color: gold">主动技能快捷键1</span>',
'开启后会在战斗时会额外增加一定量的攻击,但同时减少一定量的防御。'
],
consume: level => 200 * level + 400,
front: [[1, 5]],
loc: [4, 1],
max: 5,
effect: level => [`增加${level * 10}%攻击,减少${level * 10}%防御`]
},
{
index: 3,
title: '坚韧',
desc: ['由智慧转化出坚韧每级增加2点防御'],
consume: level => 10 * level + 10,
front: [],
loc: [1, 4],
max: 10,
effect: level => [`防御 + ${level * 2}`]
},
{
index: 4,
title: '回春',
desc: ['让智慧化为治愈之泉水每级增加1点生命回复'],
consume: level => 20 * level + 20,
front: [[3, 5]],
loc: [2, 5],
max: 25,
effect: level => [`生命回复 + ${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: level => 50 + level * 50,
front: [[3, 5]],
loc: [2, 3],
max: 10,
effect: level => [`防御 + ${level * 10}`]
},
{
index: 7,
title: '无上之盾',
desc: [
'<span style="color: #dd4">第一章终极技能</span>,战斗时智慧的 1/10 会充当等量护盾。'
],
consume: () => 2500,
front: [
[6, 10],
[5, 1],
[2, 2]
],
loc: [5, 3],
max: 1,
effect: () => [`战斗时智慧会充当护盾`]
}
],
chapter2: [
{
index: 8,
title: '锋利',
desc: ['让剑变得更加锋利每级使攻击增加1%buff式增加'],
consume: level => (level > 5 ? 50 * level ** 2 : 250 * level + 250),
front: [],
loc: [1, 2],
max: 15,
effect: level => [`攻击增加${level}%`]
},
{
index: 9,
title: '坚硬',
desc: ['让盾牌变得更加坚固每级使防御增加1%buff式增加'],
consume: level => (level > 5 ? 50 * level ** 2 : 250 * level + 250),
front: [],
loc: [1, 4],
max: 15,
effect: level => [`防御增加${level}%`]
},
{
index: 10,
title: '铸剑为盾',
desc: [
'<span style="color: gold">主动技能快捷键3</span>',
'减少一定的攻击,增加一定的防御'
],
consume: level => 1000 * level ** 2 + 1000,
front: [[9, 5]],
loc: [2, 5],
max: 5,
effect: level => [
`增加${level * 10}%的防御,减少${level * 10}%的攻击`
]
},
{
index: 11,
title: '魔法盾',
desc: ['为主角提供魔法防御每级增加100点魔法防御'],
consume: level => 5000 * level + 5000,
front: [
[8, 10],
[12, 10]
],
loc: [4, 1],
max: 10,
effect: level => [`魔法防御 + ${level * 100}`]
},
{
index: 12,
title: '聪慧',
desc: ['使主角变得更加聪明每级使绿宝石增加的智慧点上升5%'],
consume: level =>
level > 5 ? 100 * level ** 2 : 250 * level + 1250,
front: [
[8, 10],
[9, 10]
],
loc: [3, 3],
max: 20,
effect: level => [`增加${level * 5}%绿宝石效果`]
},
{
index: 13,
title: '治愈',
desc: ['使主角能够更好地回复生命每级使血瓶的加血量增加2%'],
consume: level =>
level > 5 ? 100 * level ** 2 : 250 * level + 1250,
front: [[10, 3]],
loc: [4, 5],
max: 10,
effect: level => [`增加${level * 2}%的血瓶回血量`]
},
{
index: 14,
title: '胜利之号',
desc: [
'<span style="color: #dd4">第二章终极技能</span>',
'勇士攻防增加10%buff式增加'
],
consume: () => 25000,
front: [
[13, 10],
[12, 10],
[11, 3]
],
loc: [5, 3],
max: 1,
effect: () => [`攻防增加10%`]
}
]
};
export function resetSkillLevel() {
levels = [];
}
export function getSkillFromIndex(index: number) {
for (const [, skill] of Object.entries(skills)) {
const s = skill.find(v => v.index === index);
if (s) return s;
}
}
/**
* 获取技能等级
*/
export function getSkillLevel(skill: number) {
levels[skill] ??= 0;
return levels[skill];
}
export function getSkillConsume(skill: number) {
const s = getSkillFromIndex(skill);
if (!s) return 0;
return s.consume(getSkillLevel(skill));
}
export function openTree() {
if (main.replayChecking) return;
Mota.require('@motajs/legacy-ui').mainUi.open('skillTree');
}
/**
* 能否升级某个技能
*/
export function canUpgrade(skill: number) {
const consume = getSkillConsume(skill);
if (consume > core.status.hero.mdef) return false;
const level = getSkillLevel(skill);
const s = getSkillFromIndex(skill);
if (level === s?.max) return false;
const front = s?.front ?? [];
for (const [skill, level] of front) {
if (getSkillLevel(skill) < level) return false;
}
return true;
}
/**
* 实际升级效果
* @param {number} skill
*/
export function upgradeSkill(skill: number) {
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: // 断灭之刃
HeroSkill.learnSkill(HeroSkill.Blade);
break;
case 3: // 坚韧 +2防御
core.status.hero.def += 2;
break;
case 4: // 回春 +1回复
core.status.hero.hpmax += 1;
break;
case 5: // 治愈之泉
core.setFlag('spring', true);
break;
case 6: // 坚固之盾 +10防御
core.status.hero.def += 10;
break;
case 7: // 无上之盾
core.setFlag('superSheild', true);
break;
case 8: // 锋利 +1%攻击
core.addBuff('atk', 0.01);
break;
case 9: // 锋利 +1%防御
core.addBuff('def', 0.01);
break;
case 10: // 铸剑为盾
HeroSkill.learnSkill(HeroSkill.Shield);
break;
case 11: // 魔法盾
core.status.hero.magicDef += 100;
break;
case 14:
core.addBuff('atk', 0.1);
core.addBuff('def', 0.1);
break;
}
const consume = getSkillConsume(skill);
core.status.hero.mdef -= consume;
levels[skill]++;
core.updateStatusBar();
return true;
}
export function saveSkillTree() {
return levels.slice();
}
export function loadSkillTree(data: number[]) {
levels = data ?? [];
}
export namespace HeroSkill {
export const enum Skill {
None,
/** 断灭之刃 */
Blade,
/** 铸剑为盾 */
Shield,
/** 跳跃 */
Jump
}
export const Blade = Skill.Blade;
export const Shield = Skill.Shield;
export const Jump = Skill.Jump;
const skillNameMap = new Map<Skill, string>([
[Skill.Blade, '断灭之刃'],
[Skill.Shield, '铸剑为盾'],
[Skill.Jump, '跳跃']
]);
const skillDesc = new Map<Skill, (level: number) => string>([
[
Skill.Blade,
level => `攻击上升 ${level * 10}%,防御下降 ${level * 10}%`
],
[
Skill.Shield,
level => `防御上升 ${level * 10}%,攻击下降 ${level * 10}%`
],
[Skill.Jump, () => `跳过前方障碍,或踢走面前的怪物`]
]);
interface SkillSave {
autoSkill: boolean;
learned: Skill[];
}
const learned = new Set<Skill>();
let autoSkill = true;
let enabled: Skill = Skill.None;
export function getLevel(skill: Skill = getEnabled()) {
switch (skill) {
case Blade:
return getSkillLevel(2);
case Jump:
return learned.has(Jump) ? 1 : 0;
case Shield:
return getSkillLevel(10);
}
return 0;
}
export function getSkillName(skill: Skill = getEnabled()) {
return skillNameMap.get(skill) ?? '未开启技能';
}
export function getSkillDesc(
skill: Skill = getEnabled(),
level: number = getLevel()
) {
return skillDesc.get(skill)?.(level) ?? '';
}
export function setAutoSkill(auto: boolean) {
autoSkill = auto;
}
export function getAutoSkill() {
return autoSkill;
}
export function learnedSkill(skill: Skill) {
return learned.has(skill);
}
export function learnSkill(skill: Skill) {
learned.add(skill);
}
export function forgetSkill(skill: Skill) {
learned.delete(skill);
}
export function clearSkill() {
learned.clear();
}
export function saveSkill(): SkillSave {
return { autoSkill, learned: [...learned] };
}
export function loadSkill(skills: SkillSave) {
learned.clear();
for (const skill of skills.learned) {
learned.add(skill);
}
autoSkill = skills.autoSkill;
}
export function getAll() {
return learned;
}
export function toggleSkill(skill: Skill) {
if (!learned.has(skill)) return;
if (enabled !== skill) enabled = skill;
else enabled = Skill.None;
}
export function enableSkill(skill: Skill) {
if (!learned.has(skill)) return;
enabled = skill;
}
export function disableSkill() {
enabled = Skill.None;
}
export function getEnabled() {
return enabled;
}
}