全局:属性修改

This commit is contained in:
luying
2021-02-27 15:35:16 +08:00
parent d4561c2e3d
commit 0966f025cf
35 changed files with 1186 additions and 1130 deletions

View File

@@ -4,9 +4,6 @@
* 属性 id
*/
import { JOB_TYPE } from "..";
export enum ABI_TYPE{
/**生命 */
ABI_HP = 1,
@@ -41,12 +38,33 @@ export enum ABI_TYPE{
ABI_DEF_IGNORE = 15,
/**吸血等级 */
ABI_BLOOD_SUCK = 16,
/**怒气 */
/**怒气恢复效果 */
ABI_AP = 17,
/**暴击伤害 */
ABI_DAMAGE_CRI = 18,
ABI_MAX,
}
// 主属性
export const ABI_TYPE_MAIN = [
ABI_TYPE.ABI_HP,
ABI_TYPE.ABI_ATK,
ABI_TYPE.ABI_DEF,
ABI_TYPE.ABI_MDEF
];
// 次级属性
export const ABI_TYPE_SUB = [
ABI_TYPE.ABI_HIT,
ABI_TYPE.ABI_CRI,
ABI_TYPE.ABI_FLEE,
ABI_TYPE.ABI_ANT_CRI,
ABI_TYPE.ABI_DAMAGE_INCREASE,
ABI_TYPE.ABI_DAMAGE_DECREASE,
ABI_TYPE.ABI_DEF_IGNORE,
ABI_TYPE.ABI_DAMAGE_CRI
];
export enum SEID_TYPE {
/**属性固定值加成(数值) */
@@ -63,39 +81,10 @@ export enum ABI_STAGE {
ATK = 2,
DEF = 3,
MDEF = 4,
AGI = 5,
LUK = 6,
END = 6
END = 4
}
export const ATTR = {}
//武将训练等级
export const HEROTARIN = {
1: "hp",
2: "atk",
3: "def",
4: "mdef",
5: "agi",
6: "luk"
};
//战力系数
export const CE_RATIO = {
"hp" : 1,
"atk" : 2,
"matk": 2,
"def": 2,
"mdef": 2,
"agi": 2,
"luk": 0,
"hit": 0,
"cri": 0,
"flee": 0,
"antCri": 0,
"damageIncrease": 0,
"damageDecrease": 0,
"defIngnore": 0,
"bloodSuck": 0,
};
export const HERO_ATTR = {
1: "hp", // 生命
@@ -114,44 +103,30 @@ export const HERO_ATTR = {
14: "damageDecrease", // 伤害减免等级
15: "defIngnore", // 忽视防御等级
16: "bloodSuck", // 吸血等级
17: "ap" // 怒气
17: "damageCri", // 暴击伤害
18: "ap" // 暴击伤害
};
export const JEWEL_ATTR = {
1: "hp",
2: "atk",
3: "def",
4: "mdef",
5: "agi",
6: "luk"
}
const BASE_ATTR = {
'hp' : 1 ,
'atk' : 2,
'def' : 3,
'mdef' : 4
}
export const ABI_TYPE_TO_STAGE = new Map<number, number | ((jobType: number) => number)>([
export const ABI_TYPE_TO_STAGE = new Map<number, number>([
[ABI_STAGE.HP, ABI_TYPE.ABI_HP],
[ABI_STAGE.ATK, (jobType:number) => { return jobType == JOB_TYPE.PHYSIC?ABI_TYPE.ABI_ATK: ABI_TYPE.ABI_MATK}],
[ABI_STAGE.ATK, ABI_TYPE.ABI_ATK],
[ABI_STAGE.DEF, ABI_TYPE.ABI_DEF],
[ABI_STAGE.MDEF, ABI_TYPE.ABI_MDEF],
[ABI_STAGE.AGI, ABI_TYPE.ABI_AGI],
[ABI_STAGE.LUK, ABI_TYPE.ABI_LUK]
[ABI_STAGE.MDEF, ABI_TYPE.ABI_MDEF]
]);
export function getAtrrNameById(attrId: number):string {
return HERO_ATTR[attrId];
};
export function getAttrCeRatio(attr: string):number {
return CE_RATIO[attr];
};
export function getAttrNameByJobStage(jobStage: number) {
return HEROTARIN[jobStage];
};
export function getTeraphAttr() {
return BASE_ATTR;
};
export enum CE_CONST {
FLEE_VALUE = 0.3, // 格挡价值
PUT_HIT = 50000, // 投放总命中
HIT_RATE_BASE = 0.75, // 命中率基础
HIT_RATE_MAX = 1, // 命中率上限
HIT_RATE_MIN = 0, // 命中率下限
PUT_ANT_CRI = 50000, // 投放总抗暴
CRI_RATE_BASE = 0.05, // 暴击率基础
CRI_RATE_MAX = 0.75, // 暴击率上限
CRI_RATE_MIN = 0.05, // 暴击率下限
CRI_VALUE_BASE = 1.5, // 暴击价值基础
}

View File

@@ -14,7 +14,3 @@ export const GOLD_COST_RATIO = {
"DAILY_REF_NUM": { "A": 50, "B": 0 }, // 每日购买次数花费
"DUNGRON_BUY_NUM": { "A": 0, "B": 50 } // 秘境购买次数花费
}
export const EXPRESSION = {
"CE": "1*hp+2*atk+2*matk+2*def+2*mdef+2*agi+2*luk+0*hit+0*cri+0*flee+0*antCri+0*damageIncrease+0*damageDecrease+0*defIngnore+0*bloodSuck"
}

View File

@@ -18,7 +18,9 @@ export const HERO_SYSTEM_TYPE = {
ADD_SKIN: 15,
SCHOOL: 16,
SCROLL: 17,
TITLE:18,
TITLE: 18,
TERAPH: 19,
TERAPH_UP: 20
};
// 武将上限
@@ -36,4 +38,6 @@ export const JOB_TYPE = {
}
// 武将战力放大系数
export const HERO_CE_RATIO = 100;
export const HERO_CE_RATIO = 100;
// 次级属性放大系数
export const HERO_SUB_ATTR_RATIO = 1000;

View File

@@ -94,7 +94,7 @@ export default class Equip extends BaseModel {
return equip;
}
public static async putOn(hid: number, equipId: string, lean = true) {
public static async putOnOrOff(equipId: string, hid: number, lean = true) {
const equip: EquipType = await EquipModel.findOneAndUpdate({ _id: equipId }, { hid }, { new: true }).lean(lean);
return equip;
}

View File

@@ -1,5 +1,5 @@
import BaseModel from './BaseModel';
import { CeAttr } from '../domain/roleField/attribute';
import { CeAttrData } from '../domain/roleField/attribute';
import { index, getModelForClass, prop, Ref, mongoose, DocumentType } from '@typegoose/typegoose';
import Equip, { } from './Equip';
import { CounterModel } from './Counter';
@@ -11,7 +11,7 @@ import { reduceCe } from '../pubUtils/util';
* 英雄表
*/
class Connect {
export class Connect {
@prop({ required: true })
shipId: number;
@prop({ required: true })
@@ -51,31 +51,6 @@ function getInitialEplace() {
return ePlace;
}
interface heroUpdate {
exp?: number;
lv?: number;
ce?: number;
star?: number;
starStage?: number;
colorStar?: number;
colorStarStage?: number;
quality?: number;
job?:number;
jobStage?:number;
favour?:number;
favourLv?:number;
skins?: Skin[];
connections?: Connect[];
ePlace?:EPlace[];
_id?:number;
scrollActive?: boolean;
scrollId?: number;
scrollStar?: number;
scrollColorStar?: number;
scrollQuality?: number;
historyCe?: number;
}
@index({ roleId: 1, hid: 1 })
@index({ roleId: 1, seqId: 1 })
export default class Hero extends BaseModel {
@@ -102,8 +77,8 @@ export default class Hero extends BaseModel {
ce: number; // 武将战力
@prop({ required: true, default: 0 })
historyCe: number; // 武将历史最高战力
@prop({required: true, default: new CeAttr(), _id: false })
ceAttr: CeAttr; // 影响战力的属性
@prop({required: true, type: CeAttrData, default: [], _id: false })
attr: CeAttrData[]; // 影响战力的属性
@prop({ required: true, default: 1 })
star: number; // 星级
@@ -181,10 +156,21 @@ export default class Hero extends BaseModel {
public static async addEquip(roleId: string, hid: number, ePlaceId: number, equipId: string, lean = true) {
const hero: HeroType = await HeroModel.findOneAndUpdate(
{ roleId, hid, 'ePlace.id': ePlaceId },
{$set: {'ePlace.$.equip': equipId, 'ePlace.$.hid':hid, 'ePlace.$.ePlaceId':ePlaceId}},
{$set: { 'ePlace.$.equip': equipId }},
{new: true}).populate('ePlace.equip').lean(lean);
if (hero) {
await Equip.putOn(hero.hid, equipId);
await Equip.putOnOrOff( equipId, hero.hid );
}
return hero;
}
public static async removeEquip(roleId: string, hid: number, ePlaceId: number, equipId: string, lean = true) {
const hero: HeroType = await HeroModel.findOneAndUpdate(
{ roleId, hid, 'ePlace.id': ePlaceId },
{$set: {'ePlace.$.equip': null}},
{new: true}).populate('ePlace.equip').lean(lean);
if (hero) {
await Equip.putOnOrOff( equipId, 0 );
}
return hero;
}
@@ -238,7 +224,7 @@ export default class Hero extends BaseModel {
return result;
}
public static async updateHeroInfo(roleId: string, hid:number, heroUpdate:heroUpdate, select?: string, lean = true) {
public static async updateHeroInfo(roleId: string, hid:number, heroUpdate:HeroUpdate, select?: string, lean = true) {
delete heroUpdate._id;
let result: HeroType = await HeroModel.findOneAndUpdate({roleId, hid}, {$set:heroUpdate}, {new: true}).select(select).lean(lean);
return result;
@@ -270,3 +256,4 @@ export default class Hero extends BaseModel {
export const HeroModel = getModelForClass(Hero);
export interface HeroType extends Pick<DocumentType<Hero>, keyof Hero>{};
export type HeroUpdate = Partial<HeroType>; // 将所有字段变成可选项

View File

@@ -1,6 +1,6 @@
import { HANG_UP_CONSTS, ROLE_TERAPH, ROLE_SELECT } from './../consts';
import { HANG_UP_CONSTS, ROLE_TERAPH, ROLE_SELECT, ABI_TYPE } from './../consts';
import BaseModel from './BaseModel';
import { CeAttrRole } from '../domain/roleField/attribute';
import { CeAttrDataRole } from '../domain/roleField/attribute';
import { index, getModelForClass, prop, DocumentType, Ref, mongoose } from '@typegoose/typegoose';
import User from './User';
import { shouldRefresh, reduceCe } from '../pubUtils/util';
@@ -41,37 +41,47 @@ export class WarStar {
star: number; // 星级
}
class Teraph{
export class Teraph{
@prop({ required: true, default: 1 })
id: number; // 神像的id
@prop({ required: true, default: 1 })
grade: number; // 等级
grade: number = 1; // 等级
@prop({ required: true, default: 0 })
hp: number;
hp: number = 0;
@prop({ required: true, default: 0 })
atk: number;
atk: number = 0;
@prop({ required: true, default: 0 })
def: number;
def: number = 0;
@prop({ required: true, default: 0 })
mdef: number;
@prop({ required: true, default: 0 })
agi: number;
@prop({ required: true, default: 0 })
luk: number;
mdef: number = 0;
constructor(id: number) {
this.id = id;
}
public get attr() {
let map = new Map<number, number>();
map.set(ABI_TYPE.ABI_HP, this.hp);
map.set(ABI_TYPE.ABI_ATK, this.atk);
map.set(ABI_TYPE.ABI_DEF, this.def);
map.set(ABI_TYPE.ABI_MDEF, this.mdef);
return map
}
public set attr(value: Map<number, number>) {
value.forEach((val, id) => {
if(id == ABI_TYPE.ABI_HP) this.hp = val;
if(id == ABI_TYPE.ABI_ATK) this.atk = val;
if(id == ABI_TYPE.ABI_DEF) this.def = val;
if(id == ABI_TYPE.ABI_MDEF) this.mdef = val;
});
}
}
// 初始化
function getInitialTeraph() {
let teraphs = new Array<Teraph>();
for(let i = ROLE_TERAPH.START; i <= ROLE_TERAPH.END; i++) {
let p = new Teraph();
p.id = i;
p.grade = 1;
p.hp = 0;
p.atk = 0;
p.def = 0;
p.mdef = 0;
p.agi = 0;
p.luk = 0;
let p = new Teraph(i);
teraphs.push(p);
}
return teraphs;
@@ -114,8 +124,8 @@ export default class Role extends BaseModel {
lv: number; // 主公等级
@prop({ required: true, default: 0, set: (val: number) => val, get: (val: number) => reduceCe(val) })
ce: number; // 总战力
@prop({ required: true, default: new CeAttrRole(), _id: false })
globalCeAttr: CeAttrRole; // 总战力
@prop({ required: true, type: CeAttrDataRole, default: [], _id: false })
attr: CeAttrDataRole[]; // 总战力
@prop({ required: true, default: 0, set: (val: number) => val, get: (val: number) => reduceCe(val) })
topLineupCe: number; // 最强x人战力
@prop({ required: true, type: TopHero, default: [], _id: false })
@@ -242,8 +252,8 @@ export default class Role extends BaseModel {
* @param select 选取字段,来自 selectConst/ROLE
* @param getters 是否使用get方法如ce使用了自动缩小1w倍
*/
public static async findByRoleId(roleId: string, select?: string, getters = false) {
const role: RoleType = await RoleModel.findOne({ roleId }).select(select).lean({getters});
public static async findByRoleId(roleId: string, select?: string, getters = false, virtuals = true) {
const role: RoleType = await RoleModel.findOne({ roleId }).select(select).lean({getters, virtuals});
return role;
}
@@ -252,9 +262,8 @@ export default class Role extends BaseModel {
if (!user) return null;
const doc = new RoleModel();
const update = Object.assign(doc.toJSON(), roleInfo, { userInfo: user, serverType: user.serverType, serverId });
initRoleAtrr(update);
const role: RoleType = await RoleModel.findOneAndUpdate({ 'userInfo.uid': uid, serverId }, update, { upsert: true, new: true }).lean(lean);
initRoleAtrr(role);
return role;
}
@@ -427,7 +436,7 @@ export default class Role extends BaseModel {
return recs
}
public static async updateRoleInfo(roleId: string, roleUpdate:roleUpdate, lean = true) {
public static async updateRoleInfo(roleId: string, roleUpdate:RoleUpdate, lean = true) {
delete roleUpdate._id;
let result: RoleType = await RoleModel.findOneAndUpdate({roleId}, {$set:roleUpdate}, {new: true}).lean(lean);
return result;
@@ -519,4 +528,4 @@ export default class Role extends BaseModel {
export const RoleModel = getModelForClass(Role);
export interface RoleType extends Pick<DocumentType<Role>, keyof Role>{};
type roleUpdate = Partial<RoleType>; // 将所有字段变成可选项
export type RoleUpdate = Partial<RoleType>; // 将所有字段变成可选项

View File

@@ -1,7 +1,7 @@
import { prop } from '@typegoose/typegoose';
import { DicWarJson } from '../pubUtils/dictionary/DicWarJson';
import { HeroType } from '../db/Hero';
import { CeAttrNumber } from './roleField/attribute';
import { Attribute } from './roleField/attribute';
// 从玩家数据中覆盖warjson的部分字段
export class PvpHeroInfo {
@@ -27,7 +27,7 @@ export class PvpHeroInfo {
quality?: number = 0; // 品质
@prop({ required: true, _id: false })
attribute?: CeAttrNumber; // 属性
attribute?: Attribute; // 属性
setHeroInfo(hero: HeroType) {
this.actorId = hero.hid;
@@ -46,7 +46,7 @@ export class PvpHeroInfo {
this.quality = quality;
}
setAttribute(attribute: CeAttrNumber) {
setAttribute(attribute: Attribute) {
this.attribute = attribute;
}

View File

@@ -1,7 +1,10 @@
import { prop } from '@typegoose/typegoose';
import { HERO_CE_RATIO, getAtrrNameById, CE_CONST, HERO_SUB_ATTR_RATIO } from '../../consts';
// hero表内属性基础格式
export class CeAttrData {
@prop({ required: true })
id?: number = 0;
@prop({ required: true })
base: number = 0;
@prop({ required: true })
@@ -12,132 +15,128 @@ export class CeAttrData {
equipUp: number = 0;
}
// hero表全属性
export class CeAttr {
@prop({ required: false, _id: false })
hp?: CeAttrData = new CeAttrData();
@prop({ required: false, _id: false })
atk?: CeAttrData = new CeAttrData();
@prop({ required: false, _id: false })
matk?: CeAttrData = new CeAttrData();
@prop({ required: false, _id: false })
def?: CeAttrData = new CeAttrData();
@prop({ required: false, _id: false })
mdef?: CeAttrData = new CeAttrData();
@prop({ required: false, _id: false })
agi?: CeAttrData = new CeAttrData();
@prop({ required: false, _id: false })
luk?: CeAttrData = new CeAttrData();
@prop({ required: false, _id: false })
hit?: CeAttrData = new CeAttrData();
@prop({ required: false, _id: false })
cri?: CeAttrData = new CeAttrData();
@prop({ required: false, _id: false })
flee?: CeAttrData = new CeAttrData();
@prop({ required: false, _id: false })
antCri?: CeAttrData = new CeAttrData();
@prop({ required: false, _id: false })
damageIncrease?: CeAttrData = new CeAttrData();
@prop({ required: false, _id: false })
damageDecrease?: CeAttrData = new CeAttrData();
@prop({ required: false, _id: false })
defIngnore?: CeAttrData = new CeAttrData();
@prop({ required: false, _id: false })
bloodSuck?: CeAttrData = new CeAttrData();
}
// role表属性格式
export class CeAttrDataRole {
@prop({ required: true })
id?: number = 0;
@prop({ required: true })
ratioUp: number = 0;
@prop({ required: true })
fixUp: number = 0;
}
// role表全属性
export class CeAttrRole {
@prop({ required: false, _id: false })
hp?: CeAttrDataRole = new CeAttrDataRole();
@prop({ required: false, _id: false })
atk?: CeAttrDataRole = new CeAttrDataRole();
@prop({ required: false, _id: false })
matk?: CeAttrDataRole = new CeAttrDataRole();
@prop({ required: false, _id: false })
def?: CeAttrDataRole = new CeAttrDataRole();
@prop({ required: false, _id: false })
mdef?: CeAttrDataRole = new CeAttrDataRole();
@prop({ required: false, _id: false })
agi?: CeAttrDataRole = new CeAttrDataRole();
@prop({ required: false, _id: false })
luk?: CeAttrDataRole = new CeAttrDataRole();
@prop({ required: false, _id: false })
hit?: CeAttrDataRole = new CeAttrDataRole();
@prop({ required: false, _id: false })
cri?: CeAttrDataRole = new CeAttrDataRole();
@prop({ required: false, _id: false })
flee?: CeAttrDataRole = new CeAttrDataRole();
@prop({ required: false, _id: false })
antCri?: CeAttrDataRole = new CeAttrDataRole();
@prop({ required: false, _id: false })
damageIncrease?: CeAttrDataRole = new CeAttrDataRole();
@prop({ required: false, _id: false })
damageDecrease?: CeAttrDataRole = new CeAttrDataRole();
@prop({ required: false, _id: false })
defIngnore?: CeAttrDataRole = new CeAttrDataRole();
@prop({ required: false, _id: false })
bloodSuck?: CeAttrDataRole = new CeAttrDataRole();
}
// 所有属性使用数字格式
export class CeAttrNumber {
@prop({ required: false })
hp?: number = 0;
@prop({ required: false })
atk?: number = 0;
@prop({ required: false })
matk?: number = 0;
@prop({ required: false })
def?: number = 0;
@prop({ required: false })
mdef?: number = 0;
@prop({ required: false })
agi?: number = 0;
@prop({ required: false })
luk?: 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;
}
// 主属性
export class MainAttrNumber {
hp: number = 0;
atk: number = 0;
matk: number = 0;
def: number = 0;
mdef: number = 0;
agi: number = 0;
luk: number = 0;
constructor(attr: CeAttrNumber) {
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;
if(attr.agi) this.agi = attr.agi;
if(attr.luk) this.luk = attr.luk;
}
}
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;
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(attrName in this) this[attrName] = Math.floor(val * 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 setSubAttrRatio() {
return {
hit: this.hit / HERO_SUB_ATTR_RATIO,
cri: this.cri / HERO_SUB_ATTR_RATIO,
flee: this.flee / HERO_SUB_ATTR_RATIO,
antCri: this.antCri / HERO_SUB_ATTR_RATIO,
damageIncrease: this.damageIncrease / HERO_SUB_ATTR_RATIO,
damageDecrease: this.damageDecrease / HERO_SUB_ATTR_RATIO,
defIngnore: this.defIngnore / HERO_SUB_ATTR_RATIO,
damageCri: this.damageCri / HERO_SUB_ATTR_RATIO
}
}
public calCe() {
let { cri, flee, damageIncrease, damageDecrease, damageCri } = this.setSubAttrRatio();
let hitRate = CE_CONST.HIT_RATE_BASE + CE_CONST.PUT_HIT/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 - CE_CONST.PUT_ANT_CRI/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 = this.hp + (this.def + this.mdef) * 0.5 / ((1 - fleeRate * CE_CONST.FLEE_VALUE) * (1 - damageDecrease)); // 有效生命
let validAtk = this.atk * hitRate * ( 1 + criRate * criValue) * ( 1 + damageIncrease); // 有效输出
let ce = Math.floor(validHp * validAtk);
return ce > 0? ce: 1;
}
}

View File

@@ -35,7 +35,6 @@ import { dicTeraph } from './dictionary/DicTeraph';
import { dicSchool } from './dictionary/DicSchool';
import { dicSchoolRate } from './dictionary/DicSchoolRate';
import { dicHeroScroll, preHeroScroll } from './dictionary/DicHeroScroll';
import { ABI_TYPE_TO_STAGE } from "../consts";
import { dicPvpOpponent } from './dictionary/DicPvpOpponent';
import { dicPvpTeamLevel } from './dictionary/DicPvpTeamLevel';
import { dicPvpRefreshConsume, maxPvpRefreshCnt } from './dictionary/DicPvpRefreshConsume';
@@ -58,6 +57,7 @@ import { dicArmyBossRank } from '../pubUtils/dictionary/DicArmyBossRank';
import { dicArmyDonate } from '../pubUtils/dictionary/DicArmyDonateBoxReward';
import { dicRoleFriend } from "./dictionary/DicRoleFriend";
import { dicRoleFriendLv } from "./dictionary/DicRoleFriendLv";
import { Attribute } from "../domain/roleField/attribute";
export const gameData = {
blurprtCompose: dicBlueprtCompose,
@@ -213,7 +213,10 @@ export function getBossHpByWarId(warId: number) {
warInfo.forEach(hero => {
let { attribute, dataId, relation, actorId } = hero;
if (relation === 2) {
const hp = attribute.hp||0;
let attrJson = new Attribute();
attrJson.setByWarJson(attribute, 1);
const hp = attrJson.hp||0;
if (hp > 0) {
bossHpArr.push({dataId, hp, actorId});
bossHpSum += hp;
@@ -300,17 +303,6 @@ export function getScollByStar(quality: number, star: number, curQuality: number
return heroScroll;
}
// 根据存在升星表等的stage字段的id对应17维id
export function getFieldByStage(stage: number, jobid: number) {
let targetAttrId = ABI_TYPE_TO_STAGE.get(stage);
if(typeof targetAttrId === 'number') {
return targetAttrId
} else {
const dicJob = gameData.job.get(jobid);
return targetAttrId(dicJob.type);
}
}
export function getSuit(id: number) {
const suitInfo = gameData.suit.get(id);
return suitInfo;
@@ -420,7 +412,7 @@ export function getArmyWishPoolBaseByLv(lv: number) {
export function getFriendLvByExp(exp: number) {
let resultLv = 1;
for(let [lv, {sum}] of gameData.roleFriendLv) {
for(let [lv, {sum}] of gameData.roleFriendLv.entries()) {
resultLv = lv;
if(exp < sum) break;
}

View File

@@ -152,12 +152,10 @@ function parseAbility(json) {
let map = new Map<number, number>();
map.set(ABI_TYPE.ABI_HP, json.hp||0);
map.set(ABI_TYPE.ABI_ATK, json.atk||0);
map.set(ABI_TYPE.ABI_MATK, json.matk||0);
map.set(ABI_TYPE.ABI_DEF, json.def||0);
map.set(ABI_TYPE.ABI_MDEF, json.mdef||0);
map.set(ABI_TYPE.ABI_AGI, json.agi||0);
map.set(ABI_TYPE.ABI_LUK, json.luk||0);
map.set(ABI_TYPE.ABI_SPEED, json.speed||0);
map.set(ABI_TYPE.ABI_DAMAGE_INCREASE, json.damageIncrease||0);
map.set(ABI_TYPE.ABI_DAMAGE_DECREASE, json.damageDecrease||0);
return map
}
@@ -165,12 +163,10 @@ function parseAbilityUp(json) {
let map = new Map<number, number>();
map.set(ABI_TYPE.ABI_HP, json.hp_up||0);
map.set(ABI_TYPE.ABI_ATK, json.atk_up||0);
map.set(ABI_TYPE.ABI_MATK, json.matk_up||0);
map.set(ABI_TYPE.ABI_DEF, json.def_up||0);
map.set(ABI_TYPE.ABI_MDEF, json.mdef_up||0);
map.set(ABI_TYPE.ABI_AGI, json.agi_up||0);
map.set(ABI_TYPE.ABI_LUK, json.luk_up||0);
map.set(ABI_TYPE.ABI_SPEED, json.speed_up||0);
map.set(ABI_TYPE.ABI_DAMAGE_INCREASE, json.damageIncrease_up||0);
map.set(ABI_TYPE.ABI_DAMAGE_DECREASE, json.damageDecrease_up||0);
return map
}

View File

@@ -41,7 +41,5 @@ function parseCeAttr(elem) {
ceAttr.set(ABI_STAGE.ATK, elem.atk);
ceAttr.set(ABI_STAGE.DEF, elem.def);
ceAttr.set(ABI_STAGE.MDEF, elem.mdef);
ceAttr.set(ABI_STAGE.AGI, elem.agi);
ceAttr.set(ABI_STAGE.LUK, elem.luk);
return ceAttr;
}

View File

@@ -36,7 +36,6 @@ function parseCeAttr(elem) {
ceAttr.set(ABI_STAGE.ATK, elem.atk_up);
ceAttr.set(ABI_STAGE.DEF, elem.def_up);
ceAttr.set(ABI_STAGE.MDEF, elem.mdef_up);
ceAttr.set(ABI_STAGE.AGI, elem.agi_up);
ceAttr.set(ABI_STAGE.LUK, elem.luk_up);
return ceAttr;
}
}
arr = undefined;

View File

@@ -40,7 +40,5 @@ function parseCeAttr(elem) {
ceAttr.set(ABI_STAGE.ATK, elem.atk_up);
ceAttr.set(ABI_STAGE.DEF, elem.def_up);
ceAttr.set(ABI_STAGE.MDEF, elem.mdef_up);
ceAttr.set(ABI_STAGE.AGI, elem.agi_up);
ceAttr.set(ABI_STAGE.LUK, elem.luk_up);
return ceAttr;
}

View File

@@ -1,6 +1,6 @@
// 兵种表
import {readJsonFile, parseNumberList, parseGoodStr} from '../util'
import { FILENAME } from '../../consts'
import { FILENAME, ABI_STAGE } from '../../consts'
import { RewardInter } from '../interface';
const _ = require('lodash');
@@ -23,18 +23,8 @@ export interface DicJob {
readonly trainingConsume: Array<RewardInter>;
// 升阶消耗
readonly upGradeConsume: Array<RewardInter>;
// 生命训练提升
readonly hp: number;
// 攻击力训练提升
readonly atk: number;
// 防御力训练提升
readonly def: number;
// 策防训练提升
readonly mdef: number;
// 敏捷训练提升
readonly agi: number;
// 幸运训练提升
readonly luk: number;
// 每阶升级属性
readonly ceAttr: Map<number, number>
}
@@ -42,7 +32,7 @@ const str = readJsonFile(FILENAME.DIC_JOB);
let arr = JSON.parse(str);
type KeysEnum<T> = { [P in keyof Required<T>]: true };
const DicJobKeys: KeysEnum<DicJob> = {jobid: true, name: true, grade: true, unlockLevel: true, job_class: true, type: true, seid: true,trainingConsume: true, upGradeConsume: true, hp: true, atk: true, def: true, mdef: true, agi: true, luk: true};
const DicJobKeys: KeysEnum<DicJob> = {jobid: true, name: true, grade: true, unlockLevel: true, job_class: true, type: true, seid: true,trainingConsume: true, upGradeConsume: true, ceAttr: true};
export const dicJob = new Map<number, DicJob>();
export const jobClassMaxGrades = new Map<number, {grade:number, jobid:number}>();
@@ -52,6 +42,7 @@ arr.forEach(o => {
o.seid = parseNumberList(o.seid);
o.trainingConsume = parseGoodStr(o.trainingConsume);
o.upGradeConsume = parseGoodStr(o.upGradeConsume);
o.ceAttr = parseCeAttr(o);
dicJob.set(o.jobid, _.pick(o, Object.keys(DicJobKeys)));
let jobClass = jobClassMaxGrades.get(o.job_class);
if (!!jobClass && jobClass.grade < o.grade) {
@@ -61,4 +52,13 @@ arr.forEach(o => {
});
function parseCeAttr(elem) {
let ceAttr = new Map<number, number>();
ceAttr.set(ABI_STAGE.HP, elem.hp);
ceAttr.set(ABI_STAGE.ATK, elem.atk);
ceAttr.set(ABI_STAGE.DEF, elem.def);
ceAttr.set(ABI_STAGE.MDEF, elem.mdef);
return ceAttr;
}
arr = undefined;

View File

@@ -1,6 +1,7 @@
// 物品表
import { decodeArrayListStr, readJsonFile, parseGoodStr } from '../util'
import { FILENAME} from '../../consts'
import { FILENAME, ABI_TYPE} from '../../consts'
import { RewardInter } from '../interface';
const _ = require('lodash');
export interface SpecialMaterial {
@@ -13,25 +14,16 @@ export interface DicTeraph {
readonly id: number;
readonly index: number;
readonly grade: number;
readonly hpMax: number;
readonly atkMax: number;
readonly defMax: number;
readonly mdefMax: number;
readonly agiMax: number;
readonly lukMax: number;
readonly hp;
readonly atk;
readonly def;
readonly mdef;
readonly agi;
readonly luk;
readonly criRate;
readonly criEffect;
readonly upMaterial:Array<{id: number, number: number}>;
readonly mainAttrMax: Map<number, number>; // 最大强化加成 id => value 18围内的id
readonly mainAttrUp: Map<number, number>; // 每次强化加成 id => value 18围内的id
readonly criRate: number;
readonly criEffect: number;
readonly upMaterial:Array<RewardInter>;
readonly assiAttrValue:Array<{id: number, number: number}>;
readonly upGradeMaterial:Array<{id: number, number: number}>;
readonly assiAttrValue:Map<number, number>; // 次级属性
readonly upGradeMaterial:Array<RewardInter>;
}
const str = readJsonFile(FILENAME.DIC_TERAPH);
@@ -42,18 +34,8 @@ const DicTeraphKeys: KeysEnum<DicTeraph> = {
id: true,
index: true,
grade: true,
hpMax: true,
atkMax: true,
defMax: true,
mdefMax: true,
agiMax: true,
lukMax: true,
hp: true,
atk: true,
def: true,
mdef: true,
agi: true,
luk: true,
mainAttrMax: true,
mainAttrUp: true,
criRate: true,
criEffect: true,
upMaterial: true,
@@ -65,26 +47,38 @@ arr.forEach(o => {
o.assiAttrValue = parseAttr(o.assiAttrValue);
o.upGradeMaterial = parseGoodStr(o.upGradeMaterial);
o.upMaterial = parseGoodStr(o.upMaterial);
o.hp = o.hpUp;
o.atk = o.atkUp;
o.def = o.defUp;
o.mdef = o.mdefUp;
o.agi = o.agiUp;
o.luk = o.lukUp;
o.mainAttrMax = parseMainAttrMax(o);
o.mainAttrUp = parseMainAttrUp(o);
dicTeraph.set(o.index + '_' + o.grade, _.pick(o, Object.keys(DicTeraphKeys)));
});
arr = undefined;
function parseAttr(str: string) {
let result = new Array<{id: number, number: number}>();
let result = new Map<number, number>();
if(!str) return result;
let decodeArr = decodeArrayListStr(str);
for(let [id, number] of decodeArr) {
if(isNaN(parseInt(id)) || isNaN(parseInt(number))) {
throw new Error('data table format wrong');
}
result.push({id: parseInt(id), number: parseInt(number)});
result.set(parseInt(id), parseInt(number));
}
return result
}
function parseMainAttrMax(elem) {
let result = new Map<number, number>();
result.set(ABI_TYPE.ABI_HP, elem.hpMax);
result.set(ABI_TYPE.ABI_ATK, elem.atkMax);
result.set(ABI_TYPE.ABI_DEF, elem.defMax);
result.set(ABI_TYPE.ABI_MDEF, elem.mdefMax);
}
function parseMainAttrUp(elem) {
let result = new Map<number, number>();
result.set(ABI_TYPE.ABI_HP, elem.hpUp);
result.set(ABI_TYPE.ABI_ATK, elem.atkUp);
result.set(ABI_TYPE.ABI_DEF, elem.defUp);
result.set(ABI_TYPE.ABI_MDEF, elem.mdefUp);
}

View File

@@ -1,6 +1,6 @@
// 物品表
import { decodeArrayListStr, readJsonFile, parseGoodStr } from '../util'
import { FILENAME} from '../../consts'
import { FILENAME, ABI_STAGE, ABI_TYPE_TO_STAGE, ABI_TYPE} from '../../consts'
const _ = require('lodash');
export interface SpecialMaterial {
@@ -9,15 +9,10 @@ export interface SpecialMaterial {
}
export interface DicTitle {
// 等级
readonly id: number;
readonly hp: number;
readonly atk: number;
readonly def: number;
readonly mdef: number;
readonly agi: number;
readonly luk: number;
readonly assiAttrValue: Array<{id: number, number: number}>;
// 等级
readonly mainAttrValue: Map<number, number>; // id => value 这里的值是上一级的基础上增加的值
readonly assiAttrValue: Map<number, number>; // id => value
// 等级现在
readonly lvLimited: number;
// 升级消耗
@@ -30,18 +25,14 @@ let arr = JSON.parse(str);
type KeysEnum<T> = { [P in keyof Required<T>]: true };
const DicTitleKeys: KeysEnum<DicTitle> = {
id: true,
hp: true,
atk: true,
def: true,
mdef: true,
agi: true,
luk: true,
mainAttrValue: true,
assiAttrValue: true,
lvLimited: true,
material: true
}
export const dicTitle = new Map<number, DicTitle>();
arr.forEach(o => {
o.mainAttrValue = parseMainAttr(o);
o.assiAttrValue = parseAttr(o.assiAttrValue);
o.material = parseGoodStr(o.material);
dicTitle.set(o.id, _.pick(o, Object.keys(DicTitleKeys)));
@@ -50,14 +41,23 @@ arr.forEach(o => {
arr = undefined;
function parseAttr(str: string) {
let result = new Array<{id: number, number: number}>();
let result = new Map<number, number>();
if(!str) return result;
let decodeArr = decodeArrayListStr(str);
for(let [id, number] of decodeArr) {
if(isNaN(parseInt(id)) || isNaN(parseInt(number))) {
for(let [id, value] of decodeArr) {
if(isNaN(parseInt(id)) || isNaN(parseInt(value))) {
throw new Error('data table format wrong');
}
result.push({id: parseInt(id), number: parseInt(number)});
result.set(parseInt(id), parseInt(value));
}
return result
}
function parseMainAttr(elem) {
let result = new Map<number, number>();
result.set(ABI_TYPE.ABI_HP, elem.hp);
result.set(ABI_TYPE.ABI_ATK, elem.atk);
result.set(ABI_TYPE.ABI_DEF, elem.def);
result.set(ABI_TYPE.ABI_MDEF, elem.mdef);
return result;
}

View File

@@ -1,8 +1,5 @@
// 关卡表
import {decodeArrayListStr, readWarJsonFileList} from '../util'
import { ABI_TYPE } from '../../consts';
import { Attributes } from '../interface';
export interface DicWarJson {
@@ -33,7 +30,7 @@ export interface DicWarJson {
// 角色使用的AI类型
readonly initial_ai: number;
// 属性
readonly attribute: Attributes;
readonly attribute: {id: number, val: number}[];
// 武将技能
readonly skill: string;
// 武将被动技能
@@ -63,55 +60,15 @@ readWarJsonFileList().forEach(str => {
dicWarJson.set(warid, warjson);
})
function parseAttribute(str: string) {
let attribute: Attributes = {};
if(!str) return attribute;
let arr = decodeArrayListStr(str);
for(let [id, value] of arr) {
if(isNaN(parseInt(id)) || isNaN(parseInt(value))) {
export function parseAttribute(str: string) {
let result = new Array<{ id: number, val: number }>();
if (!str) return result;
let decodeArr = decodeArrayListStr(str);
for (let [id, val] of decodeArr) {
if (isNaN(parseInt(id)) || isNaN(parseInt(val))) {
throw new Error('data table format wrong');
}
let _id = parseInt(id), _value = parseInt(value);
switch(_id) {
case ABI_TYPE.ABI_HP:
attribute.hp = _value; break;
case ABI_TYPE.ABI_ATK:
attribute.atk = _value; break;
case ABI_TYPE.ABI_MATK:
attribute.matk = _value; break;
case ABI_TYPE.ABI_DEF:
attribute.def = _value; break;
case ABI_TYPE.ABI_MDEF:
attribute.mdef = _value; break;
case ABI_TYPE.ABI_AGI:
attribute.agi = _value; break;
case ABI_TYPE.ABI_LUK:
attribute.luk = _value; break;
case ABI_TYPE.ABI_SPEED:
attribute.speed = _value; break;
case ABI_TYPE.ABI_HIT:
attribute.hit = _value; break;
case ABI_TYPE.ABI_CRI:
attribute.cri = _value; break;
case ABI_TYPE.ABI_FLEE:
attribute.flee = _value; break;
case ABI_TYPE.ABI_ANT_CRI:
attribute.antCri = _value; break;
case ABI_TYPE.ABI_DAMAGE_INCREASE:
attribute.damageIncrease = _value; break;
case ABI_TYPE.ABI_DAMAGE_DECREASE:
attribute.damageDecrease = _value; break;
case ABI_TYPE.ABI_DEF_IGNORE:
attribute.defIngnore = _value; break;
case ABI_TYPE.ABI_BLOOD_SUCK:
attribute.bloodSuck = _value; break;
case ABI_TYPE.ABI_AP:
attribute.ap = _value; break;
default:
break;
}
result.push({ id: parseInt(id), val: parseInt(val) });
}
return attribute
}
return result
}

View File

@@ -373,8 +373,6 @@ function parseHeroStar() {
ceAttr.set(ABI_STAGE.ATK, elem.atk_up);
ceAttr.set(ABI_STAGE.DEF, elem.def_up);
ceAttr.set(ABI_STAGE.MDEF, elem.mdef_up);
ceAttr.set(ABI_STAGE.AGI, elem.agi_up);
ceAttr.set(ABI_STAGE.LUK, elem.luk_up);
heroStarList.set(`${elem.quality}_${elem.star}`,{ceAttr, ...elem});
}
@@ -392,8 +390,6 @@ function parseHeroWake() {
ceAttr.set(ABI_STAGE.ATK, elem.atk_up);
ceAttr.set(ABI_STAGE.DEF, elem.def_up);
ceAttr.set(ABI_STAGE.MDEF, elem.mdef_up);
ceAttr.set(ABI_STAGE.AGI, elem.agi_up);
ceAttr.set(ABI_STAGE.LUK, elem.luk_up);
heroWakeList.set(`${elem.quality}_${elem.star}`,{ceAttr, ...elem});
}

View File

@@ -1,31 +1,12 @@
// 一些通用的interface定义
import { Attribute } from "../domain/roleField/attribute";
export interface RewardInter {
id: number;
count: number;
}
export interface Attributes {
hp?: number;
atk?: number;
matk?: number;
def?: number;
mdef?: number;
agi?: number;
luk?: number;
speed?: number;
hit?: number;
cri?: number;
flee?: number;
antCri?: number;
damageIncrease?: number;
damageDecrease?: number;
defIngnore?: number;
bloodSuck?: number;
ap?: number;
}
export interface EquipInter {
id: number;
name: string;
@@ -82,7 +63,7 @@ export interface oppHeroesDefenseInter {
lv: number; // 等级
hide: number; // 是否隐藏
initial_ai: number; // ai类型
attribute: Attributes;
attribute: Attribute;
star: number; // 星级
skill: string|number; // 技能
seid: string; // 技能

File diff suppressed because it is too large Load Diff