就搞了一个怪物伤害都这么麻烦

This commit is contained in:
枫谷剑仙 2021-05-27 16:12:24 +08:00
parent b7f51b1128
commit 2124420511
8 changed files with 171 additions and 62 deletions

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

View File

@ -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'}属性`, //词缀-属性
},
},
}

View File

@ -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)} &rArr;</>}
<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 </>}
&rArr; {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;

View File

@ -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 = [];

View File

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

View File

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

View File

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