import { Equip, Skills, Monster, Attribute, Player } from '@/config'; import { randonBootyEquip, deepCopy, replace, callReducPercent, callDmgReduc, callDmgPercent } from '@/tool'; import i18n from '@/config/i18n'; const { t } = i18n; export class BattleRole { attr: Attribute; actions: Skills.Skill[] = new Array(); passives: Skills.Skill[] = new Array(); commit; type: string; control: number = 0; //临时状态 action: Skills.ActionSkill | null = null; atk: number = 0; dmg: number = 0; baseDmg: number = 0; crit: boolean = false; extraAttr: Attribute = new Attribute(); shield: number = 0; skillPercent: number = 100; constructor(attr: Attribute, commit, type: string) { this.attr = attr; this.commit = commit; this.type = type; this.addSkill(attr.skill); //添加默认主动技能普通攻击 this.initTmp(); } initTmp = () => { this.action = null; this.atk = 0; this.dmg = 0; this.baseDmg = 0; this.crit = false; this.extraAttr = new Attribute(); this.extraAttr.hp = 0; this.extraAttr.critDmg = 0; this.shield = Math.ceil(this.shield * 0.9); this.skillPercent = 100; }; addSkill = (skillName, lv?) => { lv = lv || 1; const skills = createSkill(skillName, lv); skills.forEach((skill) => { const type = skill.type; if (type == Skills.skill_type_action) { this.actions.push(skill); //主动技能 } else if (type == Skills.skill_type_passive) { this.passives.push(skill); //被动技能 } }); }; onStartBattle = (target: BattleRole) => { //技能排序 this.actions.sort((a, b) => { return a.order - b.order; }); this.passives.sort((a, b) => { return a.order - b.order; }); //战斗开始前触发的技能 this.passives.forEach((skill) => { skill.beforeBattle(this, target); }); }; attack = (target: BattleRole) => { //选择使用的主动技能 this.actions.forEach((skill) => { skill.beforeAtk(this, target); }); //攻击前触发的被动技能 this.passives.forEach((skill) => { skill.beforeAtk(this, target); }); this.action?.use(this, target); //攻击后触发的被动技能 this.passives.forEach((skill) => { skill.afterAtk(this, target); }); //触发攻击目标的反制技能 target.onAttacked(this); }; onAttacked = (target: BattleRole) => { //触发反制技能 this.passives.forEach((skill) => { skill.onAtked(this, target); }); //初始化临时状态 this.initTmp(); }; battleLog = (log: string) => { this.commit('set_sys_info', { type: 'battle', msg: log }); }; addHp = (hp: number) => { if (hp < 0 && this.shield > 0) { if (this.shield > -1 * hp) { this.shield += hp; return; } else { hp += this.shield; this.shield = 0; } } if (this.type == 'player') { this.commit('add_player_curhp', hp); } else { this.attr.curHp += hp; } }; getBootys = (target: BattleRole) => { //战斗结束后触发的技能 this.passives.forEach((skill) => { skill.afterBattle(this, target); }); const equips = randonBootyEquip(target.attr); const coins = target.attr.coins; return { equips: equips, coins: coins }; }; isDeath = () => { return this.attr.curHp <= 0; }; /** * * @param skillPercent 技能伤害倍率 * @param target 被攻击目标 * @returns */ callDmg = (target: BattleRole) => { //被控制时无法攻击 if (this.control > 0) { const log = replace(t('skill.control.3'), [t(this.type), this.control]); this.battleLog(log); this.control--; return; } const attr = this.attr; const extra = this.extraAttr; const baseAtk = attr.baseAtk + extra.baseAtk; //基础攻击 const atkPercent = 1 + (attr.atkPercent + extra.atkPercent) / 100; //攻击加成 this.atk = baseAtk * atkPercent; //回合最终攻击力 const dmgPercent = callDmgPercent(attr.dmgPercent, extra.dmgPercent) / 100; //伤害加成 this.baseDmg = this.atk * (1 + dmgPercent) * (this.skillPercent / 100); //造成伤害 const crit = attr.crit + extra.crit - target.attr.critAvoid - target.extraAttr.critAvoid; //最终暴击率 this.crit = Math.random() < crit / 100; if (this.crit) { let critDmg = attr.critDmg + extra.critDmg - target.attr.critDmgReduc - target.extraAttr.critDmg; //目标最终承受暴击伤害 critDmg < 100 ? 100 : critDmg; //暴击伤害不低于100% this.baseDmg *= critDmg / 100; //暴击时目标承受伤害 } const reducPercent = callReducPercent(target.attr.def + target.extraAttr.def, target.attr.lv); //目标防御提供的减伤比例 const dmgReduc = callDmgReduc(target.attr.dmgReduc, target.extraAttr.dmgReduc); //目标伤害减免 const takeDmgPercent = (1 - reducPercent) * (1 - dmgReduc / 100); //目标承受伤害比例 const bloc = target.attr.bloc + target.extraAttr.bloc; //目标格挡值 this.dmg = Math.ceil(this.baseDmg * takeDmgPercent - bloc); //目标承受伤害 }; } export const createBattleRole = (player: Player, monster: Monster, commit) => { const playerRole = new BattleRole(player.attribute, commit, 'player'); const palyerEquips = [player.weapon, player.armor, player.neck, player.ring, player.jewelry, player.pants, player.shoes, player.bracers]; palyerEquips.forEach((equip) => { equip && playerRole.addSkill(equip.base.skill, equip.lv); }); monster = deepCopy(monster); monster.curHp = monster.hp; const monsterRole = new BattleRole(monster, commit, monster.type); return { player: playerRole, monster: monsterRole }; }; /** * 初始化装备技能 * @param equip 装备 * @returns */ export const createEquipSkill = (equip): Skills.Skill[] => { if (!equip) { return []; } return createSkill(equip.base.skill, equip.lv); }; /** * 初始化技能 * @param skillName 技能名称 * @returns */ export const createSkill = (skillName, lv): Skills.Skill[] => { const skills: Skills.Skill[] = new Array(); if (!skillName) { return skills; } const names: string[] = skillName.split(','); names.forEach((name) => { const clazz = Skills[name]; if (clazz) { const skill: Skills.Skill = new clazz(); skill.lv = lv; skills.push(skill); } }); return skills; };