Merge branch 'feature/ce'
This commit is contained in:
@@ -99,13 +99,17 @@ export const ABI_TYPE_SUB = [
|
||||
|
||||
export enum SEID_TYPE {
|
||||
/**属性固定值加成(数值) */
|
||||
TYPE101 = 1,
|
||||
/**基础属性加百分比,除以1000以后加到ratioUp */
|
||||
TYPE103 = 2,
|
||||
/**次级属性的百分比加成,乘以100后加到fixUp */
|
||||
TYPE104 = 3,
|
||||
FIX = 1,
|
||||
/**基础属性加百分比,除以1000 */
|
||||
MAIN_RATIO = 2,
|
||||
/**次级属性的百分比加成 */
|
||||
SUB_RATIO = 3,
|
||||
/**基础属性加百分比,除以1000 */
|
||||
MAIN_RATIO_2 = 4,
|
||||
/**次级属性的百分比加成 */
|
||||
SUB_RATIO_2 = 5,
|
||||
/**复合属性 */
|
||||
TYPE999 = 999,
|
||||
MIX = 999,
|
||||
}
|
||||
|
||||
export enum ABI_STAGE {
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
//武将养成系统分类
|
||||
export enum HERO_SYSTEM_TYPE {
|
||||
INIT = 0, // 初始武将
|
||||
STAR = 1, // 升星
|
||||
LVUP = 2, // 升级
|
||||
LVUP = 1, // 升级
|
||||
STAR = 2, // 升星
|
||||
COLORSTAR = 3, // 觉醒
|
||||
QUALITY = 4, // 升品
|
||||
TRAIN = 5, // (职业)训练
|
||||
@@ -10,11 +10,11 @@ export enum HERO_SYSTEM_TYPE {
|
||||
SKIN =7, // 皮肤
|
||||
FAVOUR =8, // 好感
|
||||
CONNECT =9, // 羁绊
|
||||
EQUIP = 10, // 装备穿脱
|
||||
EQUIP_BASE = 11, // 装备栏升级,装备精炼等
|
||||
RESTRENGTHEN = 12, // 洗练
|
||||
JEWEL_ON = 13, // 穿宝石
|
||||
JEWEL_OFF = 14, // 脱宝石
|
||||
// EQUIP = 10, // 装备穿脱
|
||||
// EQUIP_BASE = 11, // 装备栏升级,装备精炼等
|
||||
// RESTRENGTHEN = 12, // 洗练
|
||||
// JEWEL_ON = 13, // 穿宝石
|
||||
// JEWEL_OFF = 14, // 脱宝石
|
||||
ADD_SKIN = 15, // 第一次获取皮肤(全局)
|
||||
SCHOOL = 16, // 百家学宫
|
||||
SCROLL = 17, // 名将谱
|
||||
@@ -31,6 +31,7 @@ export enum HERO_SYSTEM_TYPE {
|
||||
JEWEL_QUENCH = 28, // 天晶石淬炼
|
||||
REBIRTH = 29, // 武将重生
|
||||
TALENT = 30, // 天赋
|
||||
ROLE_LV = 31, // 玩家等级
|
||||
};
|
||||
|
||||
// 武将上限
|
||||
@@ -47,10 +48,8 @@ export const JOB_TYPE = {
|
||||
MAGIC: 2
|
||||
}
|
||||
|
||||
// 武将战力放大系数
|
||||
export const HERO_CE_RATIO = 100;
|
||||
// 次级属性放大系数
|
||||
export const HERO_SUB_ATTR_RATIO = 1000 * 100;
|
||||
export const HERO_SUB_ATTR_RATIO = 1000;
|
||||
|
||||
export const HERO_INITIAL_QUALITY = {
|
||||
BLUE: 1,
|
||||
|
||||
@@ -14,14 +14,14 @@ export enum ROLE_SELECT {
|
||||
COM_BATTLE = 'lv head frame spine heads frames spines topLineupCe',
|
||||
GET_HEADS = 'heads head frames frame spines spine',
|
||||
// 排行榜基础数据
|
||||
RANK = 'roleId roleName lv vLv head frame spine heads frames spines title guildName ce isReducedCe topLineup towerLv towerUpTime topLineupCe heroNum updatedAt heroNumUpdatedAt dungeonWarId dungeonUpdatedAt dungeonHeroes mainWarId mainUpdatedAt mainEliteWarId mainEliteUpdatedAt showLineup hasGuild',
|
||||
RANK = 'roleId roleName lv vLv head frame spine heads frames spines title guildName ce topLineup towerLv towerUpTime topLineupCe heroNum updatedAt heroNumUpdatedAt dungeonWarId dungeonUpdatedAt dungeonHeroes mainWarId mainUpdatedAt mainEliteWarId mainEliteUpdatedAt showLineup hasGuild',
|
||||
};
|
||||
|
||||
export enum HERO_SELECT {
|
||||
ENTRY = '-_id -attr',
|
||||
HERO_DETAIL = 'roleId roleName hid hName ce isReducedCe lv star colorStar quality job skins attr ePlace skinId',
|
||||
HERO_DETAIL = 'roleId roleName hid hName ce lv star colorStar quality job skins attr ePlace skinId',
|
||||
// 排行榜中lineup字段
|
||||
RANK_LINEUP = 'seqId roleId hid star colorStar lv quality job ce isReducedCe updatedAt skinId'
|
||||
RANK_LINEUP = 'seqId roleId hid star colorStar lv quality job ce updatedAt skinId'
|
||||
}
|
||||
|
||||
export enum EQUIP_SELECT {
|
||||
|
||||
@@ -540,6 +540,7 @@ export const FILENAME = {
|
||||
DIC_STONE: 'dic_zyz_stone',
|
||||
DIC_JEWEL_CONDITION: 'dic_zyz_jewel_condition',
|
||||
DIC_MAIN_STAR_BOX: 'dic_zyz_main_star_reward',
|
||||
DIC_EQUIP_STRENGTH_ATTR: 'dic_zyz_equipStrengthAttr',
|
||||
}
|
||||
|
||||
export const WAR_RELATE_TABLES = [
|
||||
|
||||
@@ -3,7 +3,6 @@ import { index, getModelForClass, prop, DocumentType, Ref, mongoose } from '@typ
|
||||
import Role, { RoleType } from './Role';
|
||||
import { GUILD_STRUCTURE, GUILD_STATUS, GUILD_PER_PAGE, GUILD_SELECT, REDIS_KEY, SHOP_REFRESH_TYPE } from '../consts';
|
||||
import { getZeroPoint, getZeroPointD, nowSeconds } from '../pubUtils/timeUtil';
|
||||
import { reduceCe } from '../pubUtils/util';
|
||||
import { gameData } from '../pubUtils/data';
|
||||
import { SearchGuildParam } from '../domain/backEndField/search';
|
||||
|
||||
@@ -77,12 +76,9 @@ export default class Guild extends BaseModel {
|
||||
@prop({ required: true, default: new Date(), select: false })
|
||||
refTimeDaily: Date;
|
||||
|
||||
@prop({ required: true, default: 0, get: (val:number) => reduceCe(val), set: (val: number) => val })
|
||||
@prop({ required: true, default: 0 })
|
||||
guildCe: number; // 总战力
|
||||
|
||||
@prop({ required: false, set: (val: boolean) => val, get: () => true })
|
||||
isReducedCe: boolean; // 如果战力没有缩过就会返回false,缩过了就会返回true
|
||||
|
||||
@prop({ required: true, type: String, default: [], select: false })
|
||||
members: string[]; // 军团成员的roleId,用于增加战力的时候加入总战力
|
||||
|
||||
|
||||
@@ -1,55 +1,11 @@
|
||||
import BaseModel from './BaseModel';
|
||||
import { index, getModelForClass, prop, Ref, mongoose, DocumentType } from '@typegoose/typegoose';
|
||||
// import Equip, { } from './Equip';
|
||||
import { CounterModel } from './Counter';
|
||||
import { COUNTER, HERO_CE_RATIO } from '../consts';
|
||||
import { reduceCe } from '../pubUtils/util';
|
||||
import Skin from './Skin';
|
||||
import { DEFAULT_HERO_LV } from '../consts';
|
||||
import Skin, { SkinUpdate } from './Skin';
|
||||
import { SearchHeroParam } from '../domain/backEndField/search';
|
||||
import { Reward } from '../domain/battleField/pvp';
|
||||
import { getHeroInitTalent } from '../pubUtils/data';
|
||||
|
||||
type CeAttrUpdate = Partial<CeAttrData>;
|
||||
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;
|
||||
}
|
||||
|
||||
public copyFromHero(data: CeAttrData) {
|
||||
this.base = data.base;
|
||||
this.ratioUp = data.ratioUp;
|
||||
this.fixUp = data.fixUp;
|
||||
this.equipUp = data.equipUp;
|
||||
}
|
||||
|
||||
public updateAttr(update: { inc?: CeAttrUpdate, set?: CeAttrUpdate }) {
|
||||
if(update.inc) {
|
||||
let { base, equipUp, fixUp, ratioUp } = update.inc;
|
||||
if(base != undefined) this.base += base * HERO_CE_RATIO;
|
||||
if(equipUp != undefined) this.equipUp += equipUp * HERO_CE_RATIO;
|
||||
if(fixUp != undefined) this.fixUp += fixUp * HERO_CE_RATIO;
|
||||
if(ratioUp != undefined) this.ratioUp += ratioUp;
|
||||
}
|
||||
if(update.set) {
|
||||
let { base, equipUp, fixUp, ratioUp } = update.set;
|
||||
if(base != undefined) this.base = base * HERO_CE_RATIO;
|
||||
if(equipUp != undefined) this.equipUp = equipUp * HERO_CE_RATIO;
|
||||
if(fixUp != undefined) this.fixUp = fixUp * HERO_CE_RATIO;
|
||||
if(ratioUp != undefined) this.ratioUp = ratioUp;
|
||||
}
|
||||
}
|
||||
}
|
||||
import { gameData, getHeroExpByLv, getHeroInitTalent } from '../pubUtils/data';
|
||||
|
||||
/**
|
||||
* 英雄表
|
||||
@@ -88,12 +44,12 @@ export class HeroSkin {
|
||||
@prop({ required: true })
|
||||
usedTalentPoint: number; // 已使用的天赋点数
|
||||
|
||||
constructor(id: number, skinId: number, skin: string, enable: boolean) {
|
||||
this.id = id;
|
||||
this.skinId = skinId;
|
||||
this.skin = skin;
|
||||
constructor(skin: SkinUpdate, enable = true) {
|
||||
this.id = skin.id;
|
||||
this.skinId = skin.skinId;
|
||||
this.skin = skin._id;
|
||||
this.enable = enable;
|
||||
this.talent = getHeroInitTalent(skinId);
|
||||
this.talent = getHeroInitTalent(skin.skinId);
|
||||
this.usedTalentPoint = 0;
|
||||
}
|
||||
}
|
||||
@@ -111,7 +67,7 @@ export class EPlace {
|
||||
@prop({ required: true })
|
||||
equipId: number;
|
||||
@prop({ required: true })
|
||||
lv: number = 1;
|
||||
lv: number = 0;
|
||||
@prop({ required: true })
|
||||
quality: number = 1;
|
||||
@prop({ required: true })
|
||||
@@ -162,14 +118,8 @@ export default class Hero extends BaseModel {
|
||||
exp: number; // 经验值
|
||||
@prop({ required: true, default: 1 })
|
||||
lv: number; // 武将等级
|
||||
@prop({ required: true, default: 0, set: (val: number) => val, get: (val: number) => reduceCe(val) })
|
||||
ce: number; // 武将战力
|
||||
@prop({ required: false, set: (val: boolean) => val, get: () => true })
|
||||
isReducedCe: boolean; // 如果战力没有缩过就会返回false,缩过了就会返回true
|
||||
@prop({ required: true, default: 0 })
|
||||
historyCe: number; // 武将历史最高战力
|
||||
@prop({ required: true, type: CeAttrData, default: [], _id: false })
|
||||
attr: CeAttrData[]; // 影响战力的属性
|
||||
ce: number; // 武将战力
|
||||
|
||||
@prop({ required: true, default: 1 })
|
||||
star: number; // 星级
|
||||
@@ -274,39 +224,31 @@ export default class Hero extends BaseModel {
|
||||
return hero;
|
||||
}
|
||||
|
||||
public static getInitInfo(heroInfo: HeroUpdate = {}): HeroUpdate {
|
||||
public static getInitInfo(hid: number, heroInfo: HeroUpdate = {}): HeroUpdate {
|
||||
let dicHero = gameData.hero.get(hid)
|
||||
let { quality, initialStars: star, jobid: job, name: hName } = dicHero;
|
||||
const doc = new HeroModel();
|
||||
const update = { ...doc.toJSON(), ...heroInfo};
|
||||
const update = { ...doc.toJSON(), hid, skinId: hid, hName, star, quality, job, lv: DEFAULT_HERO_LV, exp: getHeroExpByLv(DEFAULT_HERO_LV - 1) || 0, ...heroInfo};
|
||||
delete update._id;
|
||||
return update
|
||||
}
|
||||
|
||||
public static async createHero(heroInfo: HeroUpdate, lean = true) {
|
||||
const seqId = await CounterModel.getNewCounter(COUNTER.HID) || -1;
|
||||
const update = this.getInitInfo({ ...heroInfo, seqId });
|
||||
const hero: HeroType = await HeroModel.findOneAndUpdate({ roleId: heroInfo.roleId, hid: heroInfo.hid }, update, { upsert: true, new: true }).lean(lean);
|
||||
return hero;
|
||||
}
|
||||
// public static async createHero(heroInfo: HeroUpdate, lean = true) {
|
||||
// const seqId = await CounterModel.getNewCounter(COUNTER.HID) || -1;
|
||||
// const update = this.getInitInfo(heroInfo.hid, { ...heroInfo, seqId });
|
||||
// const hero: HeroType = await HeroModel.findOneAndUpdate({ roleId: heroInfo.roleId, hid: heroInfo.hid }, update, { upsert: true, new: true }).lean(lean);
|
||||
// return hero;
|
||||
// }
|
||||
|
||||
public static async insertHeroes(roleId: string, roleName: string, serverId: number, heroInfos: HeroUpdate[]) {
|
||||
let insertInfos: HeroUpdate[] = [];
|
||||
for(let hero of heroInfos) {
|
||||
const seqId = await CounterModel.getNewCounter(COUNTER.HID) || -1;
|
||||
insertInfos.push({ ...hero, seqId, roleId, roleName, serverId })
|
||||
}
|
||||
await HeroModel.insertMany(insertInfos);
|
||||
return <HeroType[]>insertInfos;
|
||||
}
|
||||
|
||||
public static async sumTopHeroCe(roleId: string, num: number) {
|
||||
let ce: Array<{ historyCe: number }> = await HeroModel.aggregate([
|
||||
{ $match: { roleId } },
|
||||
{ $sort: { historyCe: -1 } },
|
||||
{ $limit: num },
|
||||
{ $group: { _id: null, historyCe: { $sum: '$historyCe' } } }
|
||||
]);
|
||||
return ce.length > 0 ? ce[0].historyCe : 0;
|
||||
}
|
||||
// public static async insertHeroes(roleId: string, roleName: string, serverId: number, heroInfos: HeroUpdate[]) {
|
||||
// let insertInfos: HeroUpdate[] = [];
|
||||
// for(let hero of heroInfos) {
|
||||
// const seqId = await CounterModel.getNewCounter(COUNTER.HID) || -1;
|
||||
// insertInfos.push({ ...hero, seqId, roleId, roleName, serverId })
|
||||
// }
|
||||
// await HeroModel.insertMany(insertInfos);
|
||||
// return <HeroType[]>insertInfos;
|
||||
// }
|
||||
|
||||
public static async sumHeroCe(roleId: string) {
|
||||
let ce: Array<{ ce: number }> = await HeroModel.aggregate([
|
||||
@@ -321,13 +263,6 @@ export default class Hero extends BaseModel {
|
||||
return heroes;
|
||||
}
|
||||
|
||||
public static async updateCe(roleId: string, hid: number, ce: number, oldCe: number, historyCe: number, lean = true) {
|
||||
let distance = ce - oldCe;
|
||||
let historyDistance = ce > historyCe ? ce - historyCe : 0;
|
||||
let result: HeroType = await HeroModel.findOneAndUpdate({ roleId, hid }, { $inc: { ce: distance, historyCe: historyDistance } }).lean(lean);
|
||||
return result;
|
||||
}
|
||||
|
||||
public static async deleteAccount(roleId: string) {
|
||||
let result = await HeroModel.deleteMany({ roleId });
|
||||
return result;
|
||||
@@ -340,7 +275,7 @@ export default class Hero extends BaseModel {
|
||||
|
||||
public static async updateHeroInfo(roleId: string, hid: number, heroUpdate: HeroUpdate, select?: string, getters = false) {
|
||||
delete heroUpdate._id;
|
||||
let result: HeroType = await HeroModel.findOneAndUpdate({ roleId, hid }, { $set: heroUpdate }, { new: true }).select(select).lean({ getters });
|
||||
let result: HeroType = await HeroModel.findOneAndUpdate({ roleId, hid }, { $set: heroUpdate }, { new: true, upsert: true }).select(select).lean({ getters });
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,42 +1,14 @@
|
||||
import { ROLE_TERAPH, ROLE_SELECT, ABI_TYPE, HERO_CE_RATIO, BLOCK_TYPE } from './../consts';
|
||||
import { ROLE_TERAPH, ROLE_SELECT, ABI_TYPE, BLOCK_TYPE } from './../consts';
|
||||
import BaseModel from './BaseModel';
|
||||
import { index, getModelForClass, prop, DocumentType, Ref, mongoose } from '@typegoose/typegoose';
|
||||
import User from './User';
|
||||
import { shouldRefresh, reduceCe } from '../pubUtils/util';
|
||||
import { shouldRefresh } from '../pubUtils/util';
|
||||
import { nowSeconds, getTimeFunD } from '../pubUtils/timeUtil';
|
||||
import { Figure } from '../domain/dbGeneral';
|
||||
import * as dicParam from '../pubUtils/dicParam';
|
||||
import Hero from './Hero';
|
||||
import { SearchRoleParam } from '../domain/backEndField/search';
|
||||
|
||||
type CeAttrUpdate = Partial<CeAttrDataRole>;
|
||||
// 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;
|
||||
}
|
||||
|
||||
public updateAttr(update: { inc?: CeAttrUpdate, set?: CeAttrUpdate }) {
|
||||
if(update.inc) {
|
||||
let { fixUp, ratioUp } = update.inc;
|
||||
if(fixUp != undefined) this.fixUp += fixUp * HERO_CE_RATIO;
|
||||
if(ratioUp != undefined) this.ratioUp += ratioUp;
|
||||
}
|
||||
if(update.set) {
|
||||
let { fixUp, ratioUp } = update.set;
|
||||
if(fixUp != undefined) this.fixUp = fixUp * HERO_CE_RATIO;
|
||||
if(ratioUp != undefined) this.ratioUp = ratioUp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class TopHero {
|
||||
@prop({ required: true })
|
||||
hid: number; // 武将id
|
||||
@@ -185,16 +157,12 @@ export default class Role extends BaseModel {
|
||||
exp: number; // 经验值
|
||||
@prop({ required: true, default: 1 })
|
||||
lv: number; // 主公等级
|
||||
@prop({ required: true, default: 0, set: (val: number) => val, get: (val: number) => reduceCe(val) })
|
||||
@prop({ required: true, default: 0 })
|
||||
ce: number; // 总战力
|
||||
@prop({ required: true, type: CeAttrDataRole, default: [], _id: false })
|
||||
attr: CeAttrDataRole[]; // 总战力
|
||||
@prop({ required: true, default: 0, set: (val: number) => val, get: (val: number) => reduceCe(val) })
|
||||
@prop({ required: true, default: 0 })
|
||||
topLineupCe: number; // 最强x人战力
|
||||
@prop({ required: true, type: TopHero, default: [], _id: false })
|
||||
topLineup: Array<TopHero>; // 总战力
|
||||
@prop({ required: false, set: (val: boolean) => val, get: () => true })
|
||||
isReducedCe: boolean; // 如果战力没有缩过就会返回false,缩过了就会返回true
|
||||
|
||||
@prop({ required: true, default: 100 })
|
||||
gold: number; // 总金币
|
||||
|
||||
122
shared/db/RoleCe.ts
Normal file
122
shared/db/RoleCe.ts
Normal file
@@ -0,0 +1,122 @@
|
||||
import BaseModel from './BaseModel';
|
||||
import { index, getModelForClass, prop, DocumentType } from '@typegoose/typegoose';
|
||||
|
||||
// 全局加成
|
||||
export class AttrCell {
|
||||
@prop({ required: true })
|
||||
attrId: number; // 属性id
|
||||
@prop({ required: true, type: Number })
|
||||
values: number[]; // 战力公式中的全局加成的数据,查表后的结果
|
||||
}
|
||||
|
||||
// 单武将加成
|
||||
export class HeroAttr {
|
||||
@prop({ required: true })
|
||||
hid: number; // 武将id
|
||||
@prop({ required: true })
|
||||
lv: number;
|
||||
@prop({ required: true, type: () => AttrCell, _id: false })
|
||||
attrs: AttrCell[];
|
||||
@prop({ required: true })
|
||||
historyCe: number;
|
||||
@prop({ required: true })
|
||||
objectId: string;
|
||||
}
|
||||
|
||||
export class EquipAttr {
|
||||
@prop({ required: true })
|
||||
hid: number; // 武将id
|
||||
@prop({ required: true })
|
||||
eplaceId: number; // 装备位置
|
||||
@prop({ required: true })
|
||||
lv: number;
|
||||
@prop({ required: true, type: () => AttrCell, _id: false })
|
||||
attrs: AttrCell[];
|
||||
}
|
||||
|
||||
// 百家学宫加成
|
||||
export class SchoolAttr {
|
||||
@prop({ required: true })
|
||||
hid: number; // 武将id
|
||||
@prop({ required: true })
|
||||
attrId: number; // 属性id
|
||||
@prop({ required: true })
|
||||
value: number; // 百家学宫有多个武将,单独拎出来方便计算,计算之后结果存到globaAttrs的global1
|
||||
}
|
||||
|
||||
// 名将谱加成
|
||||
export class ScrollAttr {
|
||||
@prop({ required: true })
|
||||
hid: number; // 武将id
|
||||
@prop({ required: true })
|
||||
attrId: number; // 属性id
|
||||
@prop({ required: true })
|
||||
value: number; // 百家学宫有多个武将,单独拎出来方便计算,计算之后结果存到globaAttrs的global1
|
||||
}
|
||||
|
||||
|
||||
// 属性结果
|
||||
export class SingleAttribute {
|
||||
@prop({ required: true })
|
||||
id: number; // 属性id
|
||||
@prop({ required: true })
|
||||
val: number; // 值
|
||||
@prop({ required: true })
|
||||
str: string; // 公式
|
||||
}
|
||||
|
||||
export class Attribute {
|
||||
@prop({ required: true })
|
||||
hid: number;
|
||||
@prop({ required: true, type: SingleAttribute, _id: false })
|
||||
attrs: SingleAttribute[]; // 属性id
|
||||
}
|
||||
|
||||
/**
|
||||
* 属性表
|
||||
*/
|
||||
|
||||
@index({ roleId: 1 })
|
||||
@index({ roleId: 1 })
|
||||
|
||||
export default class RoleCe extends BaseModel {
|
||||
|
||||
@prop({ required: true })
|
||||
roleId: string; // 角色 id
|
||||
|
||||
@prop({ required: true })
|
||||
roleLv: number; // 玩家等级
|
||||
|
||||
@prop({ required: true, type: AttrCell, _id: false })
|
||||
globalAttrs: AttrCell[]
|
||||
|
||||
@prop({ required: true, type: HeroAttr, _id: false })
|
||||
heroAttrs: HeroAttr[]
|
||||
|
||||
@prop({ required: true, type: EquipAttr, _id: false })
|
||||
equipAttrs: EquipAttr[]
|
||||
|
||||
@prop({ required: true, type: SchoolAttr, _id: false })
|
||||
schoolAttrs: SchoolAttr[];
|
||||
|
||||
@prop({ required: true, type: ScrollAttr, _id: false })
|
||||
scrollAttrs: ScrollAttr[];
|
||||
|
||||
@prop({ required: true, type: Attribute, _id: false })
|
||||
attributes: Attribute[];
|
||||
|
||||
public static async findByRoleId(roleId: string) {
|
||||
let result: RoleCeType = await RoleCeModel.findOne({ roleId }).lean();
|
||||
return result;
|
||||
}
|
||||
|
||||
public static async updateRoleCe(roleId: string, update: RoleCeUpdate) {
|
||||
let result: RoleCeType = await RoleCeModel.findOneAndUpdate({ roleId }, { $set: update }, { new: true, upsert: true }).lean();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
export const RoleCeModel = getModelForClass(RoleCe);
|
||||
|
||||
export interface RoleCeType extends Pick<DocumentType<RoleCe>, keyof RoleCe> { };
|
||||
export type RoleCeUpdate = Partial<RoleCeType>;
|
||||
@@ -1,5 +1,6 @@
|
||||
import BaseModel from './BaseModel';
|
||||
import { index, getModelForClass, prop, DocumentType, modelOptions } from '@typegoose/typegoose';
|
||||
import { gameData } from '../pubUtils/data';
|
||||
@index({ roleId: 1, id: 1 })
|
||||
@index({ seqId: 1 })
|
||||
@modelOptions({ schemaOptions: { id: false } })
|
||||
@@ -28,6 +29,15 @@ export default class Skin extends BaseModel {
|
||||
return rec;
|
||||
}
|
||||
|
||||
public static getInitInfo(hid: number): SkinUpdate {
|
||||
let dicHero = gameData.hero.get(hid);
|
||||
let dicFashion = gameData.fashion.get(dicHero.initialSkin)
|
||||
const doc = new SkinModel();
|
||||
const update = { ...doc.toJSON(), id: dicFashion.id, skinId: dicFashion.heroId, skinName: dicFashion.name, hid};
|
||||
delete update._id;
|
||||
return update
|
||||
}
|
||||
|
||||
public static async insertSkins(roleId: string, roleName: string, skinInfos: SkinUpdate[]) {
|
||||
let insertInfos: SkinUpdate[] = [];
|
||||
for(let skinInfo of skinInfos) {
|
||||
|
||||
@@ -65,10 +65,15 @@ export default class User extends BaseModel {
|
||||
guestTime: number; // 游客体验时间
|
||||
|
||||
// 防沉迷相关
|
||||
@prop({ required: false, default: false })
|
||||
@prop({ required: false, default: true })
|
||||
hasAuthenticated: boolean; // 是否是已认证
|
||||
@prop({ required: false })
|
||||
@prop({ required: false, default: '1990-01-01' })
|
||||
birthday: string; // 生日年月
|
||||
// 暂时不使用内部防沉迷
|
||||
// @prop({ required: false, default: false })
|
||||
// hasAuthenticated: boolean; // 是否是已认证
|
||||
// @prop({ required: false })
|
||||
// birthday: string; // 生日年月
|
||||
@prop({ required: false })
|
||||
pi: string; // 已通过实名认证用户唯一标识
|
||||
@prop({ required: false, default: 0 })
|
||||
|
||||
@@ -4,7 +4,7 @@ import { DungeonFirstType } from '../../db/DungeonFirst';
|
||||
class DungeonUserInfo extends RankParam {
|
||||
roleId: string;
|
||||
constructor(roleId: string, userInfo: RankParam) {
|
||||
super(userInfo, false);
|
||||
super(userInfo);
|
||||
this.roleId = roleId;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { EXTERIOR } from "../pubUtils/dicParam";
|
||||
import { WoodenHorse } from "./battleField/guildActivity";
|
||||
import { RoleUpdate, RoleType } from "../db/Role";
|
||||
import { reduceCe } from "../pubUtils/util";
|
||||
import { GuildUpdateParam } from "../db/Guild";
|
||||
import { HeroUpdate, } from "../db/Hero";
|
||||
import { getSeconds } from "../pubUtils/timeUtil";
|
||||
@@ -38,7 +37,7 @@ export class RankParam {
|
||||
@prop({ required: true })
|
||||
updatedAt?: number = 0;
|
||||
|
||||
constructor(role: RoleUpdate|RankParam, fromDb: boolean) {
|
||||
constructor(role: RoleUpdate|RankParam) {
|
||||
if(role.roleName) this.roleName = role.roleName;
|
||||
if(role.lv) this.lv = role.lv;
|
||||
if(role.head) this.head = role.head;
|
||||
@@ -46,13 +45,7 @@ export class RankParam {
|
||||
if(role.spine) this.spine = role.spine;
|
||||
if(role.title) this.title = role.title;
|
||||
if(role.guildName) this.guildName = role.guildName||"";
|
||||
if(role.ce) {
|
||||
if(fromDb && !(<RoleUpdate>role).isReducedCe) {
|
||||
this.ce = reduceCe(role.ce);
|
||||
} else {
|
||||
this.ce = role.ce;
|
||||
}
|
||||
}
|
||||
if(role.ce) this.ce = role.ce;
|
||||
if(role.updatedAt) {
|
||||
if(typeof role.updatedAt == 'number') {
|
||||
this.updatedAt = role.updatedAt;
|
||||
@@ -178,27 +171,14 @@ export class GuildRankParam {
|
||||
@prop({ required: true })
|
||||
guildCe: number;
|
||||
|
||||
constructor(guild: GuildUpdateParam, fromDb: boolean) {
|
||||
constructor(guild: GuildUpdateParam) {
|
||||
this.icon = guild.icon;
|
||||
this.name = guild.name;
|
||||
this.lv = guild.lv;
|
||||
let leader = <RoleType>guild.leader;
|
||||
let _leader = new GuildLeader(leader);
|
||||
this.leader = _leader;
|
||||
// console.log('*****', guild.isReducedCe, guild.guildCe, reduceCe(guild.guildCe))
|
||||
if(guild.isReducedCe) {
|
||||
this.guildCe = guild.guildCe;
|
||||
} else {
|
||||
this.guildCe = reduceCe(guild.guildCe);
|
||||
}
|
||||
|
||||
if(fromDb && !(<GuildUpdateParam>guild).isReducedCe) {
|
||||
this.guildCe = reduceCe(guild.guildCe);
|
||||
} else {
|
||||
this.guildCe = guild.guildCe;
|
||||
}
|
||||
|
||||
|
||||
this.guildCe = guild.guildCe;
|
||||
this.memberCnt = guild.memberCnt;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
import { HERO_CE_RATIO, getAtrrNameById, ABI_TYPE_MAIN } from '../../consts';
|
||||
import { CeAttrDataRole } from '../../db/Role';
|
||||
import { CeAttrData } from '../../db/Hero';
|
||||
import { getAtrrNameById, ABI_TYPE_MAIN } from '../../consts';
|
||||
import { gameData } from '../../pubUtils/data';
|
||||
import { decodeArrayListStr, reduceCe } from '../../pubUtils/util';
|
||||
import { decodeArrayListStr } from '../../pubUtils/util';
|
||||
import { ATTRIBUTE } from '../../pubUtils/dicParam';
|
||||
|
||||
export class AttributeCal {
|
||||
@@ -14,34 +12,12 @@ export class AttributeCal {
|
||||
this.lv = lv;
|
||||
}
|
||||
|
||||
public setByDbData(roleAttrs: CeAttrDataRole[], heroAttrs: CeAttrData[]) {
|
||||
for(let { id, fixUp: roleFix, ratioUp: roleRatio } of roleAttrs) {
|
||||
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);
|
||||
this.attrs.set(id, value);
|
||||
} else {
|
||||
let value = this.calAttrValue(roleFix, roleRatio, 0, 0, 0, 0);
|
||||
this.attrs.set(id, value);
|
||||
}
|
||||
}
|
||||
|
||||
for(let { id, base: heroBase, fixUp: heroFix, ratioUp: heroRatio, equipUp: heroEquip } of heroAttrs) {
|
||||
let roleAttr = roleAttrs.find(roleAttr => roleAttr.id == id);
|
||||
if(!roleAttr) {
|
||||
let value = this.calAttrValue(0, 0, heroBase, heroFix, heroRatio, heroEquip);
|
||||
this.attrs.set(id, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public setByWarJson(attributes: {id: number, val: number}[], ratio: number = 1) {
|
||||
for(let {id, val} of attributes) {
|
||||
if(ABI_TYPE_MAIN.includes(id)) {
|
||||
this.attrs.set(id, Math.floor(val * ratio * HERO_CE_RATIO * HERO_CE_RATIO));
|
||||
this.attrs.set(id, Math.floor(val * ratio));
|
||||
} else {
|
||||
this.attrs.set(id, Math.floor(val * HERO_CE_RATIO * HERO_CE_RATIO));
|
||||
this.attrs.set(id, Math.floor(val));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -49,58 +25,42 @@ export class AttributeCal {
|
||||
public setByMap( attributes: Map<number, number>, ratio: number = 1 ) {
|
||||
for(let [id, val] of attributes) {
|
||||
if(ABI_TYPE_MAIN.includes(id)) {
|
||||
this.attrs.set(id, Math.floor(val * ratio * HERO_CE_RATIO * HERO_CE_RATIO));
|
||||
this.attrs.set(id, Math.floor(val * ratio));
|
||||
} else {
|
||||
this.attrs.set(id, Math.floor(val * HERO_CE_RATIO * HERO_CE_RATIO));
|
||||
this.attrs.set(id, Math.floor(val));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 getRealAttrToMap() {
|
||||
// let newMap = new Map<number, number>();
|
||||
// for(let [id, val] of this.attrs) {
|
||||
// if(ABI_TYPE_MAIN.includes(id)) { // 主属性
|
||||
// newMap.set(id, val / HERO_CE_RATIO / HERO_CE_RATIO);
|
||||
// } else {
|
||||
// newMap.set(id, val / HERO_SUB_ATTR_RATIO / HERO_CE_RATIO / HERO_CE_RATIO);
|
||||
// }
|
||||
// }
|
||||
// return newMap;
|
||||
// }
|
||||
|
||||
private getReduceAttrMap() {
|
||||
private getAttrMap() {
|
||||
let newMap = new Map<number, number>();
|
||||
for(let [id, val] of this.attrs) {
|
||||
newMap.set(id, reduceCe(val));
|
||||
newMap.set(id, val);
|
||||
}
|
||||
return newMap
|
||||
}
|
||||
|
||||
public getReduceAttributes() {
|
||||
public getAttributes() {
|
||||
let attrs = new Attribute();
|
||||
attrs.setByMap(this.getReduceAttrMap());
|
||||
attrs.setByMap(this.getAttrMap());
|
||||
return attrs;
|
||||
}
|
||||
|
||||
public getReduceAttributesToArr() {
|
||||
public getAttributesToArr() {
|
||||
let arr: {id: number, val: number}[] = [];
|
||||
for(let [id, val] of this.getReduceAttrMap()) {
|
||||
for(let [id, val] of this.getAttrMap()) {
|
||||
arr.push({ id, val });
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
|
||||
public getReduceAttributesToString() {
|
||||
let arr = this.getReduceAttributesToArr();
|
||||
public getAttributesToString() {
|
||||
let arr = this.getAttributesToArr();
|
||||
return arr.map(cur => `${cur.id}&${cur.val}`).join('|');
|
||||
}
|
||||
|
||||
public getReduceMainAttributes() {
|
||||
let attribute = this.getReduceAttributes();
|
||||
public getMainAttributes() {
|
||||
let attribute = this.getAttributes();
|
||||
return attribute.getMainAttr();
|
||||
}
|
||||
|
||||
@@ -126,12 +86,8 @@ export class AttributeCal {
|
||||
return Math.floor(ce);
|
||||
}
|
||||
|
||||
public calSubAttrCeAndReduce() {
|
||||
return Math.floor(this.calCe(3) / HERO_CE_RATIO / HERO_CE_RATIO);
|
||||
}
|
||||
|
||||
public calCelAndReduce() {
|
||||
return Math.floor(this.calCe() / HERO_CE_RATIO / HERO_CE_RATIO);
|
||||
public calSubAttrCe() {
|
||||
return Math.floor(this.calCe(3));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,249 +0,0 @@
|
||||
import { ABI_STAGE, ABI_STAGE_TO_TYPE, ABI_TYPE, ABI_TYPE_MAIN, HERO_CE_RATIO, HERO_SYSTEM_TYPE, SEID_TYPE } from "../../consts";
|
||||
import { HeroModel, HeroUpdate, CeAttrData } from "../../db/Hero";
|
||||
import { CeAttrDataRole, RoleUpdate } from "../../db/Role";
|
||||
import { gameData, getHeroStarByQuality, getHeroWakeByQuality } from "../../pubUtils/data";
|
||||
import { DicRandomEffectPool } from "../../pubUtils/dictionary/DicRandomEffectPool";
|
||||
import { DicSe } from "../../pubUtils/dictionary/DicSe";
|
||||
import { deepCopy } from "../../pubUtils/util";
|
||||
import { AttributeCal } from "./attribute";
|
||||
|
||||
export class CalRoleCe {
|
||||
private roleInfo: RoleUpdate;
|
||||
private roleCeWithAttr: Map<ABI_TYPE, CeAttrDataRole> = new Map();
|
||||
|
||||
constructor(roleInfo?: RoleUpdate) {
|
||||
this.roleInfo = roleInfo;
|
||||
}
|
||||
|
||||
public cal(type: HERO_SYSTEM_TYPE) {
|
||||
switch (type) {
|
||||
case HERO_SYSTEM_TYPE.INIT:
|
||||
this.calTitleAbility();
|
||||
this.calTeraphMainAttr();
|
||||
break;
|
||||
}
|
||||
return this.getRoleAttr();
|
||||
}
|
||||
|
||||
private calTitleAbility() {
|
||||
let { title } = this.roleInfo;
|
||||
|
||||
let dicTitle = gameData.title.get(title)||{ mainAttrValue: new Map(), assiAttrValue: new Map() };
|
||||
|
||||
for (let i = ABI_TYPE.ABI_HP; i < ABI_TYPE.ABI_MAX; i++) {
|
||||
if (dicTitle.mainAttrValue.has(i)) {
|
||||
let fixUp = dicTitle.mainAttrValue.get(i) || 0;
|
||||
this.getSingleAttrObj(i).updateAttr({ inc: { fixUp } });
|
||||
}
|
||||
if (dicTitle.assiAttrValue.has(i)) {
|
||||
let fixUp = dicTitle.assiAttrValue.get(i) || 0;
|
||||
this.getSingleAttrObj(i).updateAttr({ inc: { fixUp } });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private calTeraphMainAttr(id?: number) {
|
||||
let { teraphs = [] } = this.roleInfo;
|
||||
for(let teraph of teraphs) {
|
||||
if(id == undefined || teraph.id == id) {
|
||||
for(let [attrId, val] of teraph.attr) {
|
||||
this.getSingleAttrObj(attrId).updateAttr({ inc: { fixUp: val } });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 获取一个CeAttrData对象,没有就新建
|
||||
public getSingleAttrObj(attrId: ABI_TYPE) {
|
||||
if(!this.roleCeWithAttr.has(attrId)) {
|
||||
let calSingleAttr = new CeAttrDataRole(attrId);
|
||||
this.roleCeWithAttr.set(attrId, calSingleAttr);
|
||||
}
|
||||
return this.roleCeWithAttr.get(attrId);
|
||||
}
|
||||
|
||||
private getRoleAttr() {
|
||||
let attr: CeAttrDataRole[] = [];
|
||||
this.roleCeWithAttr.forEach(value => {
|
||||
if(value.ratioUp > 0 || value.fixUp > 0) {
|
||||
attr.push(value);
|
||||
}
|
||||
});
|
||||
return attr;
|
||||
}
|
||||
}
|
||||
|
||||
export class CalHeroCe {
|
||||
private hid: number;
|
||||
private heroInfo: HeroUpdate;
|
||||
private heroCeWithAttr: Map<ABI_TYPE, CeAttrData> = new Map();
|
||||
|
||||
constructor(hid: number, heroInfo?: HeroUpdate) {
|
||||
this.hid = hid;
|
||||
if(heroInfo) this.heroInfo = heroInfo;
|
||||
}
|
||||
|
||||
public async setHeroInfoByHid(roleId: string) {
|
||||
let hero = await HeroModel.findByHidAndRole(this.hid, roleId);
|
||||
this.heroInfo = hero;
|
||||
}
|
||||
|
||||
// 主要接口
|
||||
public cal(type: HERO_SYSTEM_TYPE) {
|
||||
switch (type) {
|
||||
case HERO_SYSTEM_TYPE.INIT:
|
||||
case HERO_SYSTEM_TYPE.REBIRTH:
|
||||
this.calBaseAbility();
|
||||
this.calSkinSeid();
|
||||
this.calJobAbility();
|
||||
break;
|
||||
}
|
||||
return this.getHeroAttr()
|
||||
}
|
||||
|
||||
// 计算基础属性
|
||||
private calBaseAbility() {
|
||||
let { star, starStage, quality, colorStar, colorStarStage, lv, skinId } = this.heroInfo;
|
||||
const dicHero = gameData.hero.get(skinId);
|
||||
if(!dicHero) {
|
||||
console.error(`not found hero: ${skinId}`);
|
||||
return;
|
||||
}
|
||||
|
||||
for (let stage = ABI_STAGE.START + 1; stage <= ABI_STAGE.END; stage++) {
|
||||
let attrId = ABI_STAGE_TO_TYPE.get(stage);
|
||||
|
||||
const isWake = colorStar > 0; // 是否觉醒,只要激活了觉醒,彩星就会 > 1
|
||||
// console.log('*isUpstar', isUpStar, originStar, star, originColorStar, colorStar)
|
||||
|
||||
const dicStar = isWake ? getHeroWakeByQuality(dicHero.jobClass, dicHero.quality, colorStarStage < stage? colorStar - 1: colorStar) : getHeroStarByQuality(dicHero.jobClass, quality, starStage < stage? star - 1: star); // 星级表
|
||||
|
||||
let heroAttr = dicHero.baseAbilityArr.get(attrId); // 武将表hp等
|
||||
let heroUpAttr = dicHero.baseAbilityUpArr.get(attrId); // 武将表hp_up等
|
||||
let starUp = 0; // 星级成长
|
||||
if (!!dicStar && !!dicStar.ceAttr) {
|
||||
starUp = dicStar.ceAttr.get(stage);
|
||||
}
|
||||
let base = heroAttr + lv * (heroUpAttr + starUp);
|
||||
this.getSingleAttrObj(attrId).updateAttr({ set: { base } });
|
||||
};
|
||||
}
|
||||
|
||||
// 计算职业属性
|
||||
private calJobAbility() {
|
||||
let { job, jobStage } = this.heroInfo;
|
||||
|
||||
const dicJob = gameData.job.get(job);
|
||||
for(let i = 1; i <= dicJob.maxStage; i++) {
|
||||
if(jobStage >= i) {
|
||||
let { id, attr } = dicJob.ceAttr.get(i);
|
||||
this.getSingleAttrObj(id).updateAttr({ inc: { fixUp: attr } });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 计算皮肤属性
|
||||
private calSkinSeid() {
|
||||
let { skinId, star: _star, colorStar: _colorStar } = this.heroInfo;
|
||||
|
||||
let seidList = new Map<number, number>(); // type => seid
|
||||
let dicHero = gameData.hero.get(skinId);
|
||||
let { starSeidArr, colorStarSeidArr } = gameData.heroSkill.get(dicHero.skill);
|
||||
for (let { star, value, type } of starSeidArr) {
|
||||
if (_star >= star) {
|
||||
seidList.set(type, value);
|
||||
}
|
||||
}
|
||||
for (let { star, value, type } of colorStarSeidArr) {
|
||||
if (_colorStar >= star) {
|
||||
seidList.set(type, value);
|
||||
}
|
||||
}
|
||||
let list: number[] = [];
|
||||
for(let [_type, value] of seidList) list.push(value);
|
||||
addSeidEffect.bind(this, list);
|
||||
}
|
||||
|
||||
public getHeroAttr() {
|
||||
let attr: CeAttrData[] = [];
|
||||
this.heroCeWithAttr.forEach(value => {
|
||||
if(value.base > 0 || value.equipUp > 0 || value.fixUp > 0 || value.ratioUp > 0) {
|
||||
attr.push(value);
|
||||
}
|
||||
});
|
||||
return attr;
|
||||
}
|
||||
|
||||
// 获取一个CeAttrData对象,没有就新建
|
||||
public getSingleAttrObj(attrId: ABI_TYPE) {
|
||||
if(!this.heroCeWithAttr.has(attrId)) {
|
||||
let calSingleAttr = new CeAttrData(attrId);
|
||||
this.heroCeWithAttr.set(attrId, calSingleAttr);
|
||||
}
|
||||
return this.heroCeWithAttr.get(attrId);
|
||||
}
|
||||
|
||||
public getCalculatedCe(roleAttr: CeAttrDataRole[]) {
|
||||
let attrCal = new AttributeCal();
|
||||
attrCal.setLv(this.heroInfo.lv);
|
||||
attrCal.setByDbData(roleAttr, this.getHeroAttr());
|
||||
return attrCal.calCe();
|
||||
}
|
||||
}
|
||||
|
||||
// 添加技能增加的被动属性
|
||||
function addSeidEffect(this: CalRoleCe|CalHeroCe, seidList: number[]) {
|
||||
// console.log('******addSeidEffect',this, seidList)
|
||||
|
||||
// console.log('addSeidList', addSeidList.join())
|
||||
// console.log('removeSeidList', removeSeidList.join())
|
||||
let effectList: DicSe[] = []; // any: dic_zyz_se表内容
|
||||
|
||||
for (let ii = 0; ii < seidList.length; ii += 2) {
|
||||
let seid = seidList[ii];
|
||||
let rand = seidList[ii + 1] || 0;
|
||||
let dicSeid: DicSe | DicRandomEffectPool = gameData.se.get(seid);
|
||||
if (!dicSeid) dicSeid = gameData.randomEffectPool.get(seid);
|
||||
if (dicSeid && dicSeid.id > 0) {
|
||||
addSeid(effectList, dicSeid.id, rand, dicSeid.gainValueArr)
|
||||
}
|
||||
}
|
||||
|
||||
// console.log('effectList', JSON.stringify(effectList));
|
||||
for (let { type, gainValueArr: [ability, value] } of effectList) {
|
||||
if (type == SEID_TYPE.TYPE101) { // 加值
|
||||
this.getSingleAttrObj(ability).updateAttr({ inc: { fixUp: value } });
|
||||
} else if (type == SEID_TYPE.TYPE103) { // 主属性加百分比
|
||||
if(ABI_TYPE_MAIN.includes(ability)) {
|
||||
this.getSingleAttrObj(ability).updateAttr({ inc: {ratioUp: value / 1000} });
|
||||
}
|
||||
} else if (type == SEID_TYPE.TYPE104) { // 次级属性加百分比
|
||||
if(!ABI_TYPE_MAIN.includes(ability)) {
|
||||
this.getSingleAttrObj(ability).updateAttr({ inc: { fixUp: value * 100 * HERO_CE_RATIO } });
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 获取dic_zyz_se内容
|
||||
function addSeid(effectList: (DicSe | DicRandomEffectPool)[], seidId: number, rand: number, seidValue: number[] = []) {
|
||||
let curSeid: DicSe | DicRandomEffectPool = gameData.se.get(seidId);
|
||||
if (!curSeid) curSeid = gameData.randomEffectPool.get(seidId);
|
||||
if (!curSeid) { console.log("seidId not found:" + seidId); return; }
|
||||
if (!seidValue) seidValue = curSeid.gainValueArr;
|
||||
|
||||
if (curSeid.type === SEID_TYPE.TYPE999) {
|
||||
for (let i = 0; i < seidValue.length; i++) {
|
||||
addSeid(effectList, seidValue[i], rand);
|
||||
}
|
||||
return;
|
||||
}
|
||||
let seid: DicSe | DicRandomEffectPool = deepCopy(curSeid);
|
||||
if (curSeid.index > 0) {
|
||||
seid.gainValueArr[curSeid.index - 1] = rand;
|
||||
}
|
||||
effectList.push(seid);
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
|
||||
import { Connect, EPlace, HeroSkin, HeroType, HeroUpdate, Talent } from '../../db/Hero';
|
||||
import { gameData } from '../../pubUtils/data';
|
||||
import { reduceCe } from '../../pubUtils/util';
|
||||
export interface CreateHeroParam extends HeroUpdate {
|
||||
hid: number;
|
||||
count: number;
|
||||
@@ -41,7 +40,6 @@ export class HeroParam {
|
||||
exp: number; // 经验值
|
||||
lv: number; // 武将等级
|
||||
ce: number; // 武将战力
|
||||
historyCe: number; // 武将历史最高战力
|
||||
star: number; // 星级
|
||||
starStage: number; // 星级六维阶段
|
||||
colorStar: number; // 觉醒, 彩星
|
||||
@@ -74,13 +72,7 @@ export class HeroParam {
|
||||
this.hName = hero.hName;
|
||||
this.exp = hero.exp;
|
||||
this.lv = hero.lv;
|
||||
if(hero.isReducedCe) {
|
||||
this.ce = hero.ce;
|
||||
this.historyCe = hero.historyCe;
|
||||
} else {
|
||||
this.ce = reduceCe(hero.ce);
|
||||
this.historyCe = reduceCe(hero.historyCe);
|
||||
}
|
||||
this.ce = hero.ce;
|
||||
this.star = hero.star;
|
||||
this.starStage = hero.starStage;
|
||||
this.colorStar = hero.colorStar;
|
||||
|
||||
@@ -103,6 +103,7 @@ import { dicJewelCondition, loadJewelCondition } from './dictionary/DicJewelCond
|
||||
import { dicMainStarBox, dicMainStarBoxByChapter, loadMainStarBox } from './dictionary/DicMainStarBox';
|
||||
import { dicHeroTalent, initTalents, loadHeroTalent } from './dictionary/DicHeroTalent';
|
||||
import { Talent } from "../db/Hero";
|
||||
import { dicEquipStrengthAttr, loadEquipStrengthAttr } from './dictionary/DicEquipStrengthAttr';
|
||||
|
||||
export const gameData = {
|
||||
daily: dicDaily,
|
||||
@@ -257,6 +258,7 @@ export const gameData = {
|
||||
heroTalent: dicHeroTalent,
|
||||
initTalents: initTalents,
|
||||
talentPointOfJob: talentPointOfJob,
|
||||
equipStrengthAttr: dicEquipStrengthAttr
|
||||
};
|
||||
|
||||
// 在此提供一些原先在gamedata中提供的方法,以便更方便获取gameData数据
|
||||
@@ -333,7 +335,7 @@ export function getBossHpByWarId(warId: number) {
|
||||
if (relation === 2) {
|
||||
let newAttr = new AttributeCal();
|
||||
newAttr.setByWarJson(attribute, 1);
|
||||
let attrJson = newAttr.getReduceAttributes();
|
||||
let attrJson = newAttr.getAttributes();
|
||||
|
||||
const hp = attrJson.hp || 0;
|
||||
if (hp > 0) {
|
||||
@@ -882,6 +884,11 @@ export function getHeroInitTalent(skinId: number) {
|
||||
return ids.map(id => (new Talent(id)));
|
||||
}
|
||||
|
||||
export function getEquipStrenthenAttr(equipId: number, lv: number) {
|
||||
let result = gameData.equipStrengthAttr.get(`${equipId}_${lv}`);
|
||||
return result
|
||||
}
|
||||
|
||||
// 初始加载
|
||||
function initDatas() {
|
||||
parseDicParam();
|
||||
@@ -1049,6 +1056,7 @@ function loadDatas() {
|
||||
loadJewelCondition();
|
||||
loadMainStarBox();
|
||||
loadHeroTalent();
|
||||
loadEquipStrengthAttr();
|
||||
}
|
||||
|
||||
// 重载dicParam
|
||||
|
||||
39
shared/pubUtils/dictionary/DicEquipStrengthAttr.ts
Normal file
39
shared/pubUtils/dictionary/DicEquipStrengthAttr.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
// 装备强化表
|
||||
import { readFileAndParse, decodeArrayListStr } from '../util'
|
||||
import { FILENAME } from '../../consts'
|
||||
|
||||
export interface DicEquipStrengthAttr {
|
||||
// id
|
||||
readonly id: number;
|
||||
// 装备id
|
||||
readonly equipId: number;
|
||||
// 等级
|
||||
readonly lv: number;
|
||||
// 属性
|
||||
readonly attr: {id: number, num: number}[];
|
||||
}
|
||||
|
||||
export const dicEquipStrengthAttr = new Map<string, DicEquipStrengthAttr>();
|
||||
export function loadEquipStrengthAttr() {
|
||||
dicEquipStrengthAttr.clear();
|
||||
let arr = readFileAndParse(FILENAME.DIC_EQUIP_STRENGTH_ATTR);
|
||||
|
||||
arr.forEach(o => {
|
||||
o.attr = parseAttr(o.attr);
|
||||
dicEquipStrengthAttr.set(`${o.equipId}_${o.lv}`, o);
|
||||
});
|
||||
arr = undefined;
|
||||
}
|
||||
|
||||
function parseAttr(str: string) {
|
||||
let result = new Array<{id: number, num: number}>();
|
||||
if(!str) return result;
|
||||
let decodeArr = decodeArrayListStr(str);
|
||||
for(let [id, num] of decodeArr) {
|
||||
if(isNaN(parseInt(id)) || isNaN(parseInt(num))) {
|
||||
throw new Error('data table format wrong');
|
||||
}
|
||||
result.push({id: parseInt(id), num: parseInt(num)});
|
||||
}
|
||||
return result
|
||||
}
|
||||
@@ -10,7 +10,7 @@ export interface DicEquipSuit {
|
||||
// 套装内含的装备编号
|
||||
readonly equips: number[];
|
||||
// 按星级可解锁的属性
|
||||
readonly effect: { star: number, seid: number }[];
|
||||
readonly effect: { star: number, id: number, val: number }[];
|
||||
}
|
||||
|
||||
export const dicEquipSuit = new Map<number, DicEquipSuit>();
|
||||
@@ -30,14 +30,14 @@ export function loadEquipSuit() {
|
||||
}
|
||||
|
||||
function parseEffect(str: string) {
|
||||
let result = new Array<{star: number, seid: number}>();
|
||||
let result = new Array<{star: number, id: number, val: number}>();
|
||||
if(!str) return result;
|
||||
let decodeArr = decodeArrayListStr(str);
|
||||
for(let [star, seid] of decodeArr) {
|
||||
if(isNaN(parseInt(star)) || isNaN(parseInt(seid))) {
|
||||
for(let [star, id, val] of decodeArr) {
|
||||
if(isNaN(parseInt(star)) || isNaN(parseInt(id)) || isNaN(parseInt(val))) {
|
||||
throw new Error('data table format wrong');
|
||||
}
|
||||
result.push({star: parseInt(star), seid: parseInt(seid)});
|
||||
result.push({star: parseInt(star), id: parseInt(id), val: parseInt(val)});
|
||||
}
|
||||
return result
|
||||
}
|
||||
@@ -23,8 +23,10 @@ export interface DicJob {
|
||||
readonly trainingConsume: Array<RewardInter>;
|
||||
// 升阶消耗
|
||||
readonly upGradeConsume: Array<RewardInter>;
|
||||
// 每阶升级属性
|
||||
// 每阶升级属性 stage => {}
|
||||
readonly ceAttr: Map<number, {id: number, attr: number}>;
|
||||
// 次级属性基础 attr => value attr1
|
||||
readonly baseSubAttr: {id: number, val: number}[];
|
||||
// 一共有多少阶升级
|
||||
readonly maxStage: number;
|
||||
// 到这一阶能获得多少天赋点
|
||||
@@ -32,7 +34,7 @@ export interface DicJob {
|
||||
}
|
||||
|
||||
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, trainingConsume: true, upGradeConsume: true, ceAttr: true, maxStage: true, talentPoint: true};
|
||||
const DicJobKeys: KeysEnum<DicJob> = {jobid: true, name: true, grade: true, unlockLevel: true, job_class: true, type: true, trainingConsume: true, upGradeConsume: true, ceAttr: true, maxStage: true, talentPoint: true, baseSubAttr: true};
|
||||
|
||||
export const dicJob = new Map<number, DicJob>();
|
||||
export const jobClassMaxGrades = new Map<number, {grade:number, jobid:number}>();
|
||||
@@ -54,6 +56,7 @@ export function loadJob() {
|
||||
o.maxStage = o.trainingConsume.length;
|
||||
o.upGradeConsume = parseGoodStr(o.upGradeConsume);
|
||||
o.ceAttr = parseCeAttr(o.maxStage, o.attr);
|
||||
o.baseSubAttr = parseAttribute(o.baseSecondAttr||'');
|
||||
dicJob.set(o.jobid, _.pick(o, Object.keys(DicJobKeys)));
|
||||
let jobClass = jobClassMaxGrades.get(o.job_class);
|
||||
if (!jobClass || jobClass.grade < o.grade) {
|
||||
@@ -93,4 +96,17 @@ function parseCeAttr(maxStage: number, str: string) {
|
||||
result.set(i, { id: parseInt(id), attr: parseFloat(attr) });
|
||||
}
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
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');
|
||||
}
|
||||
result.push({ id: parseInt(id), val: parseInt(val) });
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ export function loadRandomEffectPool() {
|
||||
|
||||
arr.forEach(o => {
|
||||
o.rate = parseRate(o.count);
|
||||
o.gainValueArr = parseNumberList(o.gainvalue);
|
||||
o.gainValueArr = parseNumberList(o.gainValue);
|
||||
dicRandomEffectPool.set(o.id, o);
|
||||
dicRandomEffectPoolByGroupAndLv.set(`${o.group}_${o.level}`, o.id);
|
||||
});
|
||||
|
||||
@@ -23,6 +23,7 @@ export interface DicTeraph {
|
||||
readonly upMaterial:Array<RewardInter>;
|
||||
|
||||
readonly assiAttrValue:Map<number, number>; // 次级属性
|
||||
readonly basicAttrValue:Map<number, number>; // 主属性
|
||||
readonly upGradeMaterial:Array<RewardInter>;
|
||||
}
|
||||
export const dicTeraph = new Map<string, DicTeraph>();
|
||||
@@ -42,6 +43,7 @@ export function loadTeraph() {
|
||||
criEffect: true,
|
||||
upMaterial: true,
|
||||
assiAttrValue: true,
|
||||
basicAttrValue: true,
|
||||
upGradeMaterial: true,
|
||||
}
|
||||
|
||||
@@ -51,6 +53,7 @@ export function loadTeraph() {
|
||||
o.upMaterial = parseGoodStr(o.upMaterial);
|
||||
o.mainAttrMax = parseMainAttrMax(o);
|
||||
o.mainAttrUp = parseMainAttrUp(o);
|
||||
o.basicAttrValue = parseBasicAttr(o);
|
||||
dicTeraph.set(o.index + '_' + o.grade, _.pick(o, Object.keys(DicTeraphKeys)));
|
||||
});
|
||||
|
||||
@@ -72,10 +75,10 @@ function parseAttr(str: string) {
|
||||
|
||||
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);
|
||||
result.set(ABI_TYPE.ABI_HP, elem.hpMax - elem.hpBasis);
|
||||
result.set(ABI_TYPE.ABI_ATK, elem.atkMax - elem.atkBasis);
|
||||
result.set(ABI_TYPE.ABI_DEF, elem.defMax - elem.defBasis);
|
||||
result.set(ABI_TYPE.ABI_MDEF, elem.mdefMax - elem.mdefBasis);
|
||||
return result
|
||||
}
|
||||
|
||||
@@ -86,4 +89,13 @@ function parseMainAttrUp(elem) {
|
||||
result.set(ABI_TYPE.ABI_DEF, elem.defUp);
|
||||
result.set(ABI_TYPE.ABI_MDEF, elem.mdefUp);
|
||||
return result
|
||||
}
|
||||
|
||||
function parseBasicAttr(elem) {
|
||||
let result = new Map<number, number>();
|
||||
result.set(ABI_TYPE.ABI_HP, elem.hpBasis);
|
||||
result.set(ABI_TYPE.ABI_ATK, elem.atkBasis);
|
||||
result.set(ABI_TYPE.ABI_DEF, elem.defBasis);
|
||||
result.set(ABI_TYPE.ABI_MDEF, elem.mdefBasis);
|
||||
return result
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,12 +1,11 @@
|
||||
import { STATUS } from './../consts/statusCode';
|
||||
|
||||
import { HeroModel, HeroType } from '../db/Hero';
|
||||
import { isNumber } from 'underscore';
|
||||
|
||||
const csprng = require('csprng');
|
||||
import fs = require('fs');
|
||||
import path = require('path');
|
||||
import { HERO_CE_RATIO, ABI_STAGE, GACHA_TO_FLOOR, REFRESH_TIME, ROBOT_SYS_TYPE, ITEM_CHANGE_REASON, WAR_TYPE } from '../consts';
|
||||
import { ABI_STAGE, GACHA_TO_FLOOR, REFRESH_TIME, ROBOT_SYS_TYPE, ITEM_CHANGE_REASON, WAR_TYPE } from '../consts';
|
||||
|
||||
import { findIndex } from 'underscore';
|
||||
import { getTimeFunM } from './timeUtil';
|
||||
@@ -114,18 +113,6 @@ export function decodeIdCntArrayStr(str: string, multi: number) {
|
||||
return strMap;
|
||||
}
|
||||
|
||||
// 计算当前武将战力
|
||||
export async function calculateSumCE(roleId: string, type: number, param: { num?: number, heroes?: Array<number> }) {
|
||||
let sum: number;
|
||||
if (type == 1) { // 最高num人历史最高战力和
|
||||
sum = await HeroModel.sumTopHeroCe(roleId, param.num || 0);
|
||||
} else if (type == 2) { // 所有人战力和
|
||||
sum = await HeroModel.sumHeroCe(roleId);
|
||||
}
|
||||
sum = reduceCe(sum);
|
||||
return sum;
|
||||
}
|
||||
|
||||
/**
|
||||
* 传入两个时间,返回按照时间差计算,第二个时间比第一个晚几天
|
||||
* @param preTime 之前的时间
|
||||
@@ -573,17 +560,6 @@ export function mergeSameGoods(goods: Array<{ id: number, count: number }>) {
|
||||
return resGoods;
|
||||
}
|
||||
|
||||
export function returnHeroCeRatio(hero: HeroType) {
|
||||
let ce = reduceCe(hero.ce);
|
||||
return Object.assign(hero, { ce });
|
||||
}
|
||||
|
||||
// 缩小战力
|
||||
export function reduceCe(ce: number = 0) {
|
||||
return Math.floor(ce / HERO_CE_RATIO / HERO_CE_RATIO)
|
||||
}
|
||||
|
||||
|
||||
// 获取全部属性
|
||||
export function getAllAttrStage() {
|
||||
let attrs = new Array<number>(); // 有升级的属性 1-hp 2-atk 3-def 4-mdef 5-agi 6-luk
|
||||
@@ -788,3 +764,59 @@ export function stringToRewardInter(rewardStr: string): Array<RewardInter> {
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
export function addToMap<T>(map: Map<T, number>, id: T, value: number) {
|
||||
if(!map.has(id)) {
|
||||
map.set(id, value);
|
||||
} else {
|
||||
map.set(id, map.get(id) + value);
|
||||
}
|
||||
}
|
||||
|
||||
// /**
|
||||
// * 计算最强阵容战力
|
||||
// * @param role
|
||||
// * @param hid
|
||||
// * @param ce
|
||||
// * @param heroId
|
||||
// */
|
||||
// export async function calculatetopLineup(role: RoleType, hid?: number, ce?: number, heroId?: string) {
|
||||
// let topLineup = role?.topLineup || new Array();
|
||||
// if(!hid) { // 直接重新排
|
||||
// let heroes = await HeroModel.getTopHero(role.roleId, LINEUP_NUM);
|
||||
// topLineup = heroes.map(cur => { return { hid: cur.hid, ce: cur.ce, hero: cur._id } });
|
||||
// } else {
|
||||
// topLineup.sort((a, b) => { return b.ce - a.ce }); // 0-6,最大-最小
|
||||
// let index = topLineup.findIndex(cur => cur.hid == hid);
|
||||
// if(index != -1 && !heroId) {
|
||||
// let heroes = await HeroModel.getTopHero(role.roleId, LINEUP_NUM);
|
||||
// topLineup = heroes.map(cur => { return { hid: cur.hid, ce: cur.ce, hero: cur._id } });
|
||||
// } else {
|
||||
// if (index == -1) { // 不在最强列表
|
||||
// if (topLineup.length < LINEUP_NUM) { // 不满6人
|
||||
// topLineup.push({ hid, ce, hero: heroId });
|
||||
// } else if (topLineup.length == LINEUP_NUM) {
|
||||
// if (ce > topLineup[topLineup.length - 1].ce) { // 跻身最强6人
|
||||
// topLineup.pop();
|
||||
// topLineup.push({ hid, ce, hero: heroId });
|
||||
// }
|
||||
// } else {
|
||||
// topLineup.splice(LINEUP_NUM, topLineup.length - LINEUP_NUM);
|
||||
// }
|
||||
// } else { // 原来就是最强6人
|
||||
// if (ce < topLineup[topLineup.length - 1].ce) { // 滑出最强
|
||||
// let heroes = await HeroModel.getTopHero(role.roleId, LINEUP_NUM);
|
||||
// topLineup = heroes.map(cur => { return { hid: cur.hid, ce: cur.ce, hero: cur._id } });
|
||||
// } else {
|
||||
// topLineup[index].ce = ce;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// let topLineupCe = topLineup.reduce((pre, cur) => {
|
||||
// return pre + cur.ce
|
||||
// }, 0);
|
||||
|
||||
// return { topLineup, topLineupCe };
|
||||
// }
|
||||
|
||||
@@ -5,8 +5,6 @@
|
||||
"jobClass": 1,
|
||||
"eplaceId": 1,
|
||||
"suitId": 1,
|
||||
"attribute": "2&10",
|
||||
"attributeUp": "2&10",
|
||||
"composeMaterial": "50001&2",
|
||||
"imageId": "qingtongjian&bintiejian&wenshijian&jinggangjian&songwenjian"
|
||||
},
|
||||
@@ -16,8 +14,6 @@
|
||||
"jobClass": 1,
|
||||
"eplaceId": 2,
|
||||
"suitId": 1,
|
||||
"attribute": "4&20",
|
||||
"attributeUp": "4&20",
|
||||
"composeMaterial": "50001&2",
|
||||
"imageId": "qingtongjian&bintiejian&wenshijian&jinggangjian&songwenjian"
|
||||
},
|
||||
@@ -27,8 +23,6 @@
|
||||
"jobClass": 1,
|
||||
"eplaceId": 3,
|
||||
"suitId": 1,
|
||||
"attribute": "5&20",
|
||||
"attributeUp": "5&20",
|
||||
"composeMaterial": "50001&2",
|
||||
"imageId": "qingtongjian&bintiejian&wenshijian&jinggangjian&songwenjian"
|
||||
},
|
||||
@@ -38,8 +32,6 @@
|
||||
"jobClass": 1,
|
||||
"eplaceId": 4,
|
||||
"suitId": 1,
|
||||
"attribute": "1&50",
|
||||
"attributeUp": "1&50",
|
||||
"composeMaterial": "50001&2",
|
||||
"imageId": "qingtongjian&bintiejian&wenshijian&jinggangjian&songwenjian"
|
||||
},
|
||||
@@ -49,8 +41,6 @@
|
||||
"jobClass": 2,
|
||||
"eplaceId": 1,
|
||||
"suitId": 2,
|
||||
"attribute": "2&10",
|
||||
"attributeUp": "2&10",
|
||||
"composeMaterial": "50001&2",
|
||||
"imageId": "qingtongjian&bintiejian&wenshijian&jinggangjian&songwenjian"
|
||||
},
|
||||
@@ -60,8 +50,6 @@
|
||||
"jobClass": 2,
|
||||
"eplaceId": 2,
|
||||
"suitId": 2,
|
||||
"attribute": "4&20",
|
||||
"attributeUp": "4&20",
|
||||
"composeMaterial": "50001&2",
|
||||
"imageId": "qingtongjian&bintiejian&wenshijian&jinggangjian&songwenjian"
|
||||
},
|
||||
@@ -71,8 +59,6 @@
|
||||
"jobClass": 2,
|
||||
"eplaceId": 3,
|
||||
"suitId": 2,
|
||||
"attribute": "5&20",
|
||||
"attributeUp": "5&20",
|
||||
"composeMaterial": "50001&2",
|
||||
"imageId": "qingtongjian&bintiejian&wenshijian&jinggangjian&songwenjian"
|
||||
},
|
||||
@@ -82,8 +68,6 @@
|
||||
"jobClass": 2,
|
||||
"eplaceId": 4,
|
||||
"suitId": 2,
|
||||
"attribute": "1&50",
|
||||
"attributeUp": "1&50",
|
||||
"composeMaterial": "50001&2",
|
||||
"imageId": "qingtongjian&bintiejian&wenshijian&jinggangjian&songwenjian"
|
||||
},
|
||||
@@ -93,8 +77,6 @@
|
||||
"jobClass": 3,
|
||||
"eplaceId": 1,
|
||||
"suitId": 3,
|
||||
"attribute": "2&10",
|
||||
"attributeUp": "2&10",
|
||||
"composeMaterial": "50001&2",
|
||||
"imageId": "qingtongjian&bintiejian&wenshijian&jinggangjian&songwenjian"
|
||||
},
|
||||
@@ -104,8 +86,6 @@
|
||||
"jobClass": 3,
|
||||
"eplaceId": 2,
|
||||
"suitId": 3,
|
||||
"attribute": "4&20",
|
||||
"attributeUp": "4&20",
|
||||
"composeMaterial": "50001&2",
|
||||
"imageId": "qingtongjian&bintiejian&wenshijian&jinggangjian&songwenjian"
|
||||
},
|
||||
@@ -115,8 +95,6 @@
|
||||
"jobClass": 3,
|
||||
"eplaceId": 3,
|
||||
"suitId": 3,
|
||||
"attribute": "5&20",
|
||||
"attributeUp": "5&20",
|
||||
"composeMaterial": "50001&2",
|
||||
"imageId": "qingtongjian&bintiejian&wenshijian&jinggangjian&songwenjian"
|
||||
},
|
||||
@@ -126,8 +104,6 @@
|
||||
"jobClass": 3,
|
||||
"eplaceId": 4,
|
||||
"suitId": 3,
|
||||
"attribute": "1&50",
|
||||
"attributeUp": "1&50",
|
||||
"composeMaterial": "50001&2",
|
||||
"imageId": "qingtongjian&bintiejian&wenshijian&jinggangjian&songwenjian"
|
||||
},
|
||||
@@ -137,8 +113,6 @@
|
||||
"jobClass": 4,
|
||||
"eplaceId": 1,
|
||||
"suitId": 4,
|
||||
"attribute": "2&10",
|
||||
"attributeUp": "2&10",
|
||||
"composeMaterial": "50001&2",
|
||||
"imageId": "qingtongjian&bintiejian&wenshijian&jinggangjian&songwenjian"
|
||||
},
|
||||
@@ -148,8 +122,6 @@
|
||||
"jobClass": 4,
|
||||
"eplaceId": 2,
|
||||
"suitId": 4,
|
||||
"attribute": "4&20",
|
||||
"attributeUp": "4&20",
|
||||
"composeMaterial": "50001&2",
|
||||
"imageId": "qingtongjian&bintiejian&wenshijian&jinggangjian&songwenjian"
|
||||
},
|
||||
@@ -159,8 +131,6 @@
|
||||
"jobClass": 4,
|
||||
"eplaceId": 3,
|
||||
"suitId": 4,
|
||||
"attribute": "5&20",
|
||||
"attributeUp": "5&20",
|
||||
"composeMaterial": "50001&2",
|
||||
"imageId": "qingtongjian&bintiejian&wenshijian&jinggangjian&songwenjian"
|
||||
},
|
||||
@@ -170,8 +140,6 @@
|
||||
"jobClass": 4,
|
||||
"eplaceId": 4,
|
||||
"suitId": 4,
|
||||
"attribute": "1&50",
|
||||
"attributeUp": "1&50",
|
||||
"composeMaterial": "50001&2",
|
||||
"imageId": "qingtongjian&bintiejian&wenshijian&jinggangjian&songwenjian"
|
||||
},
|
||||
@@ -181,8 +149,6 @@
|
||||
"jobClass": 5,
|
||||
"eplaceId": 1,
|
||||
"suitId": 5,
|
||||
"attribute": "2&10",
|
||||
"attributeUp": "2&10",
|
||||
"composeMaterial": "50001&2",
|
||||
"imageId": "qingtongjian&bintiejian&wenshijian&jinggangjian&songwenjian"
|
||||
},
|
||||
@@ -192,8 +158,6 @@
|
||||
"jobClass": 5,
|
||||
"eplaceId": 2,
|
||||
"suitId": 5,
|
||||
"attribute": "4&20",
|
||||
"attributeUp": "4&20",
|
||||
"composeMaterial": "50001&2",
|
||||
"imageId": "qingtongjian&bintiejian&wenshijian&jinggangjian&songwenjian"
|
||||
},
|
||||
@@ -203,8 +167,6 @@
|
||||
"jobClass": 5,
|
||||
"eplaceId": 3,
|
||||
"suitId": 5,
|
||||
"attribute": "5&20",
|
||||
"attributeUp": "5&20",
|
||||
"composeMaterial": "50001&2",
|
||||
"imageId": "qingtongjian&bintiejian&wenshijian&jinggangjian&songwenjian"
|
||||
},
|
||||
@@ -214,8 +176,6 @@
|
||||
"jobClass": 5,
|
||||
"eplaceId": 4,
|
||||
"suitId": 5,
|
||||
"attribute": "1&50",
|
||||
"attributeUp": "1&50",
|
||||
"composeMaterial": "50001&2",
|
||||
"imageId": "qingtongjian&bintiejian&wenshijian&jinggangjian&songwenjian"
|
||||
},
|
||||
@@ -225,8 +185,6 @@
|
||||
"jobClass": 6,
|
||||
"eplaceId": 1,
|
||||
"suitId": 6,
|
||||
"attribute": "2&10",
|
||||
"attributeUp": "2&10",
|
||||
"composeMaterial": "50001&2",
|
||||
"imageId": "qingtongjian&bintiejian&wenshijian&jinggangjian&songwenjian"
|
||||
},
|
||||
@@ -236,8 +194,6 @@
|
||||
"jobClass": 6,
|
||||
"eplaceId": 2,
|
||||
"suitId": 6,
|
||||
"attribute": "4&20",
|
||||
"attributeUp": "4&20",
|
||||
"composeMaterial": "50001&2",
|
||||
"imageId": "qingtongjian&bintiejian&wenshijian&jinggangjian&songwenjian"
|
||||
},
|
||||
@@ -247,8 +203,6 @@
|
||||
"jobClass": 6,
|
||||
"eplaceId": 3,
|
||||
"suitId": 6,
|
||||
"attribute": "5&20",
|
||||
"attributeUp": "5&20",
|
||||
"composeMaterial": "50001&2",
|
||||
"imageId": "qingtongjian&bintiejian&wenshijian&jinggangjian&songwenjian"
|
||||
},
|
||||
@@ -258,8 +212,6 @@
|
||||
"jobClass": 6,
|
||||
"eplaceId": 4,
|
||||
"suitId": 6,
|
||||
"attribute": "1&50",
|
||||
"attributeUp": "1&50",
|
||||
"composeMaterial": "50001&2",
|
||||
"imageId": "qingtongjian&bintiejian&wenshijian&jinggangjian&songwenjian"
|
||||
},
|
||||
@@ -269,8 +221,6 @@
|
||||
"jobClass": 7,
|
||||
"eplaceId": 1,
|
||||
"suitId": 7,
|
||||
"attribute": "2&10",
|
||||
"attributeUp": "2&10",
|
||||
"composeMaterial": "50001&2",
|
||||
"imageId": "qingtongjian&bintiejian&wenshijian&jinggangjian&songwenjian"
|
||||
},
|
||||
@@ -280,8 +230,6 @@
|
||||
"jobClass": 7,
|
||||
"eplaceId": 2,
|
||||
"suitId": 7,
|
||||
"attribute": "4&20",
|
||||
"attributeUp": "4&20",
|
||||
"composeMaterial": "50001&2",
|
||||
"imageId": "qingtongjian&bintiejian&wenshijian&jinggangjian&songwenjian"
|
||||
},
|
||||
@@ -291,8 +239,6 @@
|
||||
"jobClass": 7,
|
||||
"eplaceId": 3,
|
||||
"suitId": 7,
|
||||
"attribute": "5&20",
|
||||
"attributeUp": "5&20",
|
||||
"composeMaterial": "50001&2",
|
||||
"imageId": "qingtongjian&bintiejian&wenshijian&jinggangjian&songwenjian"
|
||||
},
|
||||
@@ -302,8 +248,6 @@
|
||||
"jobClass": 7,
|
||||
"eplaceId": 4,
|
||||
"suitId": 7,
|
||||
"attribute": "1&50",
|
||||
"attributeUp": "1&50",
|
||||
"composeMaterial": "50001&2",
|
||||
"imageId": "qingtongjian&bintiejian&wenshijian&jinggangjian&songwenjian"
|
||||
}
|
||||
|
||||
14142
shared/resource/jsons/dic_zyz_equipStrengthAttr.json
Normal file
14142
shared/resource/jsons/dic_zyz_equipStrengthAttr.json
Normal file
File diff suppressed because it is too large
Load Diff
@@ -15,8 +15,8 @@
|
||||
"turnLimted": 20,
|
||||
"forcedCharactor": "&",
|
||||
"fobiddenCharactor": "&",
|
||||
"victoryInfoInUI": "1.消灭所有敌军\r\n2.死亡的村民数量≤2\r\n3.剩下的村民都到达洞口",
|
||||
"loseInfoInUI": "1.我方全部阵亡\r\n2.死亡的村民数量≥3\r\n3.20回合内未能胜利",
|
||||
"victoryInfoInUI": "1.消灭所有敌军\n2.死亡的村民数量≤2\n3.剩下的村民都到达洞口",
|
||||
"loseInfoInUI": "1.我方全部阵亡\n2.死亡的村民数量≥3\n3.20回合内未能胜利",
|
||||
"starInfoInUI": "1.在20回合内获得胜利",
|
||||
"cost": 10,
|
||||
"iconInMap": "spine&qingnian",
|
||||
@@ -30,7 +30,7 @@
|
||||
"needPrepare": 1,
|
||||
"spineInBigMap": "&",
|
||||
"HeroNum": "6&6",
|
||||
"gkInfo": " 循着不详的气息,赵云一行人来到了一座神秘的小村庄。老人们说,他们是为了躲避连年战乱才来此地。\r\n 想不到即使是在这里,也藏着不为人知的阴谋……\r\n 这些阴兵,究竟由谁招来?山林里还有恶兽蠢蠢欲动……\r\n",
|
||||
"gkInfo": " 循着不详的气息,赵云一行人来到了一座神秘的小村庄。老人们说,他们是为了躲避连年战乱才来此地。\n 想不到即使是在这里,也藏着不为人知的阴谋……\n 这些阴兵,究竟由谁招来?山林里还有恶兽蠢蠢欲动……\n",
|
||||
"HeroNum_1": "1&6",
|
||||
"progress": "1&0|2&0",
|
||||
"progressDesc": "已逃走的百姓数量&被击杀的百姓数量",
|
||||
@@ -52,8 +52,8 @@
|
||||
"turnLimted": 20,
|
||||
"forcedCharactor": "&",
|
||||
"fobiddenCharactor": "&",
|
||||
"victoryInfoInUI": "1.消灭所有敌军\r\n2.解救所有被绑架的村民\r\n",
|
||||
"loseInfoInUI": "1.我方全部阵亡\r\n2.20回合内未能胜利",
|
||||
"victoryInfoInUI": "1.消灭所有敌军\n2.解救所有被绑架的村民\n",
|
||||
"loseInfoInUI": "1.我方全部阵亡\n2.20回合内未能胜利",
|
||||
"starInfoInUI": "1.在20回合内获得胜利",
|
||||
"cost": 10,
|
||||
"iconInMap": "spine&yinbingdao&1",
|
||||
@@ -67,7 +67,7 @@
|
||||
"needPrepare": 1,
|
||||
"spineInBigMap": "&",
|
||||
"HeroNum": "6&6",
|
||||
"gkInfo": " 赵云一行人刚将村中的百姓带入山洞避难,一位急急忙忙寻找妻子的青年便找上门来。\r\n 洞内仍有不少以往百姓为了躲避战乱设下的陷阱,可务必要当心!\r\n 也许在这昏暗的洞穴里,点燃火炬一路小心前行,才是上策。",
|
||||
"gkInfo": " 赵云一行人刚将村中的百姓带入山洞避难,一位急急忙忙寻找妻子的青年便找上门来。\n 洞内仍有不少以往百姓为了躲避战乱设下的陷阱,可务必要当心!\n 也许在这昏暗的洞穴里,点燃火炬一路小心前行,才是上策。",
|
||||
"HeroNum_1": "1&6",
|
||||
"progress": "1&0|6&0",
|
||||
"progressDesc": "已解救的百姓数量&待解救的百姓数量",
|
||||
@@ -104,7 +104,7 @@
|
||||
"needPrepare": 1,
|
||||
"spineInBigMap": "&",
|
||||
"HeroNum": "6&6",
|
||||
"gkInfo": " 诡异的阴兵,神秘的阴珠,残忍的血法……从巨鹿废墟到山林小村,一个巨大的阴谋似乎一直笼罩在冀州的上空。\r\n 现在赵云一行人终于来到了最后的祭坛,即将揭开这一切的始作俑者……",
|
||||
"gkInfo": " 诡异的阴兵,神秘的阴珠,残忍的血法……从巨鹿废墟到山林小村,一个巨大的阴谋似乎一直笼罩在冀州的上空。\n 现在赵云一行人终于来到了最后的祭坛,即将揭开这一切的始作俑者……",
|
||||
"HeroNum_1": "1&6",
|
||||
"progress": "&",
|
||||
"progressDesc": "&",
|
||||
@@ -128,7 +128,7 @@
|
||||
"fobiddenCharactor": "&",
|
||||
"victoryInfoInUI": "消灭所有敌军",
|
||||
"loseInfoInUI": "我方全部阵亡",
|
||||
"starInfoInUI": "\r\n1.在20回合内获得胜利",
|
||||
"starInfoInUI": "\n1.在20回合内获得胜利",
|
||||
"cost": 10,
|
||||
"iconInMap": "spine&qingnian",
|
||||
"iconName": "井底世界",
|
||||
@@ -141,7 +141,7 @@
|
||||
"needPrepare": 1,
|
||||
"spineInBigMap": "&",
|
||||
"HeroNum": "6&6",
|
||||
"gkInfo": " 在枯井的周围,一群宫女装扮的幽鬼盘亘。\r\n 原来,这些是洛阳被焚毁时,惨死于皇宫中的宫女,因为长久以来的怨气而化为幽鬼,她们憎恨一切活着的人类。\r\n 小心!她们来了!",
|
||||
"gkInfo": " 在枯井的周围,一群宫女装扮的幽鬼盘亘。\n 原来,这些是洛阳被焚毁时,惨死于皇宫中的宫女,因为长久以来的怨气而化为幽鬼,她们憎恨一切活着的人类。\n 小心!她们来了!",
|
||||
"HeroNum_1": "1&6",
|
||||
"progress": "&",
|
||||
"progressDesc": "&",
|
||||
@@ -178,7 +178,7 @@
|
||||
"needPrepare": 1,
|
||||
"spineInBigMap": "&",
|
||||
"HeroNum": "6&6",
|
||||
"gkInfo": " 枯井的尽头是一条大门,出于好奇,赵云一行人穿越幽暗的隧道,来到大门前。\r\n 吱呀——推开大门,原来这里是一片墓室。\r\n 在昏黄的烛火中,他们看到了一群没有意识的侍卫,还有一个没有头颅的巨大身影……",
|
||||
"gkInfo": " 枯井的尽头是一条大门,出于好奇,赵云一行人穿越幽暗的隧道,来到大门前。\n 吱呀——推开大门,原来这里是一片墓室。\n 在昏黄的烛火中,他们看到了一群没有意识的侍卫,还有一个没有头颅的巨大身影……",
|
||||
"HeroNum_1": "1&6",
|
||||
"progress": "&",
|
||||
"progressDesc": "&",
|
||||
@@ -202,7 +202,7 @@
|
||||
"fobiddenCharactor": "&",
|
||||
"victoryInfoInUI": "消灭所有敌军",
|
||||
"loseInfoInUI": "我方全部阵亡",
|
||||
"starInfoInUI": "1.我方无人阵亡;\r\n2.在30回合内获得胜利",
|
||||
"starInfoInUI": "1.我方无人阵亡;\n2.在30回合内获得胜利",
|
||||
"cost": 30,
|
||||
"iconInMap": "spine&zhangjiao",
|
||||
"iconName": "何后废陵",
|
||||
@@ -215,7 +215,7 @@
|
||||
"needPrepare": 1,
|
||||
"spineInBigMap": "&",
|
||||
"HeroNum": "6&6",
|
||||
"gkInfo": " 何太后身材窈窕,风流妩媚,进宫之后更是凭借自身的心计一步步征服了汉灵帝的心。然其天性善妒,刘协出生后,感到自身地位动摇的何太后用鸩酒毒杀了王美人。\r\n 天道有轮回,外戚与宦官相争,何进身死,董卓进京,何太后也被逼饮下毒酒。\r\n 陵墓尽头,彼岸花开,何太后已超脱生死,可千万别停留在这里!",
|
||||
"gkInfo": " 何太后身材窈窕,风流妩媚,进宫之后更是凭借自身的心计一步步征服了汉灵帝的心。然其天性善妒,刘协出生后,感到自身地位动摇的何太后用鸩酒毒杀了王美人。\n 天道有轮回,外戚与宦官相争,何进身死,董卓进京,何太后也被逼饮下毒酒。\n 陵墓尽头,彼岸花开,何太后已超脱生死,可千万别停留在这里!",
|
||||
"HeroNum_1": "1&6",
|
||||
"progress": "&",
|
||||
"progressDesc": "&",
|
||||
@@ -239,7 +239,7 @@
|
||||
"fobiddenCharactor": "&",
|
||||
"victoryInfoInUI": "消灭所有敌军",
|
||||
"loseInfoInUI": "我方全部阵亡",
|
||||
"starInfoInUI": "1.我方无人阵亡;\r\n2.在5回合内获得胜利",
|
||||
"starInfoInUI": "1.我方无人阵亡;\n2.在5回合内获得胜利",
|
||||
"cost": 10,
|
||||
"iconInMap": "spine&guanhai",
|
||||
"iconName": 0,
|
||||
@@ -276,7 +276,7 @@
|
||||
"fobiddenCharactor": "&",
|
||||
"victoryInfoInUI": "消灭所有敌军",
|
||||
"loseInfoInUI": "我方全部阵亡",
|
||||
"starInfoInUI": "1.我方无人阵亡;\r\n2.在5回合内获得胜利",
|
||||
"starInfoInUI": "1.我方无人阵亡;\n2.在5回合内获得胜利",
|
||||
"cost": 10,
|
||||
"iconInMap": "spine&caosong",
|
||||
"iconName": 0,
|
||||
@@ -313,7 +313,7 @@
|
||||
"fobiddenCharactor": "&",
|
||||
"victoryInfoInUI": "消灭所有敌军",
|
||||
"loseInfoInUI": "我方全部阵亡",
|
||||
"starInfoInUI": "1.我方无人阵亡;\r\n2.在5回合内获得胜利",
|
||||
"starInfoInUI": "1.我方无人阵亡;\n2.在5回合内获得胜利",
|
||||
"cost": 30,
|
||||
"iconInMap": "spine&zhangrang",
|
||||
"iconName": 0,
|
||||
@@ -350,7 +350,7 @@
|
||||
"fobiddenCharactor": "&",
|
||||
"victoryInfoInUI": "消灭所有敌军",
|
||||
"loseInfoInUI": "我方全部阵亡",
|
||||
"starInfoInUI": "1.我方无人阵亡;\r\n2.在5回合内获得胜利",
|
||||
"starInfoInUI": "1.我方无人阵亡;\n2.在5回合内获得胜利",
|
||||
"cost": 10,
|
||||
"iconInMap": "spine&qingnian",
|
||||
"iconName": 0,
|
||||
@@ -387,7 +387,7 @@
|
||||
"fobiddenCharactor": "&",
|
||||
"victoryInfoInUI": "消灭所有敌军",
|
||||
"loseInfoInUI": "我方全部阵亡",
|
||||
"starInfoInUI": "1.我方无人阵亡;\r\n2.在5回合内获得胜利",
|
||||
"starInfoInUI": "1.我方无人阵亡;\n2.在5回合内获得胜利",
|
||||
"cost": 10,
|
||||
"iconInMap": "spine&yinbingdao",
|
||||
"iconName": 0,
|
||||
@@ -424,7 +424,7 @@
|
||||
"fobiddenCharactor": "&",
|
||||
"victoryInfoInUI": "消灭所有敌军",
|
||||
"loseInfoInUI": "我方全部阵亡",
|
||||
"starInfoInUI": "1.我方无人阵亡;\r\n2.在5回合内获得胜利",
|
||||
"starInfoInUI": "1.我方无人阵亡;\n2.在5回合内获得胜利",
|
||||
"cost": 30,
|
||||
"iconInMap": "spine&zhangjiao",
|
||||
"iconName": 0,
|
||||
@@ -461,7 +461,7 @@
|
||||
"fobiddenCharactor": "&",
|
||||
"victoryInfoInUI": "消灭所有敌军",
|
||||
"loseInfoInUI": "我方全部阵亡",
|
||||
"starInfoInUI": "1.我方无人阵亡;\r\n2.在5回合内获得胜利",
|
||||
"starInfoInUI": "1.我方无人阵亡;\n2.在5回合内获得胜利",
|
||||
"cost": 10,
|
||||
"iconInMap": "spine&qingnian",
|
||||
"iconName": 0,
|
||||
@@ -498,7 +498,7 @@
|
||||
"fobiddenCharactor": "&",
|
||||
"victoryInfoInUI": "消灭所有敌军",
|
||||
"loseInfoInUI": "我方全部阵亡",
|
||||
"starInfoInUI": "1.我方无人阵亡;\r\n2.在5回合内获得胜利",
|
||||
"starInfoInUI": "1.我方无人阵亡;\n2.在5回合内获得胜利",
|
||||
"cost": 10,
|
||||
"iconInMap": "spine&yinbingdao",
|
||||
"iconName": 0,
|
||||
@@ -535,7 +535,7 @@
|
||||
"fobiddenCharactor": "&",
|
||||
"victoryInfoInUI": "消灭所有敌军",
|
||||
"loseInfoInUI": "我方全部阵亡",
|
||||
"starInfoInUI": "1.我方无人阵亡;\r\n2.在5回合内获得胜利",
|
||||
"starInfoInUI": "1.我方无人阵亡;\n2.在5回合内获得胜利",
|
||||
"cost": 30,
|
||||
"iconInMap": "spine&zhangjiao",
|
||||
"iconName": 0,
|
||||
@@ -572,7 +572,7 @@
|
||||
"fobiddenCharactor": "&",
|
||||
"victoryInfoInUI": "消灭所有敌军",
|
||||
"loseInfoInUI": "我方全部阵亡",
|
||||
"starInfoInUI": "1.我方无人阵亡;\r\n2.在5回合内获得胜利",
|
||||
"starInfoInUI": "1.我方无人阵亡;\n2.在5回合内获得胜利",
|
||||
"cost": 10,
|
||||
"iconInMap": "spine&wangcan",
|
||||
"iconName": 0,
|
||||
@@ -609,7 +609,7 @@
|
||||
"fobiddenCharactor": "&",
|
||||
"victoryInfoInUI": "消灭所有敌军",
|
||||
"loseInfoInUI": "我方全部阵亡",
|
||||
"starInfoInUI": "1.我方无人阵亡;\r\n2.在5回合内获得胜利",
|
||||
"starInfoInUI": "1.我方无人阵亡;\n2.在5回合内获得胜利",
|
||||
"cost": 10,
|
||||
"iconInMap": "spine&yanshi",
|
||||
"iconName": 0,
|
||||
@@ -646,7 +646,7 @@
|
||||
"fobiddenCharactor": "&",
|
||||
"victoryInfoInUI": "消灭所有敌军",
|
||||
"loseInfoInUI": "我方全部阵亡",
|
||||
"starInfoInUI": "1.我方无人阵亡;\r\n2.在5回合内获得胜利",
|
||||
"starInfoInUI": "1.我方无人阵亡;\n2.在5回合内获得胜利",
|
||||
"cost": 30,
|
||||
"iconInMap": "spine&sengren",
|
||||
"iconName": 0,
|
||||
@@ -683,7 +683,7 @@
|
||||
"fobiddenCharactor": "&",
|
||||
"victoryInfoInUI": "消灭所有敌军",
|
||||
"loseInfoInUI": "我方全部阵亡",
|
||||
"starInfoInUI": "1.我方无人阵亡;\r\n2.在5回合内获得胜利",
|
||||
"starInfoInUI": "1.我方无人阵亡;\n2.在5回合内获得胜利",
|
||||
"cost": 10,
|
||||
"iconInMap": "spine&qingnian",
|
||||
"iconName": "武陵顽猴",
|
||||
@@ -720,7 +720,7 @@
|
||||
"fobiddenCharactor": "&",
|
||||
"victoryInfoInUI": "消灭所有敌军",
|
||||
"loseInfoInUI": "我方全部阵亡",
|
||||
"starInfoInUI": "1.我方无人阵亡;\r\n2.在5回合内获得胜利",
|
||||
"starInfoInUI": "1.我方无人阵亡;\n2.在5回合内获得胜利",
|
||||
"cost": 10,
|
||||
"iconInMap": "spine&yinbingdao",
|
||||
"iconName": "桃源疫民",
|
||||
@@ -757,7 +757,7 @@
|
||||
"fobiddenCharactor": "&",
|
||||
"victoryInfoInUI": "消灭所有敌军",
|
||||
"loseInfoInUI": "我方全部阵亡",
|
||||
"starInfoInUI": "1.我方无人阵亡;\r\n2.在5回合内获得胜利",
|
||||
"starInfoInUI": "1.我方无人阵亡;\n2.在5回合内获得胜利",
|
||||
"cost": 30,
|
||||
"iconInMap": "spine&zhangjiao",
|
||||
"iconName": "西夷疫魔",
|
||||
|
||||
Reference in New Issue
Block a user