import { prop } from '@typegoose/typegoose'; import { HERO_CE_RATIO, getAtrrNameById, CE_CONST, HERO_SUB_ATTR_RATIO, ABI_TYPE_MAIN } from '../../consts'; import { reduceCe } from '../../pubUtils/util'; // hero表内属性基础格式 export class CeAttrData { @prop({ required: true }) id: number = 0; @prop({ required: true }) base: number = 0; @prop({ required: true }) ratioUp: number = 0; @prop({ required: true }) fixUp: number = 0; @prop({ required: true }) equipUp: number = 0; constructor(id: number) { this.id = id; } } // role表属性格式 export class CeAttrDataRole { @prop({ required: true }) id: number = 0; @prop({ required: true }) ratioUp: number = 0; @prop({ required: true }) fixUp: number = 0; constructor(id: number) { this.id = id; } } // 主属性 export class MainAttrNumber { hp: number = 0; atk: number = 0; def: number = 0; mdef: number = 0; constructor(attr: Attribute) { if(attr.hp) this.hp = attr.hp; if(attr.atk) this.atk = attr.atk; if(attr.def) this.def = attr.def; if(attr.mdef) this.mdef = attr.mdef; } } export class Attribute { @prop({ required: false }) hp: number = 0; @prop({ required: false }) atk: number = 0; @prop({ required: false }) def: number = 0; @prop({ required: false }) mdef: number = 0; @prop({ required: false }) speed: number = 0; @prop({ required: false }) hit: number = 0; @prop({ required: false }) cri: number = 0; @prop({ required: false }) flee: number = 0; @prop({ required: false }) antCri: number = 0; @prop({ required: false }) damageIncrease: number = 0; @prop({ required: false }) damageDecrease: number = 0; @prop({ required: false }) defIngnore: number = 0; @prop({ required: false }) bloodSuck: number = 0; @prop({ required: false }) ap: number = 0; @prop({ required: false }) damageCri: number = 0; @prop({ required: false }) ce?: number = 0; setByDbData(roleAttrs: CeAttrDataRole[], heroAttrs: CeAttrData[]) { for(let { id, fixUp: roleFix, ratioUp: roleRatio } of roleAttrs) { let attrName = getAtrrNameById(id); let heroAttr = heroAttrs.find(heroAttr => heroAttr.id == id); if(heroAttr) { let { fixUp: heroFix, base: heroBase, ratioUp: heroRatio, equipUp: heroEquip } = heroAttr; let value = this.calAttrValue(roleFix, roleRatio, heroBase, heroFix, heroRatio, heroEquip); if(attrName in this) this[attrName] = value; } else { let value = this.calAttrValue(roleFix, roleRatio, 0, 0, 0, 0); if(attrName in this) this[attrName] = value; } } for(let { id, base: heroBase, fixUp: heroFix, ratioUp: heroRatio, equipUp: heroEquip } of heroAttrs) { let attrName = getAtrrNameById(id); let roleAttr = roleAttrs.find(roleAttr => roleAttr.id == id); if(!roleAttr) { let value = this.calAttrValue(0, 0, heroBase, heroFix, heroRatio, heroEquip); if(attrName in this) this[attrName] = value; } } } setByWarJson( attributes: {id: number, val: number}[], ratio: number = 1) { for(let {id, val} of attributes) { let attrName = getAtrrNameById(id); if(ABI_TYPE_MAIN.includes(id)) { if(attrName in this) this[attrName] = Math.floor(val * ratio * HERO_CE_RATIO * HERO_CE_RATIO); } else { if(attrName in this) this[attrName] = Math.floor(val * HERO_CE_RATIO * HERO_CE_RATIO); } } } private calAttrValue(roleFix: number = 0, roleRatio: number = 0, heroBase: number = 0, heroFix: number = 0, heroRatio: number = 0, heroEquip: number = 0) { return (heroFix + heroEquip + roleFix) * HERO_CE_RATIO + heroBase * ( HERO_CE_RATIO + heroRatio + roleRatio ); } private getRealSubAttr() { return { hit: this.hit / HERO_SUB_ATTR_RATIO / HERO_CE_RATIO / HERO_CE_RATIO, cri: this.cri / HERO_SUB_ATTR_RATIO / HERO_CE_RATIO / HERO_CE_RATIO, flee: this.flee / HERO_SUB_ATTR_RATIO / HERO_CE_RATIO / HERO_CE_RATIO, antCri: this.antCri / HERO_SUB_ATTR_RATIO / HERO_CE_RATIO / HERO_CE_RATIO, damageIncrease: this.damageIncrease / HERO_SUB_ATTR_RATIO / HERO_CE_RATIO / HERO_CE_RATIO, damageDecrease: this.damageDecrease / HERO_SUB_ATTR_RATIO / HERO_CE_RATIO / HERO_CE_RATIO, defIngnore: this.defIngnore / HERO_SUB_ATTR_RATIO / HERO_CE_RATIO / HERO_CE_RATIO, damageCri: this.damageCri / HERO_SUB_ATTR_RATIO / HERO_CE_RATIO / HERO_CE_RATIO } } private getRealMainAttr() { return { hp: this.hp / HERO_CE_RATIO / HERO_CE_RATIO, atk: this.atk / HERO_CE_RATIO / HERO_CE_RATIO, def: this.def / HERO_CE_RATIO / HERO_CE_RATIO, mdef: this.mdef / HERO_CE_RATIO / HERO_CE_RATIO } } public getReduceAttributes() { let newAttr = new Attribute(); newAttr.hp = reduceCe(this.hp); newAttr.atk = reduceCe(this.atk); newAttr.def = reduceCe(this.def); newAttr.mdef = reduceCe(this.mdef); newAttr.speed = reduceCe(this.speed); newAttr.hit = reduceCe(this.hit); newAttr.cri = reduceCe(this.cri); newAttr.flee = reduceCe(this.flee); newAttr.antCri = reduceCe(this.antCri); newAttr.damageIncrease = reduceCe(this.damageIncrease); newAttr.damageDecrease = reduceCe(this.damageDecrease); newAttr.defIngnore = reduceCe(this.defIngnore); newAttr.bloodSuck = reduceCe(this.bloodSuck); newAttr.ap = reduceCe(this.ap); newAttr.damageCri = reduceCe(this.damageCri); return newAttr; } // 战力计算 public calCe() { let { hp, atk, def, mdef } = this.getRealMainAttr(); let { cri, flee, damageIncrease, damageDecrease, damageCri } = this.getRealSubAttr(); let putHit = CE_CONST.PUT_HIT / HERO_SUB_ATTR_RATIO; let putAntCri = CE_CONST.PUT_ANT_CRI / HERO_SUB_ATTR_RATIO; let hitRate = CE_CONST.HIT_RATE_BASE + putHit/2 - flee; // 命中率 if(hitRate > CE_CONST.HIT_RATE_MAX) hitRate = CE_CONST.HIT_RATE_MAX; if(hitRate < CE_CONST.HIT_RATE_MIN) hitRate = CE_CONST.HIT_RATE_MIN; let fleeRate = 1 - hitRate; // 格挡率 let criRate = CE_CONST.CRI_RATE_BASE + cri - putAntCri/2; if(criRate > CE_CONST.CRI_RATE_MAX) criRate = CE_CONST.CRI_RATE_MAX; if(criRate < CE_CONST.CRI_RATE_MIN) criRate = CE_CONST.CRI_RATE_MIN; let criValue = CE_CONST.CRI_VALUE_BASE + damageCri; let validHp = hp + (def + mdef) * 0.5 / ((1 - fleeRate * CE_CONST.FLEE_VALUE) * (1 - damageDecrease)); // 有效生命 let validAtk = atk * hitRate * ( 1 + criRate * criValue) * ( 1 + damageIncrease); // 有效输出 let ce = Math.floor(validHp * validAtk * HERO_CE_RATIO * HERO_CE_RATIO / 1000); return ce > 0? ce: 1; } public calCelAndReduce() { return Math.floor(this.calCe() / HERO_CE_RATIO / HERO_CE_RATIO); } }