就搞了一个怪物伤害都这么麻烦
This commit is contained in:
parent
b7f51b1128
commit
2124420511
BIN
images/attrs.png
BIN
images/attrs.png
Binary file not shown.
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 15 KiB |
Binary file not shown.
Before Width: | Height: | Size: 73 KiB After Width: | Height: | Size: 75 KiB |
|
@ -3,12 +3,14 @@ const localTranslating = {
|
|||
skill_parse: {
|
||||
skill: {
|
||||
unknown: tp`未知的技能类型:${'type'}`, //type
|
||||
active_turns: tp`${'active'},效果 ${'turns'} 回合`, //turns, active
|
||||
random_skills: tp`随机发动以下技能:${'skill-list'}`, //skill-list
|
||||
active_turns: tp`${'actionSkill'},效果 ${'turns'} 回合`, //turns, actionSkill
|
||||
random_skills: tp`随机发动以下技能:${'skills'}`, //skills
|
||||
damage_enemy: tp`对${'target'}造成${'damage'}的${'attr'}伤害`, //
|
||||
delay: tp`${'icon'}延迟敌人的攻击`, //icon
|
||||
mass_attack: tp`${'icon'}所有攻击变为全体攻击`,
|
||||
leader_change: tp`${'icon'}将自身换为队长,再次使用则换回来`,
|
||||
no_skyfall: tp`${'icon'}天降的宝珠不会消除`,
|
||||
hp_modify: tp`${'icon'}回复 ${'belong_to'}${'value'} 的 ${'stats'}`,
|
||||
heal: tp`${'icon'}回复 ${'belong_to'}${'value'} 的 ${'stats'}`,
|
||||
defense_break: tp`${'icon'}敌方的防御力减少 ${'value'}`,
|
||||
poison: tp`${'icon'}使${'target'}全体中毒,每回合损失${'belong_to'} ${'value'} 的 ${'stats'}`,
|
||||
|
@ -16,7 +18,7 @@ const localTranslating = {
|
|||
follow_attack: tp`${'icon'}消除宝珠的回合,以${'belong_to'}${'value'}的伤害追打${'target'}(计算防御力)`,//(valueElement)=> [`消除宝珠的回合,以`, valueElement, `的伤害追打敌人`],
|
||||
auto_heal: tp`${'icon'}消除宝珠的回合,回复${'belong_to'}${'value'}的 ${'stats'}`,
|
||||
ctw: (valueElement)=> [valueElement, `内时间停止,可以任意移动宝珠`],
|
||||
gravity: tp`造成${'target'}${'value'}的伤害`,//(valueElement)=> [`造成敌方`, valueElement, `的伤害`],
|
||||
gravity: tp`${'icon'}造成${'target'}${'value'}的伤害`,//(valueElement)=> [`造成敌方`, valueElement, `的伤害`],
|
||||
resolve: (stats, valueElement, probability)=> [probability ? `有${(probability* 100).keepCounts()}%的几率`:'',`如当前`,valueElement,`,受到单一次致命攻击时,将会以1点 HP 生还`],
|
||||
resolve: (stats, valueElement, probability)=> [`如`, stats, `≧` , valueElement, probability<100 ? `,有${probability}%的几率`:'',`受到单一次致命攻击时,将会以1点 HP 生还`],
|
||||
},
|
||||
|
@ -27,23 +29,56 @@ const localTranslating = {
|
|||
mul_times: tp`×${'value'}倍`,
|
||||
mul_of_percent: tp`${'stats'}的${'value'}%`,
|
||||
mul_of_times: tp`${'stats'}×${'value'}倍`,
|
||||
hp_scale: tp`${'hp'}为100%时${'min'},${'hp'}为1时${'max'}`,
|
||||
},
|
||||
attrs: {
|
||||
[0]: tp`${'icon'}火`,
|
||||
[1]: tp`${'icon'}水`,
|
||||
[2]: tp`${'icon'}木`,
|
||||
[3]: tp`${'icon'}光`,
|
||||
[4]: tp`${'icon'}暗`,
|
||||
[5]: tp`${'icon'}回复`,
|
||||
[6]: tp`${'icon'}空`,
|
||||
self: tp`${'icon'}自身属性`,
|
||||
fixed: tp`${'icon'}无视防御固定`,
|
||||
},
|
||||
orbs: {
|
||||
[0]: tp`${'icon'}火`,
|
||||
[1]: tp`${'icon'}水`,
|
||||
[2]: tp`${'icon'}木`,
|
||||
[3]: tp`${'icon'}光`,
|
||||
[4]: tp`${'icon'}暗`,
|
||||
[5]: tp`${'icon'}回复`,
|
||||
[6]: tp`${'icon'}干扰`,
|
||||
[7]: tp`${'icon'}毒`,
|
||||
[8]: tp`${'icon'}剧毒`,
|
||||
[9]: tp`${'icon'}炸弹`,
|
||||
},
|
||||
target: {
|
||||
self: tp`发动者自身`,
|
||||
enemy: tp`敌人`,
|
||||
team: tp`队伍`,
|
||||
enemy_all: tp`敌方全体`,
|
||||
enemy_one: tp`敌方1体`,
|
||||
enemy_attr: tp`${'attr'}属性敌人`,
|
||||
},
|
||||
stats: {
|
||||
unknown: tp`[ 未知状态: ${'type'}]`, //type
|
||||
maxhp: tp`最大HP`,
|
||||
hp: tp`HP`,
|
||||
hp: tp`当前HP`,
|
||||
atk: tp`攻击力`,
|
||||
rcv: tp`回复力`,
|
||||
teamatk: tp`队伍攻击力`,
|
||||
teamhp: tp`队伍总HP`,
|
||||
teamatk: tp`队伍${'attrs'}总攻击力`,
|
||||
teamrcv: tp`队伍回复力`,
|
||||
},
|
||||
unit: {
|
||||
seconds : tp`秒`,
|
||||
seconds: tp`秒`,
|
||||
point: tp`点`,
|
||||
},
|
||||
word: {
|
||||
slight_pause: tp`、`, //顿号
|
||||
affix_attr: tp`${'cotent'}属性`, //词缀-属性
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
|
@ -5,9 +5,9 @@ function tp(strings, ...keys) {
|
|||
let fragment = document.createDocumentFragment();
|
||||
fragment.appendChild(document.createTextNode(strings[0]));
|
||||
//let result = [strings[0]];
|
||||
keys.forEach(function(key, i) {
|
||||
keys.forEach(function(key, i, arr) {
|
||||
let value = Number.isInteger(key) ? values[key] : dict[key];
|
||||
if (typeof value == "string" || typeof value == "number")
|
||||
if (!(value instanceof Node))
|
||||
{
|
||||
value = document.createTextNode(value);
|
||||
}
|
||||
|
@ -17,8 +17,7 @@ function tp(strings, ...keys) {
|
|||
}else
|
||||
{
|
||||
try{
|
||||
//console.log(value);
|
||||
fragment.appendChild(value);
|
||||
fragment.appendChild(arr.lastIndexOf(key) == i ? value : value.cloneNode(true));
|
||||
}catch(e)
|
||||
{
|
||||
console.log(value, e);
|
||||
|
@ -98,6 +97,7 @@ const SkillValueKind = {
|
|||
xRCV: 'mul-rcv',
|
||||
RandomATK: 'random-atk',
|
||||
HPScale: 'hp-scale',
|
||||
xTeamHP: 'mul-team-hp',
|
||||
xTeamATK: 'mul-team-atk',
|
||||
xTeamRCV: 'mul-team-rcv',
|
||||
xAwakenings: 'mul-awakenings',
|
||||
|
@ -212,6 +212,9 @@ const v = {
|
|||
hpScale: function(min, max, scale) {
|
||||
return { kind: SkillValueKind.HPScale, min: (min / 100) || 1, max: (max / 100) || 1, scale: (scale / 100) || 1 };
|
||||
},
|
||||
xTeamHP: function(value) {
|
||||
return { kind: SkillValueKind.xTeamHP, value: (value / 100) || 1 };
|
||||
},
|
||||
xTeamATK: function(attrs, value) {
|
||||
return { kind: SkillValueKind.xTeamATK, attrs: attrs, value: (value / 100) || 1 };
|
||||
},
|
||||
|
@ -568,6 +571,8 @@ const parsers = {
|
|||
[141](count, to, exclude) { return changeOrbs({ kind: 'gen', to: flags(to), exclude: flags(exclude), count }); },
|
||||
[142](turns, attr) { return activeTurns(turns, changeAttr('self', attr)); },
|
||||
|
||||
[143](mul, dmgAttr) { return damageEnemy('all', dmgAttr || 0, v.xTeamHP(mul)); },
|
||||
|
||||
[144](teamAttrs, mul, single, dmgAttr) { return damageEnemy(single ? 'single' : 'all', dmgAttr, v.xTeamATK(flags(teamAttrs), mul)); },
|
||||
[145](mul) { return heal(v.xTeamRCV(mul)); },
|
||||
[146](turns) { return skillBoost(turns); },
|
||||
|
@ -679,22 +684,34 @@ const parsers = {
|
|||
},
|
||||
};
|
||||
|
||||
//将内容添加到代码片段
|
||||
DocumentFragment.prototype.ap = function(arg)
|
||||
{
|
||||
if (Array.isArray(arg))
|
||||
if (Array.isArray(arg)) //数组,递归自身
|
||||
{
|
||||
arg.forEach(element=>this.ap(element));
|
||||
}
|
||||
else if (typeof arg == "string" || typeof arg == "number")
|
||||
else if (arg instanceof Node) //属于Node的直接添加
|
||||
{
|
||||
return this.appendChild(document.createTextNode(arg));
|
||||
this.appendChild(arg);
|
||||
}
|
||||
else
|
||||
else //其他内容的转换为文字添加
|
||||
{
|
||||
return this.appendChild(arg);
|
||||
this.appendChild(document.createTextNode(arg));
|
||||
}
|
||||
}
|
||||
|
||||
//将数组和分隔符添加到一个代码片段,类似join
|
||||
Array.prototype.nodeJoin = function(separator)
|
||||
{
|
||||
const frg = document.createDocumentFragment();
|
||||
this.forEach((item, idx, arr)=>{
|
||||
frg.ap(item);
|
||||
if (idx < (arr.length - 1))
|
||||
frg.ap(separator instanceof Node ? separator.cloneNode(true) : separator);
|
||||
});
|
||||
return frg;
|
||||
}
|
||||
//按住Ctrl点击技能在控制台输出技能的对象
|
||||
function showParsedSkill(event) {
|
||||
if (event.ctrlKey) {
|
||||
|
@ -702,7 +719,7 @@ function showParsedSkill(event) {
|
|||
}
|
||||
}
|
||||
|
||||
function renderSkills(skills)
|
||||
function renderSkillEntry(skills)
|
||||
{
|
||||
const ul = document.createElement("ul");
|
||||
ul.className = "card-skill-list";
|
||||
|
@ -738,22 +755,24 @@ function renderSkill(skill, option = {})
|
|||
break;
|
||||
}
|
||||
case SkillKinds.ActiveTurns: { //有回合的行动
|
||||
let turns = skill.turns, actionSkill = skill.skill;
|
||||
dict = {
|
||||
turns: skill.turns,
|
||||
active: renderSkill(skill.skill, { forTurns: true }),
|
||||
turns: turns,
|
||||
actionSkill: actionSkill,
|
||||
};
|
||||
frg.ap(tsp.skill.active_turns(dict));
|
||||
break;
|
||||
}
|
||||
case SkillKinds.RandomSkills: { //随机技能
|
||||
let skills = skill.skills;
|
||||
const ul = document.createElement("ul");
|
||||
ul.className = "random-active-skill";
|
||||
skill.skills.forEach(subSkills=>{
|
||||
skills.forEach(subSkills=>{
|
||||
const li = ul.appendChild(document.createElement("li"));
|
||||
li.appendChild(renderSkills(subSkills));
|
||||
li.appendChild(renderSkillEntry(subSkills));
|
||||
});
|
||||
dict = {
|
||||
"skill-list": ul,
|
||||
skills: ul,
|
||||
};
|
||||
frg.ap(tsp.skill.random_skills(dict));
|
||||
break;
|
||||
|
@ -793,7 +812,7 @@ function renderSkill(skill, option = {})
|
|||
value: renderValue(skill.value, {percent: option.forTurns}),
|
||||
stats: tsp.stats.hp(),
|
||||
};
|
||||
frg.ap(tsp.skill.heal(dict));
|
||||
frg.ap(tsp.skill.hp_modify(dict));
|
||||
break;
|
||||
}
|
||||
case SkillKinds.Heal: { //主动回血buff
|
||||
|
@ -872,6 +891,19 @@ function renderSkill(skill, option = {})
|
|||
frg.ap(tsp.skill.resolve(renderStat('hp'), renderValue(skill.min, { percent:true }), skill.condition.probability));
|
||||
break;
|
||||
}
|
||||
|
||||
case SkillKinds.DamageEnemy: {
|
||||
let attr = skill.attr, target = skill.target, selfHP = skill.selfHP, damage = skill.damage;
|
||||
if (attr == null) break; //没有属性时,编号为0的空技能
|
||||
dict = {
|
||||
icon: attr === 'fixed' ? createIcon("damage-enemy-fixed") : createIcon("damage-enemy"),
|
||||
target: target === 'all' ? tsp.target.enemy_all() : target === 'single' ? tsp.target.enemy_one() : tsp.target.enemy_attr({attr: renderAttrs(target)}),
|
||||
damage: renderValue(damage, {unit: tsp.unit.point}),
|
||||
attr: renderAttrs(attr, {affix: (attr === 'self' || attr === 'fixed') ? false : true})
|
||||
};
|
||||
frg.ap(tsp.skill.damage_enemy(dict));
|
||||
break;
|
||||
}
|
||||
/*
|
||||
|
||||
case SkillKinds.BoardChange: {
|
||||
|
@ -929,25 +961,6 @@ function renderSkill(skill, option = {})
|
|||
return <span className="CardSkill-skill">7x6 board</span>;
|
||||
}
|
||||
|
||||
case SkillKinds.DamageEnemy: {
|
||||
const { attr, target, selfHP, damage } = skill as Skill.DamageEnemy;
|
||||
return (
|
||||
<span className="CardSkill-skill">
|
||||
{!!selfHP && <>HP = {renderValue(selfHP)} ⇒</>}
|
||||
|
||||
<Asset assetId="skill-attack" className="CardSkill-icon" />
|
||||
|
||||
{target === 'all' && <Asset assetId="status-mass-attack" className="CardSkill-icon" title="All enemies" />}
|
||||
{target === 'single' && <>single enemy </>}
|
||||
{typeof target === 'number' && <>{renderAttrs(target)} enemies </>}
|
||||
|
||||
⇒ {renderValue(damage)}
|
||||
{attr === 'fixed' && <Asset assetId="status-def-break" className="CardSkill-icon" title="Fixed damage" />}
|
||||
{typeof attr === 'number' && renderAttrs(attr)}
|
||||
|
||||
</span>
|
||||
);
|
||||
}
|
||||
case SkillKinds.Vampire: {
|
||||
const { attr, damage, heal } = skill as Skill.Vampire;
|
||||
return (
|
||||
|
@ -1176,12 +1189,12 @@ function renderSkill(skill, option = {})
|
|||
return frg;
|
||||
};
|
||||
|
||||
function renderStat(stat) {
|
||||
function renderStat(stat, option) {
|
||||
const frg = document.createDocumentFragment();
|
||||
if (typeof localTranslating == "undefined") return frg;
|
||||
const tspt = localTranslating.skill_parse.stats;
|
||||
if (tspt[stat])
|
||||
frg.ap(tspt[stat]());
|
||||
frg.ap(tspt[stat](option));
|
||||
else
|
||||
{
|
||||
console.log("未知状态类型",stat);
|
||||
|
@ -1189,16 +1202,25 @@ function renderStat(stat) {
|
|||
}
|
||||
return frg;
|
||||
}
|
||||
/*
|
||||
function renderAttrs(attrs: Attributes | Attributes[]) {
|
||||
|
||||
function renderAttrs(attrs, option = {}) {
|
||||
if (!Array.isArray(attrs))
|
||||
attrs = [attrs];
|
||||
return attrs.map(attr => {
|
||||
if (attr >= Attributes.Heart)
|
||||
return <Asset assetId={`orb-${attr}`} key={attr} className="CardSkill-icon" />;
|
||||
return <Asset assetId={`attr-${attr}`} key={attr} className="CardSkill-icon" />;
|
||||
});
|
||||
attrs = [attrs || 0];
|
||||
const frg = document.createDocumentFragment();
|
||||
if (typeof localTranslating == "undefined") return frg;
|
||||
|
||||
const tsp = localTranslating.skill_parse;
|
||||
const contentFrg = attrs.map(attr => {
|
||||
const icon = document.createElement("icon");
|
||||
icon.className = "attr";
|
||||
icon.setAttribute("data-attr-icon",attr);
|
||||
return tsp.attrs[attr]({icon: icon});
|
||||
})
|
||||
.nodeJoin(tsp.word.slight_pause());
|
||||
frg.ap(option.affix ? tsp.word.affix_attr({cotent: contentFrg}) : contentFrg);
|
||||
return frg;
|
||||
}
|
||||
/*
|
||||
|
||||
function renderOrbs(attrs: Attributes | Attributes[]) {
|
||||
if (!Array.isArray(attrs))
|
||||
|
@ -1396,6 +1418,19 @@ function renderValue(_value, option = {}) {
|
|||
);
|
||||
break;
|
||||
}
|
||||
case SkillValueKind.xTeamHP: {
|
||||
let value = _value.value;
|
||||
dict = {
|
||||
value: option.percent ? (value * 100).keepCounts(od,os) : value.keepCounts(od,os),
|
||||
stats: renderStat('teamhp'),
|
||||
};
|
||||
frg.ap(
|
||||
option.percent ?
|
||||
tspv.mul_of_percent(dict) :
|
||||
tspv.mul_of_times(dict)
|
||||
);
|
||||
break;
|
||||
}
|
||||
case SkillValueKind.xTeamRCV: {
|
||||
dict = {
|
||||
value: option.percent ? (_value.value * 100).keepCounts(od,os) : _value.value.keepCounts(od,os),
|
||||
|
@ -1409,9 +1444,10 @@ function renderValue(_value, option = {}) {
|
|||
break;
|
||||
}
|
||||
case SkillValueKind.xTeamATK: {
|
||||
let attrs = _value.attrs, value = _value.value;
|
||||
dict = {
|
||||
value: option.percent ? (_value.value * 100).keepCounts(od,os) : _value.value.keepCounts(od,os),
|
||||
stats: renderStat('teamatk'),
|
||||
value: option.percent ? (value * 100).keepCounts(od,os) : value.keepCounts(od,os),
|
||||
stats: renderStat('teamatk', {attrs: renderAttrs(attrs, {affix: true})}),
|
||||
};
|
||||
frg.ap(
|
||||
option.percent ?
|
||||
|
@ -1420,6 +1456,17 @@ function renderValue(_value, option = {}) {
|
|||
);
|
||||
break;
|
||||
}
|
||||
case SkillValueKind.HPScale: {
|
||||
let min = _value.min, max = _value.max;
|
||||
dict = {
|
||||
min: tspv.mul_of_times({value: min.keepCounts(od,os), stats:renderStat('atk')}),
|
||||
max: tspv.mul_of_times({value: max.keepCounts(od,os), stats:renderStat('atk')}),
|
||||
hp: renderStat('hp'),
|
||||
};
|
||||
|
||||
frg.ap(tspv.hp_scale(dict));
|
||||
break;
|
||||
}
|
||||
/*
|
||||
case SkillValueKind.Percent: {
|
||||
const { value } = _value as SkillValue.Simple;
|
||||
|
|
|
@ -51,16 +51,17 @@ Number.prototype.prefixInteger = function(length, useGrouping = false) {
|
|||
useGrouping: useGrouping,
|
||||
minimumIntegerDigits: length
|
||||
});
|
||||
}
|
||||
//最多保留N位小数,不留0
|
||||
Number.prototype.keepCounts = function(decimalDigits = 2, plusSign = false)
|
||||
{
|
||||
return (plusSign && this > 0 ? '+' : '') + Number(this.toFixed(decimalDigits)).toString();
|
||||
}
|
||||
//大数字缩短长度,默认返回本地定义字符串
|
||||
Number.prototype.bigNumberToString = function() {
|
||||
return this.toLocaleString();
|
||||
}
|
||||
//最多保留N位小数,不留0
|
||||
Number.prototype.keepCounts = function(decimalDigits = 2, plusSign = false)
|
||||
{
|
||||
let newNumber = Number(this.toFixed(decimalDigits));
|
||||
return (plusSign && this > 0 ? '+' : '') + newNumber.bigNumberToString();
|
||||
}
|
||||
//将二进制flag转为数组
|
||||
function flags(num) {
|
||||
const arr = [];
|
||||
|
|
|
@ -2925,7 +2925,7 @@ function editBoxChangeMonId(id) {
|
|||
skillDetailOriginal.innerHTML = "";
|
||||
skillDetailOriginal.appendChild(parseSkillDescription(activeskill));
|
||||
skillDetailParsed.innerHTML = "";
|
||||
skillDetailParsed.appendChild(renderSkills(skillParser(card.activeSkillId)));
|
||||
skillDetailParsed.appendChild(renderSkillEntry(skillParser(card.activeSkillId)));
|
||||
|
||||
const t_maxLevel = card.overlay || card.types.includes(15) ? 1 : activeskill.maxLevel; //遇到不能升技的,最大等级强制为1
|
||||
skillLevel.max = t_maxLevel;
|
||||
|
@ -2951,7 +2951,7 @@ function editBoxChangeMonId(id) {
|
|||
lskillDetailOriginal.innerHTML = "";
|
||||
lskillDetailOriginal.appendChild(parseSkillDescription(leaderSkill));
|
||||
lskillDetailParsed.innerHTML = "";
|
||||
lskillDetailParsed.appendChild(renderSkills(skillParser(card.leaderSkillId)));
|
||||
lskillDetailParsed.appendChild(renderSkillEntry(skillParser(card.leaderSkillId)));
|
||||
|
||||
rowLederSkill.appendChild(fragment);
|
||||
|
||||
|
|
|
@ -948,12 +948,20 @@
|
|||
background-image: url(images/attrs.png);
|
||||
background-position-y:calc(32px);
|
||||
background-repeat: no-repeat;
|
||||
vertical-align: bottom;
|
||||
}
|
||||
.attr[data-attr-icon='any']
|
||||
.attr[data-attr-icon='any'],
|
||||
.attr[data-attr-icon='self']
|
||||
{
|
||||
background-position-x: -32px;
|
||||
background-position-y:calc(-32px * 0);
|
||||
}
|
||||
.attr[data-attr-icon='fixed']
|
||||
{
|
||||
background-position-x: -32px;
|
||||
background-position-y:calc(-32px * 1);
|
||||
}
|
||||
|
||||
.attr[data-attr-icon='-1']
|
||||
{
|
||||
width: auto;
|
||||
|
|
20
style.css
20
style.css
|
@ -28,6 +28,14 @@
|
|||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
@keyframes gravity-animate{
|
||||
from {
|
||||
transform: scaley(1);
|
||||
}
|
||||
to {
|
||||
transform: scaley(0.5);
|
||||
}
|
||||
}
|
||||
body{
|
||||
--head-block-width: 108px;
|
||||
--head-block-height: 108px;
|
||||
|
@ -3006,7 +3014,7 @@ table .orb-icon
|
|||
{
|
||||
vertical-align: bottom;
|
||||
transform: scale(0.75);
|
||||
margin: -4px;
|
||||
/*margin: -4px;*/
|
||||
position: relative;
|
||||
}
|
||||
.icon-skill.status-incr::after,
|
||||
|
@ -3120,7 +3128,17 @@ table .orb-icon
|
|||
animation: rotate-animate 6s infinite linear;
|
||||
background-position-x:calc(-36px * 2);
|
||||
}
|
||||
.icon-skill[data-icon-type="gravity"]
|
||||
{
|
||||
animation: gravity-animate 1s infinite;
|
||||
transform-origin: bottom center;
|
||||
background-position-y:calc(-36px * 14);
|
||||
}
|
||||
.icon-skill[data-icon-type="resolve"]
|
||||
{
|
||||
background-position-y:calc(-36px * 15);
|
||||
}
|
||||
.icon-skill[data-icon-type="damage-enemy-fixed"]
|
||||
{
|
||||
background-position-y:calc(-36px * 16);
|
||||
}
|
Loading…
Reference in New Issue