diff --git a/languages/zh-CN.js b/languages/zh-CN.js index 9303c127..104818aa 100644 --- a/languages/zh-CN.js +++ b/languages/zh-CN.js @@ -81,14 +81,15 @@ reduce_damage: tp`${'condition'}受到的${'attrs'}伤害${'icon'}减少${'value'}`, power_up: tp`${'condition'}${'targets'}${'value'}${'reduceDamage'}${'addCombo'}${'followAttack'}`, henshin: tp`变身为${'card'}`, + void_poison: tp`消除${'poison'}时不会受到毒伤害`, }, power: { unknown: tp`[ 未知能力提升: ${'type'} ]`, scale_attributes: tp`${'orbs'}中${'min'}种属性同时攻击时${'stats'}${'bonus'}`, scale_attributes_bonus: tp`,每多1种${'bonus'},最大${'max'}种时${'stats_max'}`, - scale_combos: tp`${'min'}连击以上,${'stats'}${'bonus'}`, + scale_combos: tp`${'min'}连击以上时${'stats'}${'bonus'}`, scale_combos_bonus: tp`,每多1连击${'bonus'},最大${'max'}连击时${'stats_max'}`, - scale_match_attrs: tp`${'matches'}中${'min'}串匹配时,${'stats'}${'bonus'}`, + scale_match_attrs: tp`${'matches'}中${'min'}串匹配时${'stats'}${'bonus'}`, scale_match_attrs_bonus: tp`,每多1串${'bonus'},最大${'max'}串时${'stats_max'}`, scale_match_length: tp`${'in_once'}相连消除${'min'}个${'orbs'}时${'stats'}${'bonus'}`, scale_match_length_bonus: tp`,每多1个${'bonus'},最大${'max'}个时${'stats_max'}`, @@ -112,6 +113,8 @@ compo_type_card: tp`队伍中同时存在 ${'ids'} 时`, compo_type_series: tp`队员组成全为 ${'ids'} 合作时`, compo_type_evolution: tp`队员组成全为 ${'ids'} 进化时`, + + L_shape: tp`以L字形式消除5个${'orbs'}时`, }, position: { top: tp`上方第${'pos'}横行`, diff --git a/script-skill-parser.js b/script-skill-parser.js index b3e23d4e..613b542b 100644 --- a/script-skill-parser.js +++ b/script-skill-parser.js @@ -346,7 +346,6 @@ const SkillPowerUpKind = { ScaleMatchLength: 'scale-match-len', ScaleMatchAttrs: 'scale-match-attrs', ScaleCross: 'scale-cross', - ScaleAwakenings: 'scale-awakenings', ScaleStateKindCount: 'scale-state-kind-count', }; @@ -393,6 +392,7 @@ const SkillKinds = { Board7x6: "7x6-board", NoSkyfall: "no-skyfall", Henshin: "henshin", + VoidPoison: "void-poison", } function skillParser(skillId) @@ -521,6 +521,8 @@ const c = { useSkill: function () { return { useSkill: true }; }, multiplayer: function () { return { multiplayer: true }; }, prob: function (percent) { return { prob: percent }; }, + LShape: function (attrs) { return { LShape: { attrs: attrs } }; }, + heal: function (heal) { return { heal: { heal: heal } }; }, } const p = { @@ -566,7 +568,7 @@ const p = { return { kind: SkillPowerUpKind.ScaleCombos ,...this.scale(min, max, baseMul, bonusMul) }; }, scaleMatchLength: function (attrs, min, max, baseMul, bonusMul, matchAll = false) { - return { kind: SkillPowerUpKind.ScaleMatchLength, attrs: attrs, matchAll ,...this.scale(min, max, baseMul, bonusMul) }; + return { kind: SkillPowerUpKind.ScaleMatchLength, attrs: attrs, matchAll: matchAll ,...this.scale(min, max, baseMul, bonusMul) }; }, scaleMatchAttrs: function (matches, min, max, baseMul, bonusMul) { return { kind: SkillPowerUpKind.ScaleMatchAttrs, matches: matches ,...this.scale(min, max, baseMul, bonusMul) }; @@ -612,13 +614,13 @@ function generateOrbs(orbs, exclude, count) { function fixedOrbs() { return { kind: SkillKinds.FixedOrbs, generates: Array.from(arguments) }; } -function powerUp(attrs, types, value, condition, reduceDamageValue, addCombo, followAttack) { +function powerUp(attrs, types, value, condition, reduceDamageValue, additional) { if (value.kind === SkillPowerUpKind.Multiplier) { let hp = value.hp, atk = value.atk, rcv = value.rcv; if (hp === 1 && atk === 1 && rcv === 1 && !reduceDamage) return null; } - return { kind: SkillKinds.PowerUp, attrs: attrs, types: types, condition: condition, value: value, reduceDamage: reduceDamageValue, addCombo: addCombo, followAttack: followAttack }; + return { kind: SkillKinds.PowerUp, attrs: attrs, types: types, condition: condition, value: value, reduceDamage: reduceDamageValue, additional: additional}; } function counterAttack(attr, prob, value) { return { kind: SkillKinds.CounterAttack, attr: attr, prob: prob, value: value }; @@ -672,6 +674,7 @@ function leaderChange(type = 0) { return { kind: SkillKinds.LeaderChange, type: function board7x6() { return { kind: SkillKinds.Board7x6 }; } function noSkyfall() { return { kind: SkillKinds.NoSkyfall }; } function henshin(id) { return { kind: SkillKinds.Henshin, id: id }; } +function voidPoison() { return { kind: SkillKinds.VoidPoison }; } const parsers = { parser: (() => []), //这个用来解决代码提示的报错问题,不起实际作用 @@ -945,7 +948,7 @@ const parsers = { noSkyfall(), powerUp(flags(attrs), flags(types), p.mul({ hp, atk, rcv })), rPercent && reduceDamage(flags(rAttrs), v.percent(rPercent)) || null, - ]; + ].filter(Boolean); }, [164](attrs1, attrs2, attrs3, attrs4, min, atk, rcv, bonus) { const attrs = [attrs1, attrs2, attrs3, attrs4].filter(Boolean); @@ -981,17 +984,19 @@ const parsers = { { orbs: [attrs ?? 0], type: 'shape', positions: [row1, row2, row3, row4, row5].map(row=>flags(row)) } ); }, - [177](_0, _1, _2, _3, _4, remains, mul) { + [177](attrs, types, hp, atk, rcv, remains, mul) { return [ noSkyfall(), - powerUp(null, null, p.mul({ atk: mul }), c.remainOrbs(remains)) - ]; + (hp || atk || rcv) && powerUp(flags(attrs), flags(types), p.mul({ hp, atk, rcv })) || null, + mul && powerUp(null, null, p.mul({ atk: mul }), c.remainOrbs(remains)) || null + ].filter(Boolean); }, - [178](time, attrs, types, hp, atk, rcv) { + [178](time, attrs, types, hp, atk, rcv, attrs2, percent) { return [ fixedTime(time), - powerUp(flags(attrs), flags(types), p.mul({ hp, atk, rcv })) - ]; + (hp || atk || rcv) && powerUp(flags(attrs), flags(types), p.mul({ hp, atk, rcv })), + percent && reduceDamage(flags(attrs2), v.percent(percent)) || null, + ].filter(Boolean); }, [179](turns, value, percent, bind, awokenBind) { return [ @@ -1021,6 +1026,7 @@ const parsers = { powerUp(flags(attrs), flags(types), p.mul({ hp, atk, rcv })), ]; }, + [188](value) { return damageEnemy('single', 'fixed', v.constant(value)); }, @@ -1031,11 +1037,18 @@ const parsers = { autoPath(), ]; }, + [191](turns) { return activeTurns(turns, voidEnemyBuff(['damage-void'])); }, [192](attrs, len, mul, combo) { - return powerUp(null, null, p.scaleMatchLength(flags(attrs), len, len, [mul, 100], [0, 0], true), null, null, combo); + return powerUp(null, null, p.scaleMatchLength(flags(attrs), len, len, [mul, 100], [0, 0], true), null, null, [addCombo(combo)]); + }, + [193](attrs, atk, rcv, percent) { + return powerUp(null, null, p.mul([atk, rcv]), c.LShape(flags(attrs)), v.percent(percent)); + }, + [194](attrs, min, mul, combo) { + return powerUp(null, null, p.scaleAttrs(flags(attrs), min, min, [mul, 0], [0, 0]), null, null, [addCombo(combo)]); }, [195](percent) { return selfHarm(percent ? v.xHP(percent) : v.constantTo(1)); @@ -1043,6 +1056,12 @@ const parsers = { [196](matches) { return unbind(0,0,matches); }, + [197]() { + return voidPoison(); + }, + [198](heal, atk, percent, awokenBind) { + return powerUp(null, null, p.mul([atk, 0]), c.heal(heal), v.percent(percent), [unbind(0, awokenBind ?? 0)]); + }, [202](id) { return henshin(id); }, @@ -1628,7 +1647,7 @@ function renderSkill(skill, option = {}) break; } case SkillKinds.PowerUp: { - let attrs = skill.attrs, types = skill.types, condition = skill.condition, value = skill.value, reduceDamage = skill.reduceDamage, addCombo = skill.addCombo, followAttack = skill.followAttack; + let attrs = skill.attrs, types = skill.types, condition = skill.condition, value = skill.value, reduceDamage = skill.reduceDamage, additional = skill.additional; let targets = []; if (attrs?.filter(attr=> attr !== 5)?.length && !isEqual(attrs, Attributes.all())) targets.push(renderAttrs(attrs || [], {affix: true})); if (types?.length) targets.push(renderTypes(types || [], {affix: true})); @@ -1638,36 +1657,40 @@ function renderSkill(skill, option = {}) }; if (condition) dict.condition = renderCondition(condition); if (targets.length > 0) dict.targets = targets.nodeJoin(tsp.word.slight_pause()); + let subDocument = []; if (value){ if (attrs?.includes(5) && value.kind == SkillPowerUpKind.Multiplier) - { + { //如果属性有5,则是回复力 let _value = Object.assign({}, value); _value.rcv = value.atk; _value.atk = value.rcv; - console.log(_value) value = _value; } - dict.value = renderPowerUp(value); + if (value.kind == SkillPowerUpKind.Multiplier && Boolean(value.hp || value.atk || value.rcv) == false) + { + //不显示 value + }else + { + subDocument.push(renderPowerUp(value)); + } } if (reduceDamage) { - dict.reduceDamage = tsp.word.comma().ap(tsp.skill.reduce_damage({ + subDocument.push(tsp.skill.reduce_damage({ value: renderValue(reduceDamage, {percent: true}), icon: createIcon("reduce-damage"), })); } - if (addCombo) { - dict.addCombo = tsp.word.comma().ap(renderSkill({kind: SkillKinds.AddCombo, value: addCombo})); - } - if (followAttack) { - dict.followAttack = tsp.word.comma().ap(tsp.skill.follow_attack_fixed({ - value: renderValue(v.constant(followAttack)), - icon: createIcon("follow-attack"), - })); + if (additional?.length) { + for (let subSkill of additional) + { + subDocument.push(renderSkill(subSkill, option)); + } } + dict.value = subDocument.filter(Boolean).nodeJoin(tsp.word.comma()); frg.ap(tsp.skill.power_up(dict)); break; } - case SkillKinds.Henshin: { + case SkillKinds.Henshin: { //变身 let id = skill.id; const dom = cardN(id); dom.monDom.onclick = changeToIdInSkillDetail; @@ -1677,6 +1700,13 @@ function renderSkill(skill, option = {}) frg.ap(tsp.skill.henshin(dict)); break; } + case SkillKinds.VoidPoison: { //毒无效 + dict = { + poison: renderOrbs([7,8], {affix: true}) + } + frg.ap(tsp.skill.void_poison(dict)); + break; + } default: { console.log("未处理的技能类型",skill.kind, skill); frg.ap(skill.kind); @@ -1874,6 +1904,11 @@ function renderCondition(cond) { break; } } + } else if (cond.LShape) { + let dict = { + orbs: renderOrbs(cond.LShape.attrs, {affix: true}), + }; + frg.ap(tsp.cond.L_shape(dict)); } else { frg.ap(tsp.cond.unknown()); } @@ -2042,89 +2077,7 @@ function renderPowerUp(powerUp) { } return frg; } -/* - -function renderPowerUp(powerUp: SkillPowerUp) { - function renderStats(hp: number, atk: number, rcv: number, mul = true) { - const operator = mul ? <>× : <>+; - let list: Array<['hp' | 'atk' | 'rcv', number]> = [['hp', hp], ['atk', atk], ['rcv', rcv]]; - list = list.filter(([, value]) => value !== (mul ? 1 : 0)); - if (list.length === 0) return null; - - if (list.every(([, value]) => value === list[0][1])) { - return <> - {list.map(([name], i) => {i !== 0 && ', '}{renderStat(name)})} -  {operator} {formatNumber(list[0][1])} - ; - } else { - return <> - {list.map(([name, value], i) => ( - - {i !== 0 ? '; ' : ''} - {renderStat(name)} -  {operator} {formatNumber(value)} - - ))} - ; - } - } - switch (powerUp.kind) { - case SkillPowerUpKind.Multiplier: { - const { hp, atk, rcv } = powerUp as SkillPowerUp.Mul; - return renderStats(hp, atk, rcv); - } - case SkillPowerUpKind.ScaleAttributes: { - const { attrs, min, max, baseAtk, baseRcv, bonusAtk, bonusRcv } = powerUp as SkillPowerUp.ScaleAttrs; - return <> - ≥ {min} of [{renderAttrs(attrs)}] ⇒ {renderStats(1, baseAtk, baseRcv)} - {max !== min && <> for each ≤ {max} attributes: {renderStats(0, bonusAtk, bonusRcv, false)}} - ; - } - case SkillPowerUpKind.ScaleCombos: { - const { min, max, baseAtk, baseRcv, bonusAtk, bonusRcv } = powerUp as SkillPowerUp.Scale; - return <> - ≥ {min} combos ⇒ {renderStats(1, baseAtk, baseRcv)} - {max !== min && <> for each ≤ {max} combos: {renderStats(0, bonusAtk, bonusRcv, false)}} - ; - } - case SkillPowerUpKind.ScaleMatchAttrs: { - const { matches, min, max, baseAtk, baseRcv, bonusAtk, bonusRcv } = powerUp as SkillPowerUp.ScaleMultiAttrs; - return <> - ≥ {min} matches of [{matches.map((attrs, i) => - {i !== 0 && ', '}{renderAttrs(attrs)} - )}] ⇒ {renderStats(1, baseAtk, baseRcv)} - {max !== min && <> for each ≤ {max} matches: {renderStats(0, bonusAtk, bonusRcv, false)}} - ; - } - case SkillPowerUpKind.ScaleMatchLength: { - const { attrs, min, max, baseAtk, baseRcv, bonusAtk, bonusRcv } = powerUp as SkillPowerUp.ScaleAttrs; - return <> - ≥ {min} × {renderAttrs(attrs)} ⇒ {renderStats(1, baseAtk, baseRcv)} - {max !== min && <> for each ≤ {max} orbs: {renderStats(0, bonusAtk, bonusRcv, false)}} - ; - } - case SkillPowerUpKind.ScaleCross: { - const { crosses } = powerUp as SkillPowerUp.ScaleCross; - return crosses.map(({ single, attr, mul }, i) => - {i !== 0 && ', '} - {mul !== 1 && <>{renderStat('atk')} × {formatNumber(mul)} } - {single ? 'when' : 'for each'} cross of {renderAttrs(attr)} - ); - } - case SkillPowerUpKind.ScaleAwakenings: { - const { awakenings, value } = powerUp as SkillPowerUp.ScaleAwakenings; - return <> - {renderStat('atk')} × {formatNumber(value - 1)} for each {awakenings.map(id => - - )} - ; - } - default: - return <>[ unknown power up ]; - } -} -*/ function renderValue(_value, option = {}) { const frg = document.createDocumentFragment(); if (typeof localTranslating == "undefined") return frg;