feat(宝物): 添加宝物系统

This commit is contained in:
luying
2022-12-07 10:55:30 +08:00
parent b684307818
commit a83deeff5f
46 changed files with 15656 additions and 54 deletions

View File

@@ -3,7 +3,7 @@ import { Application, BackendSession, pinus, HandlerService, } from 'pinus';
import { isArray, pick } from 'underscore';
import { gameData } from '../../../pubUtils/data';
import { STATUS } from '../../../consts/statusCode';
import { resResult } from '../../../pubUtils/util';
import { arrToMap, resResult } from '../../../pubUtils/util';
import { LadderMatchModel, LadderUpdateInter } from '../../../db/LadderMatch';
import { battleEndWhenChange, checkRank, generateInitRecInfo, generateOppPlayers, getBuyCntCost, getLadderData, getLadderEnemies, getLadderOppDetailData, getLadderOppStatus, getNumberArr, ladderBattleEndReward, refreshLadderDaily, refreshLadderEnemies, sendLadderDailyReward, uniqueArr } from '../../../services/ladderService';
import { LadderDataReturn, LadderDefense, LadderDefenseHero, LadderOppDetailReturn, LadderOppLineupReturn, LadderOppPlayerHeroInfo, LadderOppPlayerReturn } from '../../../domain/battleField/ladder';
@@ -96,8 +96,8 @@ export class LadderHandler {
// 创建ladderMatchRec发行battleCode
let attackInfo = generateInitRecInfo(false, false, ladderData.rank, ladderData);
let defenseInfo = generateInitRecInfo(isRobot, true, rank, hisLadderData);
let attackInfo = await generateInitRecInfo(false, false, ladderData.rank, ladderData);
let defenseInfo = await generateInitRecInfo(isRobot, true, rank, hisLadderData);
let rec = await LadderMatchRecModel.createRec(serverId, roleId, targetRoleId, hisLadderData?.defense, attackInfo, defenseInfo);
// 倒计时倒计时结束没有check设为失败并发失败通知

View File

@@ -0,0 +1,340 @@
import { Application, BackendSession, HandlerService, } from "pinus";
import { STATUS, HERO_SYSTEM_TYPE, ITEM_CHANGE_REASON, TASK_TYPE } from "../../../consts";
import { ArtifactModel, ArtifactModelType, ArtifactModelUpdate } from "../../../db/Artifact";
import { HeroModel } from "../../../db/Hero";
import { ArtifactParam } from "../../../domain/roleField/hero";
import { gameData, getArtifactByGidAndType, getArtifactStageZero, getArtifactWithQuality, getDicArtifactLvByPlanId, getNextArtifact } from "../../../pubUtils/data";
import { ARTIFACT, BAG } from "../../../pubUtils/dicParam";
import { ItemInter } from "../../../pubUtils/interface";
import { resResult, parseGoodStr, arrToMap, genCode } from "../../../pubUtils/util";
import { checkArtifactCanCompose, getRebuildConsume, hasArtifactStrength } from "../../../services/equipService";
import { calculateCeWithHero } from "../../../services/playerCeService";
import { CheckMeterial } from "../../../services/role/checkMaterial";
import { addItems, handleCost } from "../../../services/role/rewardService";
import { combineItems } from "../../../services/role/util";
import { checkTask } from "../../../services/task/taskService";
export default function (app: Application) {
new HandlerService(app, {});
return new ArtifactHandler(app);
}
export class ArtifactHandler {
constructor(private app: Application) {
}
public async putOn(msg: { seqId: number, hid: number }, session: BackendSession) {
let roleId: string = session.get('roleId');
let sid: string = session.get('sid');
let serverId: number = session.get('serverId');
let { seqId, hid } = msg;
let hero = await HeroModel.findByHidAndRole(hid, roleId);
if (!hero) return resResult(STATUS.HERO_NOT_FIND);
let chosenArtifact = await ArtifactModel.findbySeqId(roleId, seqId);
if(!chosenArtifact) return resResult(STATUS.ARTIFACT_IS_NOT_FIND);
let artifacts: ArtifactModelType[] = [];
let artifactOfHero = hero.artifact? await ArtifactModel.findbySeqId(roleId, hero.artifact): null; // 原本自己的天晶石
if(chosenArtifact.hid != 0) { // 如果天晶石原本镶嵌在其他武将身上,把自己的给他
let heroOfChosenArtifact = await HeroModel.findByHidAndRole(chosenArtifact.hid, roleId); // 我想要的宝物的原持有者
if(heroOfChosenArtifact) {
await calculateCeWithHero(HERO_SYSTEM_TYPE.PUT_ARTIFACT, roleId, serverId, sid, heroOfChosenArtifact.hid, { artifact: hero.artifact||0 }, { artifact: artifactOfHero, job: heroOfChosenArtifact.job, skinId: heroOfChosenArtifact.skinId }); // 把我的换给他
}
}
if(artifactOfHero) { // 更新自己的天晶石
artifactOfHero = await ArtifactModel.putOnOrOff(roleId, artifactOfHero.seqId, chosenArtifact.hid||0);
if(artifactOfHero) artifacts.push(artifactOfHero);
}
chosenArtifact = await ArtifactModel.putOnOrOff(roleId, seqId, hid);
if(chosenArtifact) artifacts.push(chosenArtifact);
await calculateCeWithHero(HERO_SYSTEM_TYPE.PUT_ARTIFACT, roleId, serverId, sid, hid, { artifact: seqId }, { artifact: chosenArtifact, job: hero.job, skinId: hero.skinId }); // 把我的换给他
await checkTask(serverId, roleId, sid, TASK_TYPE.ARTIFACT_QUALITY_EQUIP, { artifacts });
return resResult(STATUS.SUCCESS, { artifacts: artifacts.map(artifact => new ArtifactParam(artifact)) });
}
public async putOff(msg: { seqId: number }, session: BackendSession) {
let roleId: string = session.get('roleId');
let sid: string = session.get('sid');
let serverId: number = session.get('serverId');
let { seqId } = msg;
let chosenArtifact = await ArtifactModel.findbySeqId(roleId, seqId);
if(!chosenArtifact) return resResult(STATUS.ARTIFACT_IS_NOT_FIND);
let heroOfChosenArtifact = await HeroModel.findByHidAndRole(chosenArtifact.hid, roleId); // 我想要的宝物的原持有者
if(!heroOfChosenArtifact) return resResult(STATUS.ARTIFACT_IS_NOT_EQUIPED);
chosenArtifact = await ArtifactModel.putOnOrOff(roleId, seqId, 0);
let artifacts: ArtifactParam[] = [new ArtifactParam(chosenArtifact)];
await calculateCeWithHero(HERO_SYSTEM_TYPE.PUT_OFF_ARTIFACT, roleId, serverId, sid, heroOfChosenArtifact.hid, { artifact: 0 }); // 把我的换给他
return resResult(STATUS.SUCCESS, { artifacts });
}
public async lvUp(msg: { seqId: number, isOneClick: boolean }, session: BackendSession) {
let roleId: string = session.get('roleId');
let sid: string = session.get('sid');
let serverId: number = session.get('serverId');
let { seqId, isOneClick } = msg;
let artifact = await ArtifactModel.findbySeqId(roleId, seqId);
if(!artifact) return resResult(STATUS.ARTIFACT_IS_NOT_FIND);
let dicArtifact = getArtifactWithQuality(artifact.artifactId);
if(!dicArtifact) return resResult(STATUS.DIC_DATA_NOT_FOUND);
if(artifact.lv >= dicArtifact.maxLv) return resResult(STATUS.ARTIFACT_LV_MAX);
let toLv = isOneClick? dicArtifact.maxLv: artifact.lv + 1;
let newLv = artifact.lv;
let check = new CheckMeterial(roleId);
for (let lv = artifact.lv + 1; lv <= toLv; lv++) {
let dicArtifactLv = getDicArtifactLvByPlanId(dicArtifact.lvAttrPlan, lv);
if(!dicArtifactLv) break;
let isEnough = await check.decrease(dicArtifactLv.consumes);
if(!isEnough) break; // 消耗不足
newLv = lv;
}
if(newLv == artifact.lv) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH);
let consumes = check.getConsume();
let result = await handleCost(roleId, sid, consumes, ITEM_CHANGE_REASON.ARTIFACT_LV);
if (!result) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH);
artifact = await ArtifactModel.updateInfoBySeqId(roleId, seqId, { lv: newLv });
if(artifact.hid > 0) {
await calculateCeWithHero(HERO_SYSTEM_TYPE.ARTIFACT_LV, roleId, serverId, sid, artifact.hid, {}, { artifact });
}
await checkTask(serverId, roleId, sid, TASK_TYPE.ARTIFACT_LV, { artifacts: [artifact] });
return resResult(STATUS.SUCCESS, { artifact: new ArtifactParam(artifact) });
}
public async compose(msg: { seqId: number, material: number[], generalItems: {id: number, count: number}[] }, session: BackendSession) {
let roleId: string = session.get('roleId');
let sid: string = session.get('sid');
let serverId: number = session.get('serverId');
let { seqId, material = [], generalItems = [] } = msg;
let seqIds = [seqId, ...material];
let artifacts = await ArtifactModel.findbySeqIds(roleId, seqIds);
if (artifacts.length < seqIds.length) return resResult(STATUS.ARTIFACT_IS_NOT_FIND);
let artifactMap = arrToMap(artifacts, obj => obj.seqId);
let originArtifact = artifactMap.get(seqId);
if(!originArtifact) return resResult(STATUS.ARTIFACT_IS_NOT_FIND);
let dicOriginArtifact = getArtifactWithQuality(originArtifact.artifactId);
if(!dicOriginArtifact) return resResult(STATUS.ARTIFACT_IS_NOT_FIND);
let dicNextArtifact = getNextArtifact(originArtifact.artifactId);
if(!dicNextArtifact) return resResult(STATUS.DIC_DATA_NOT_FOUND);
// 狗粮处理
let remainCnt = dicNextArtifact.materialCnt, cost: ItemInter[] = [], delSeqIds: number[] = [];
for(let seqId of material) {
let artifact = artifactMap.get(seqId);
let res = checkArtifactCanCompose(originArtifact.artifactId, artifact);
if(res.code != 0) return resResult(res);
cost.push({ seqId, id: artifact.id });
delSeqIds.push(seqId);
remainCnt--;
}
// 通用道具
if(dicNextArtifact.materialGroup == 0) { // 可使用材料代替,不是必须同名的那种
let dicMaterialArtifactQuality = gameData.artifactQualityById.get(dicNextArtifact.previousId);
if(!dicMaterialArtifactQuality) return resResult(STATUS.DIC_DATA_NOT_FOUND);
for(let { id, count } of dicMaterialArtifactQuality.generalItem) {
let needCount = count * remainCnt;
let chosenItem = generalItems.find(cur => cur.id == id);
if(!chosenItem || chosenItem.count < needCount) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH);
cost.push({ id, count: needCount });
}
remainCnt = 0;
}
if(remainCnt > 0) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH);
let result = await handleCost(roleId, sid, cost, ITEM_CHANGE_REASON.ARTIFACT_QUALITY);
if (!result) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH);
let { quality, qualityStage, artifactId, goodId } = dicNextArtifact;
originArtifact = await ArtifactModel.updateInfoBySeqId(roleId, seqId, { quality, qualityStage, artifactId, id: goodId });
if(originArtifact.hid > 0) {
let hero = await HeroModel.findByHidAndRole(originArtifact.hid, roleId);
if (!hero) return resResult(STATUS.HERO_NOT_FIND);
await calculateCeWithHero(HERO_SYSTEM_TYPE.ARTIFACT_QUALITY, roleId, serverId, sid, originArtifact.hid, {}, { artifact: originArtifact, job: hero.job, skinId: hero.skinId });
await checkTask(serverId, roleId, sid, TASK_TYPE.ARTIFACT_QUALITY_EQUIP, { artifacts: [originArtifact] });
}
await checkTask(serverId, roleId, sid, TASK_TYPE.ARTIFACT_COMPOSE, { count: 1 });
return resResult(STATUS.SUCCESS, { delSeqIds, artifact: new ArtifactParam(originArtifact) });
}
public async composeAll(msg: {}, session: BackendSession) {
let roleId: string = session.get('roleId');
let sid: string = session.get('sid');
let serverId: number = session.get('serverId');
let taskCount = 0;
const batchCode = genCode(10), delSeqIds: number[] = [];
for(let [_, { quality, canComposeAll }] of gameData.artifactQualityById) {
if(!canComposeAll) continue;
let artifacts = await ArtifactModel.findByQuality(roleId, quality);
let used: number[] = [], materials: ItemInter[] = [], target: ArtifactModelUpdate[] = [];
for(let artifact of artifacts) {
if(used.indexOf(artifact.seqId) > -1) continue;
let tmpUsed: number[] = [artifact.seqId];
let dicNextArtifact = getNextArtifact(artifact.artifactId);
if(!dicNextArtifact) continue;
let { materialCnt, goodId: nextGid, artifactId: nextArtId, quality: nextQuality, qualityStage: nextStage } = dicNextArtifact;
let canUseMaterial: ItemInter[] = [];
for(let i = 0; i < materialCnt; i++) {
for(let _artifact of artifacts) {
if(used.indexOf(_artifact.seqId) > -1 || tmpUsed.indexOf(_artifact.seqId) > -1) continue;
let res = checkArtifactCanCompose(artifact.artifactId, _artifact);
if(res.code != 0) continue;
canUseMaterial.push({ id: _artifact.id, seqId: _artifact.seqId });
tmpUsed.push(_artifact.seqId);
break;
}
}
if(materialCnt == canUseMaterial.length) {
used.push(...tmpUsed);
materials.push(...canUseMaterial);
delSeqIds.push(...canUseMaterial.map(cur => cur.seqId));
target.push({ seqId: artifact.seqId, id: nextGid, artifactId: nextArtId, quality: nextQuality, qualityStage: nextStage });
taskCount++;
}
}
let result = await handleCost(roleId, sid, materials, ITEM_CHANGE_REASON.ARTIFACT_QUALITY);
if (!result) continue;
for(let { seqId, quality, qualityStage, artifactId, id} of target) {
await ArtifactModel.updateInfoBySeqId(roleId, seqId, { quality, qualityStage, artifactId, id, batchCode });
}
}
let artifacts = await ArtifactModel.findByBatchCode(batchCode);
await checkTask(serverId, roleId, sid, TASK_TYPE.ARTIFACT_COMPOSE, { count: taskCount });
return resResult(STATUS.SUCCESS, { delSeqIds, artifacts: artifacts.map(artifact => new ArtifactParam(artifact))});
}
public async transfer(msg: { seqId: number, type: number }, session: BackendSession) {
let roleId: string = session.get('roleId');
let sid: string = session.get('sid');
let serverId: number = session.get('serverId');
let { seqId, type } = msg;
let artifact = await ArtifactModel.findbySeqId(roleId, seqId);
if(!artifact) return resResult(STATUS.ARTIFACT_IS_NOT_FIND);
let dicArtifact = gameData.artifact.get(artifact.artifactId);
if(!dicArtifact) return resResult(STATUS.DIC_DATA_NOT_FOUND);
if(dicArtifact.type == type) return resResult(STATUS.ARTIFACT_TYPE_SAME);
let dicTargetArtifact = getArtifactByGidAndType(dicArtifact.goodId, type);
if(!dicTargetArtifact) return resResult(STATUS.ARTIFACT_TYPE_ERR);
let consume = parseGoodStr(ARTIFACT.TRANSFER_COST);
let result = await handleCost(roleId, sid, consume, ITEM_CHANGE_REASON.ARTIFACT_TRANSFER);
if (!result) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH);
let { artifactId, goodId } = dicTargetArtifact;
artifact = await ArtifactModel.updateInfoBySeqId(roleId, seqId, { artifactId, id: goodId });
if(artifact.hid > 0) {
let hero = await HeroModel.findByHidAndRole(artifact.hid, roleId);
if (!hero) return resResult(STATUS.HERO_NOT_FIND);
await calculateCeWithHero(HERO_SYSTEM_TYPE.ARTIFACT_TRANSFER, roleId, serverId, sid, artifact.hid, {}, { artifact, job: hero.job, skinId: hero.skinId });
}
return resResult(STATUS.SUCCESS, { artifact: new ArtifactParam(artifact) });
}
public async previewRebuild(msg: { seqIds: number[] }, session: BackendSession) {
let roleId: string = session.get('roleId');
let { seqIds } = msg;
let artifacts = await ArtifactModel.findbySeqIds(roleId, seqIds);
if (artifacts.length < seqIds.length) return resResult(STATUS.ARTIFACT_IS_NOT_FIND);
let consumes = getRebuildConsume(artifacts);
return resResult(STATUS.SUCCESS, { consumes });
}
public async rebuild(msg: { seqIds: number[] }, session: BackendSession) {
let roleId: string = session.get('roleId');
let roleName: string = session.get('roleName');
let serverId: number = session.get('serverId');
let sid: string = session.get('sid');
let { seqIds } = msg;
let artifacts = await ArtifactModel.findbySeqIds(roleId, seqIds);
if (artifacts.length < seqIds.length) return resResult(STATUS.ARTIFACT_IS_NOT_FIND);
let rebuildConsumes = getRebuildConsume(artifacts);
if(rebuildConsumes.length <= 0) return resResult(STATUS.ARTIFACT_HAS_NO_STRENGTH);
let consume = parseGoodStr(ARTIFACT.REBUILD_COST);
let result = await handleCost(roleId, sid, consume, ITEM_CHANGE_REASON.ARTIFACT_REBUILD);
if (!result) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH);
let returnArtifact: ArtifactParam[] = [];
for(let artifact of artifacts) {
let dicArtifactZero = getArtifactStageZero(artifact.artifactId);
if(!dicArtifactZero) continue;
let { artifactId, goodId, quality, qualityStage } = dicArtifactZero;
let result = await ArtifactModel.updateInfoBySeqId(roleId, artifact.seqId, { artifactId, id: goodId, quality, qualityStage, lv: 0 });
if(result && result.hid > 0) {
let hero = await HeroModel.findByHidAndRole(result.hid, roleId);
await calculateCeWithHero(HERO_SYSTEM_TYPE.ARTIFACT_REBUILD, roleId, serverId, sid, result.hid, {}, { artifact: result, skinId: hero.skinId, job: hero.job });
}
returnArtifact.push(new ArtifactParam(result));
}
let goods = await addItems(roleId, roleName, sid, rebuildConsumes, ITEM_CHANGE_REASON.ARTIFACT_REBUILD);
return resResult(STATUS.SUCCESS, { artifacts: returnArtifact, goods });
}
public async decompose(msg: { seqIds: number[] }, session: BackendSession) {
let roleId: string = session.get('roleId');
let sid: string = session.get('sid');
let roleName: string = session.get('roleName');
let { seqIds } = msg;
if(seqIds.length > BAG.BAG_ARTIFACT_DECOMPOSE_UPLIMITED) {
return resResult(STATUS.EQUIP_DECOMPOSE_IS_UPLIMIT);
}
let artifacts = await ArtifactModel.findbySeqIds(roleId, seqIds);
if (artifacts.length < seqIds.length) return resResult(STATUS.ARTIFACT_IS_NOT_FIND);
let cost: ItemInter[] = [], add: ItemInter[] = [], delSeqIds: number[] = [];
for(let artifact of artifacts) {
if(artifact.hid > 0 || hasArtifactStrength(artifact)) return resResult(STATUS.ARTIFACT_CANNOT_DECOMPOSE);
let dicArtifact = getArtifactWithQuality(artifact.artifactId);
if(!dicArtifact || !dicArtifact.canDecompose) return resResult(STATUS.ARTIFACT_CANNOT_DECOMPOSE);
let dicZeroArtifact = getArtifactStageZero(artifact.artifactId);
if(!dicZeroArtifact) continue;
add.push(...dicZeroArtifact.generalItem);
cost.push({ seqId: artifact.seqId, id: artifact.id, count: 1 });
delSeqIds.push(artifact.seqId);
}
let costResult = await handleCost(roleId, sid, cost, ITEM_CHANGE_REASON.EQUIP_DECOMPOSE); // 删掉装备
if(!costResult) return resResult(STATUS.BATTLE_CONSUMES_NOT_ENOUGH);
let result = await addItems(roleId, roleName, sid, add, ITEM_CHANGE_REASON.EQUIP_DECOMPOSE);
return resResult(STATUS.SUCCESS, { delSeqIds, goods: combineItems(result) });
}
}

View File

@@ -29,6 +29,7 @@ import { RoleCeModel } from "../../../db/RoleCe";
import { CalCe } from "../../../services/role/calCe";
import { getSchoolPoint } from "../../../services/roleService";
import { LadderMatchModel } from "../../../db/LadderMatch";
import { ArtifactModel } from "../../../db/Artifact";
export default function (app: Application) {
@@ -756,6 +757,10 @@ export class FriendHandler {
let heroParam = new HeroDetailParam(hero);
heroParam.setAttributes(attributes);
heroParam.setJewels(jewels);
if(hero.artifact > 0) {
let artifact = await ArtifactModel.findbySeqId(hisRoleId, hero.artifact);
if(artifact) heroParam.setArtifact(artifact);
}
heroParam.setRole(
role.title,

View File

@@ -28,6 +28,7 @@ import { saveRebirthLog } from '../../../pubUtils/logUtil';
import { isGoodsHidden, isHeroHidden } from '../../../services/dataService';
import { LadderMatchModel } from '../../../db/LadderMatch';
import { PvpSaveDataModel } from '../../../db/PvpSaveData';
import { ArtifactModel } from '../../../db/Artifact';
export default function (app: Application) {
new HandlerService(app, {});
@@ -565,7 +566,8 @@ export class HeroHandler {
job: dicNewJob.jobid,
ePlace: newEplace
}
let { curHero } = await calculateCeWithHero(HERO_SYSTEM_TYPE.SKIN, roleId, serverId, sid, hero.hid, update, { hero });
let artifact = hero.artifact? await ArtifactModel.findbySeqId(roleId, hero.artifact): null;
let { curHero } = await calculateCeWithHero(HERO_SYSTEM_TYPE.SKIN, roleId, serverId, sid, hero.hid, update, { hero, artifact });
let resultHero = new HeroParam(curHero);
return resResult(STATUS.SUCCESS, { curHero: {...pick(resultHero, ['hid', 'skins', 'skinId', 'job', 'talent', 'usedTalentPoint']), ePlace: newEplace }});
}

View File

@@ -74,6 +74,7 @@ export function checkRouteParam(route: string, msg: any) {
case "role.taskHandler.getPvpTaskList":
case "role.taskHandler.getTaskList":
case "role.taskHandler.receiveActiveReward":
case "role.artifactHandler.composeAll":
{
break;
}
@@ -1308,6 +1309,44 @@ export function checkRouteParam(route: string, msg: any) {
if(!checkNaturalNumbers(msg.originJewel, msg.targetJewel)) return false;
break;
}
case "role.artifactHandler.putOn":
{
if(!checkNaturalNumbers(msg.seqId, msg.hid)) return false;
break;
}
case "role.artifactHandler.putOff":
{
if(!checkNaturalNumbers(msg.seqId)) return false;
break;
}
case "role.artifactHandler.lvUp":
{
if(!checkNaturalNumbers(msg.seqId)) return false;
if(!checkBoolean(msg.isOneClick)) return false;
break;
}
case "role.artifactHandler.compose":
{
if(!checkNaturalNumbers(msg.seqId)) return false;
if(!checkNumberArray(msg.material)) return false;
if(!checkNaturalArray(msg.generalItems)) return false;
for(let { id, count } of msg.generalItems) {
if(!checkNaturalNumbers(id, count)) return false;
}
break;
}
case "role.artifactHandler.transfer":
{
if(!checkNaturalNumbers(msg.seqId, msg.type)) return false;
break;
}
case "role.artifactHandler.previewRebuild":
case "role.artifactHandler.rebuild":
case "role.artifactHandler.decompose":
{
if(!checkNumberArray(msg.seqIds)) return false;
break;
}
case "role.friendHandler.searchUser":
{
if(!checkNaturalStrings(msg.value)) return false;

View File

@@ -8,7 +8,7 @@ import { getCurTask, getPvpTask } from './task/taskService';
import { RoleType } from '../db/Role';
import { Application, FrontendOrBackendSession, pinus, RpcClient } from 'pinus';
import { getRandEelmWithWeight, resResult } from '../pubUtils/util';
import { STATUS, PUSH_BATCH, PUSH_INTERVAL, CONSUME_TYPE, HERO_SELECT, ENTERY_ROLE_PICK, JEWEL_SELECT, ITEM_SELECT, SKIN_SELECT, PUSH_ROUTE } from '../consts';
import { STATUS, PUSH_BATCH, PUSH_INTERVAL, CONSUME_TYPE, HERO_SELECT, ENTERY_ROLE_PICK, JEWEL_SELECT, ITEM_SELECT, SKIN_SELECT, PUSH_ROUTE, ARTIFACT_SELECT } from '../consts';
import { getAllShopList } from './shopService';
import { getGeneralRank, getRankFirstReward } from './rankService';
import { getFriendList, getApplyList } from './friendService';
@@ -50,6 +50,7 @@ import { getLadderData } from './ladderService';
import { dispatch } from '../pubUtils/dispatcher';
import { PvpDataReturn } from '../domain/battleField/pvp';
import { getHiddenData } from './dataService';
import { ArtifactModel } from '../db/Artifact';
/**
* init: 初始的时候是否推送 true-推 false-不推
@@ -123,6 +124,7 @@ export async function getModuleData(type: string, data: { role: RoleType, sessio
let jewels = await JewelModel.findbyRole(role.roleId, JEWEL_SELECT.ENTRY);
let items = await ItemModel.findbyRole(role.roleId, ITEM_SELECT.ENTRY);
let skins = await SkinModel.findbyRole(role.roleId, SKIN_SELECT.ENTRY);
let artifacts = await ArtifactModel.findbyRole(role.roleId, ARTIFACT_SELECT.ENTRY);
role['heros'] = heros.map(hero => new HeroParam(hero));
role['jewels'] = jewels;
@@ -131,6 +133,7 @@ export async function getModuleData(type: string, data: { role: RoleType, sessio
let apJson = await getAp(role.roleId, '', role.lv);
role['apJson'] = apJson;
role['ipLocation'] = role.fixedIpLocation||role.ipLocation||'未知';
role['artifacts'] = artifacts;
if (!role.showLineup) role.showLineup = role.topLineup.map(cur => cur.hid);
role.heads = role.heads.filter(cur => cur.status);

View File

@@ -1,9 +1,13 @@
import { getRandEelm, } from '../pubUtils/util';
import { EPlace, Stone } from "../db/Hero";
import { gameData, getJewelConditionByLvAndSeId, getRandEffectByGroupAndLevel } from "../pubUtils/data";
import { gameData, getArtifactWithQuality, getDicArtifactLvByPlanId, getDicArtifactQualityByStage, getJewelConditionByLvAndSeId, getNextArtifact, getNextArtifactQuality, getRandEffectByGroupAndLevel } from "../pubUtils/data";
import { JewelType, RandSe } from '../db/Jewel';
import { DicRandomEffectPool } from '../pubUtils/dictionary/DicRandomEffectPool';
import { getJewelRandSe } from './role/rewardService';
import { ArtifactModelType } from '../db/Artifact';
import { STATUS } from '../consts';
import { ItemInter } from '../pubUtils/interface';
import { combineItems } from './role/util';
export function getRandSeResult(id: number, randSe: RandSe[], originSe: RandSe[] = [], originId?: number) {
let { randomEffect, effectCount, lv } = gameData.jewel.get(id);
@@ -160,4 +164,56 @@ export function isRandSeUnLock(jewelId: number, randSeId: number, stones: Stone[
}
}
return stoneCnt >= dicJewelCondition.stoneCnt && stoneLv >= dicJewelCondition.stoneLv;
}
export function checkArtifactCanCompose(originArtifactId: number, artifact: ArtifactModelType) {
if(!artifact) return STATUS.ARTIFACT_IS_NOT_FIND;
// 宝物表
let dicArtifact = gameData.artifact.get(artifact.artifactId);
if(!dicArtifact) return STATUS.ARTIFACT_IS_NOT_FIND;
// 宝物品质表
let dicArtifactQuality = getDicArtifactQualityByStage(dicArtifact.quality, dicArtifact.qualityStage);
if(!dicArtifactQuality) return STATUS.DIC_DATA_NOT_FOUND;
// 狗粮不可装备
if(artifact.hid > 0) return STATUS.ARTIFACT_IS_EQUIPED;
// 狗粮不可强化
if(artifact.lv > 0) return STATUS.ARTIFACT_CAN_NOT_STRENGTHEN;
// 合成目标
let dicTargetArtifactQuality = getNextArtifact(originArtifactId);
if(!dicTargetArtifactQuality) return STATUS.DIC_DATA_NOT_FOUND;
// 检查狗粮品质
if(dicTargetArtifactQuality.materialId != dicArtifactQuality.uniqId) return STATUS.ARTIFACT_MATERIAL_QUALITY_ERR;
// 检查是否同名
if(dicTargetArtifactQuality.materialGroup == 1 && dicTargetArtifactQuality.group != dicArtifact.group) return STATUS.ARTIFACT_MATERIAL_QUALITY_ERR;
return STATUS.SUCCESS;
}
export function getRebuildConsume(artifacts: ArtifactModelType[]) {
let usedConsumes: ItemInter[] = [];
for(let artifact of artifacts) {
let dicArtifact = getArtifactWithQuality(artifact.artifactId);
if(!dicArtifact) continue;
if(!hasArtifactStrength(artifact)) continue;
for(let lv = 1; lv <= artifact.lv; lv++) {
let dicArtifactLv = getDicArtifactLvByPlanId(dicArtifact.lvAttrPlan, lv);
usedConsumes.push(...dicArtifactLv.consumes);
}
for(let stage = 0; stage < artifact.qualityStage; stage++) {
let dicArtifactQuality = getDicArtifactQualityByStage(dicArtifact.quality, stage);
let dicNextArtifactQuality = gameData.artifactQualityById.get(dicArtifactQuality?.nextId);
if(!dicNextArtifactQuality) continue;
let consumes = dicArtifactQuality.generalItem.map(({id, count}) => ({ id, count: count * dicNextArtifactQuality.materialCnt}));
usedConsumes.push(...consumes);
}
}
return combineItems(usedConsumes);
}
// 宝物是否有养成
export function hasArtifactStrength(artifact: ArtifactModelType) {
if(!artifact) return false;
return artifact.lv >= 1 || artifact.qualityStage > 0;
}

View File

@@ -1,4 +1,5 @@
import { ITEM_CHANGE_REASON, LADDER_OPP_STATUS, LADDER_SERVER_GAP_TIME, LADDER_STATUS, MAIL_TYPE, PUSH_ROUTE, REDIS_KEY, TA_USERSET_TYPE } from "../consts";
import { ArtifactModel } from "../db/Artifact";
import { HeroType } from "../db/Hero";
import { LadderMatchModel, LadderMatchType, LadderUpdateInter } from "../db/LadderMatch";
import { LadderMatchRecModel, LadderMatchRecType } from "../db/LadderMatchRec";
@@ -236,7 +237,7 @@ export async function getLadderOppStatus(ladderData: LadderMatchType, targetRole
* @param ladderData 需要populate过的ladderMatch表
* @returns
*/
export function generateInitRecInfo(isRobot: boolean, isDefense: boolean, rank: number, ladderData: LadderMatchType) {
export async function generateInitRecInfo(isRobot: boolean, isDefense: boolean, rank: number, ladderData: LadderMatchType) {
if(isRobot) {
let dicLadderDifficultRatio = gameData.ladderDifficultRatio.get(rank);
let dicWar = gameData.war.get(dicLadderDifficultRatio.gkId);
@@ -261,7 +262,12 @@ export function generateInitRecInfo(isRobot: boolean, isDefense: boolean, rank:
let defenseHeroes = ladderData.defense?.heroes||[];
for(let defenseHero of defenseHeroes) {
let hero = new LadderOppPlayerHeroInfo();
hero.setByDefenseHero(<HeroType>defenseHero.hero);
let dbHero = <HeroType>defenseHero.hero;
hero.setByDefenseHero(dbHero);
if(dbHero && dbHero.artifact) {
let artifact = await ArtifactModel.findbySeqId(role.roleId, dbHero.artifact);
hero.setArtifact(artifact);
}
heroes.push(hero);
}
}
@@ -411,7 +417,9 @@ export async function getLadderOppDetailData(rec: LadderMatchRecType) {
let hisLadderData = await LadderMatchModel.findByRoleIdAndInclude(rec.roleId2);
let dicWar = gameData.war.get(dicLadderDifficultRatio.gkId);
let dicWarJson = gameData.warJson.get(dicWar.dispatchJsonId);
result.setByPlayer(hisLadderData, dicWarJson);
let artifactSeids = hisLadderData.defense.heroes.map(cur => (<HeroType>cur.hero).artifact);
let artifacts = await ArtifactModel.findbySeqIds(rec.roleId2, artifactSeids);
result.setByPlayer(hisLadderData, dicWarJson, artifacts);
let attrByHid = await getHeroesAttributes(rec.roleId2);
for(let [hid, attribute] of attrByHid) {
result.setAttribute(hid, attribute.getAttributesToString());

View File

@@ -19,6 +19,7 @@ import { AttributeCal } from '../domain/roleField/attribute';
import { sendMessageToUserWithSuc } from './pushService';
import { SkinType } from '../db/Skin';
import { LadderMatchModel } from '../db/LadderMatch';
import { ArtifactModelType } from '../db/Artifact';
interface Param {
isInitRole?: boolean,
@@ -44,6 +45,8 @@ interface Param {
skins?: SkinType[],
stonesId?: number,
talentId?: number,
artifact?: ArtifactModelType,
job?: number,
}
export async function calculateCeWithHero(type: HERO_SYSTEM_TYPE, roleId: string, serverId: number, sid: string, hid: number, heroUpdate: HeroUpdate, param: Param = {}) {
@@ -130,7 +133,7 @@ export async function calculateCes(type: HERO_SYSTEM_TYPE, roleId: string, serve
}
case HERO_SYSTEM_TYPE.SKIN: // 7. 穿皮肤
{
let { hero: { quality, star, starStage, colorStar, colorStarStage, jobStage } } = param;
let { hero: { quality, star, starStage, colorStar, colorStarStage, jobStage }, artifact } = param;
for(let [hid, { skinId, job, ePlace, skins }] of heroUpdates) {
ceChangeTxt.push(`武将 ${hid} 穿上了皮肤 ${skinId}`);
calCe.setHeroBase(hid, skinId);
@@ -143,6 +146,7 @@ export async function calculateCes(type: HERO_SYSTEM_TYPE, roleId: string, serve
}
calCe.setEquipSuit(hid, skinId, ePlace);
calCe.setTalent(hid, skins);
if(artifact) calCe.setArtifactSeid(hid, skinId, job, artifact.artifactId);
}
break;
}
@@ -309,7 +313,7 @@ export async function calculateCes(type: HERO_SYSTEM_TYPE, roleId: string, serve
}
case HERO_SYSTEM_TYPE.TALENT_UNLOCK: // 30. 天赋解锁
case HERO_SYSTEM_TYPE.TALENT_LV: // 32. 天赋升级
case HERO_SYSTEM_TYPE.TALENT_RESET: // 30. 天赋洗点
case HERO_SYSTEM_TYPE.TALENT_RESET: // 33. 天赋洗点
{
let { talentId } = param;
for(let [hid, { skins }] of heroUpdates) {
@@ -354,6 +358,60 @@ export async function calculateCes(type: HERO_SYSTEM_TYPE, roleId: string, serve
ceChangeTxt.push(`后台重新计算`);
break;
}
case HERO_SYSTEM_TYPE.PUT_ARTIFACT: // 34. 装备宝物
{
let { artifact, job, skinId } = param;
if(!artifact) break;
for(let [hid ] of heroUpdates) {
calCe.setPutArtifact(hid, skinId, job, artifact);
calCe.setArtifactQuality(hid, artifact.artifactId);
calCe.setArtifactSeid(hid, skinId, job, artifact.artifactId);
ceChangeTxt.push(`武将 ${hid} 装备宝物 ${artifact.artifactId}`);
}
break;
}
case HERO_SYSTEM_TYPE.PUT_OFF_ARTIFACT: // 35. 卸下
{
for(let [hid ] of heroUpdates) {
calCe.setPutOffArtifact(hid);
ceChangeTxt.push(`武将 ${hid} 卸下宝物`);
}
break;
}
case HERO_SYSTEM_TYPE.ARTIFACT_LV: // 36.宝物升级
{
let { artifact } = param;
if(!artifact) break;
for(let [hid ] of heroUpdates) {
calCe.setArtifactLv(hid, artifact.artifactId, artifact.lv);
ceChangeTxt.push(`武将 ${hid} 装备的宝物 ${artifact.seqId} ${artifact.artifactId} 升至 ${artifact.lv}`);
}
break;
}
case HERO_SYSTEM_TYPE.ARTIFACT_QUALITY: // 37. 宝物升品
{
let { artifact, job, skinId } = param;
if(!artifact) break;
for(let [hid ] of heroUpdates) {
calCe.setArtifactQuality(hid, artifact.artifactId);
calCe.setArtifactSeid(hid, skinId, job, artifact.artifactId);
ceChangeTxt.push(`武将 ${hid} 装备的宝物 ${artifact.seqId} 升至 ${artifact.artifactId}`);
}
break;
}
case HERO_SYSTEM_TYPE.ARTIFACT_TRANSFER: // 38. 宝物转换
{
let { artifact, job, skinId } = param;
if(!artifact) break;
for(let [hid ] of heroUpdates) {
calCe.setArtifactLv(hid, artifact.artifactId, artifact.lv);
calCe.setArtifactQuality(hid, artifact.artifactId);
calCe.setArtifactSeid(hid, skinId, job, artifact.artifactId);
ceChangeTxt.push(`武将 ${hid} 装备的宝物 ${artifact.seqId} 转换至 ${artifact.artifactId}`);
}
break;
}
}
let { heroCe, roleInc } = calCe.getCeInc(); // 计算战力,获得有变化的武将战力
let changeHids: number[] = [];

View File

@@ -26,6 +26,7 @@ import { reportTAEvent } from './sdkService';
import { getVipPvpChallengeMaxCnt } from './activity/monthlyTicketService';
import { getHeroesAttributes } from './playerCeService';
import { setPvpSettleSeasonNumToRemote } from './timeTaskService';
import { ArtifactModel } from '../db/Artifact';
/**
* 返回对手三人信息
@@ -220,6 +221,7 @@ async function generPlayerOppHis(pvpdefense: PvpDefenseType, roleId: string, pos
let defCe = 0;
let attrByHid = await getHeroesAttributes(role.roleId);
for (let dbHero of dbHeroes) {
let artifact = dbHero.artifact? await ArtifactModel.findbySeqId(role.roleId, dbHero.artifact): null;
let h = defenseHeroes.find(cur => cur.actorId == dbHero.hid); // 阵容里是否有这个武将
let hs = heroScores.find(cur => cur.hid == dbHero.hid); // 这个武将是否有这个得分
if (!!h) {
@@ -227,7 +229,7 @@ async function generPlayerOppHis(pvpdefense: PvpDefenseType, roleId: string, pos
let warJson = mapWarJson.find(cur => cur.dataId == h.dataId);
if (warJson && warJson.relation == 2) {
let heroInfo = new PvpHeroInfo();
heroInfo.setHeroInfo(dbHero);
heroInfo.setHeroInfo(dbHero, artifact);
// heroInfo.setOutIndex(h.order);
let attr = attrByHid.get(h.actorId);
if(!attr) continue;
@@ -241,7 +243,7 @@ async function generPlayerOppHis(pvpdefense: PvpDefenseType, roleId: string, pos
}
} else {
let heroInfo = new PvpOtherHeroes(hs ? hs.score : 0);
heroInfo.setHeroInfo(dbHero);
heroInfo.setHeroInfo(dbHero, artifact);
otherHeroes.push(heroInfo);
}
}

View File

@@ -1,11 +1,12 @@
import { ABI_STAGE, ABI_STAGE_TO_TYPE, ABI_TYPE, ABI_TYPE_MAIN, LINEUP_NUM, SEID_TYPE, TALENT_RELATION_TYPE } from "../../consts";
import { ArtifactModelType } from "../../db/Artifact";
import { Connect, EPlace, HeroSkin, HeroType, HeroUpdate, Stone, Talent } from "../../db/Hero";
import { JewelType } from "../../db/Jewel";
import { RoleUpdate, Teraph } from "../../db/Role";
import { AttrCell, Attribute, EquipAttr, HeroAttr, RoleCeType, SchoolAttr, ScrollAttr } from "../../db/RoleCe";
import { TopHero } from "../../domain/dbGeneral";
import { AttributeCal } from "../../domain/roleField/attribute";
import { gameData, getEquipQualityIdByEquipIdAndPoint, getEquipStarAttrByStage, getEquipStrenthenAttr, getEquipSuitByHero, getFriendShipByIdAndLv, getHeroStarByQuality, getHeroWakeByQuality, getJewelConditionByLvAndSeId, getJobByGradeAndClass, getSchoolRateByStar, getScollByStar, getTeraph } from "../../pubUtils/data";
import { gameData, getDicArtifactLvByPlanId, getEquipQualityIdByEquipIdAndPoint, getEquipStarAttrByStage, getEquipStrenthenAttr, getEquipSuitByHero, getFriendShipByIdAndLv, getHeroStarByQuality, getHeroWakeByQuality, getJewelConditionByLvAndSeId, getJobByGradeAndClass, getSchoolRateByStar, getScollByStar, getTeraph } from "../../pubUtils/data";
import { DicRandomEffectPool } from "../../pubUtils/dictionary/DicRandomEffectPool";
import { DicSe } from "../../pubUtils/dictionary/DicSe";
import { addToMap, deepCopy } from "../../pubUtils/util";
@@ -45,13 +46,13 @@ export class CalCe {
let lv = this.data.heroLv.get(hid)||1;
for(let attrId = ABI_TYPE.ABI_HP; attrId < ABI_TYPE.ABI_MAX; attrId++) {
if(!this.data.heroAttrs.has(`${hid}_${attrId}`) && !this.data.globalAttrs.has(attrId)) continue;
let { mainBase = 0, mainBaseUp = 0, subBase = 0, job = 0, starUp = 0, connect = 0, talent = 0, equipQuality = 0, equipStrength = 0, equipStar = 0, equipSuit = 0, jewel = 0, stone = 0 } = this.data.heroAttrs.get(`${hid}_${attrId}`)||{};
let { mainBase = 0, mainBaseUp = 0, subBase = 0, job = 0, starUp = 0, connect = 0, talent = 0, equipQuality = 0, equipStrength = 0, equipStar = 0, equipSuit = 0, jewel = 0, stone = 0, artifactLv = 0, artifactQuality = 0, artifactSeid = 0 } = this.data.heroAttrs.get(`${hid}_${attrId}`)||{};
let { school = 0, teraph = 0, title = 0, scroll = 0, skin = 0 } = this.data.getGlobalAttrById(attrId)||{};
let val = 0, str = '';
if(ABI_TYPE_MAIN.indexOf(attrId) != -1) {
// {[ hp1 + lv * hp2 ] * ( 1 + hp5 ) + [( hp6 + hp7 ) * ( 1 + hp8 )]} * ( 1 + hp9 ) + hp10 + hp11
val = (( mainBase + job + lv * ( starUp + mainBaseUp ) ) * ( 1 + connect/100 ) + (( equipQuality + equipStrength ) * ( 1 + ( equipStar/100 + equipSuit/100 )))) * ( 1 + jewel/100 + school/100 + talent/100 + skin/100 ) + stone + teraph + title + scroll;
str += `{[${mainBase}+${job}+${lv}*(${starUp}+${mainBaseUp})]* ( 1 + ${connect}/100) + [(${equipQuality}+${equipStrength}) * ( 1 + ${equipStar}/100+${equipSuit}/100)]} * (1+${jewel}/100+${school}/100+${talent}/100+${skin}/100 )+${stone}+${teraph}+${title}+${scroll}`;
// {[ hp1 + lv * hp2 ] * ( 1 + hp5 ) + [( hp6 + hp7 ) * ( 1 + hp8 )]} * ( 1 + hp9 ) + hp10 + hp11 + hp14
val = (( mainBase + job + lv * ( starUp + mainBaseUp ) ) * ( 1 + connect/100 ) + (( equipQuality + equipStrength ) * ( 1 + ( equipStar/100 + equipSuit/100 )))) * ( 1 + jewel/100 + school/100 + talent/100 + skin/100 + artifactSeid/100) + stone + teraph + title + scroll + artifactLv + artifactQuality;
str += `{[${mainBase}+${job}+${lv}*(${starUp}+${mainBaseUp})]* ( 1 + ${connect}/100) + [(${equipQuality}+${equipStrength}) * ( 1 + ${equipStar}/100+${equipSuit}/100)]} * (1+${jewel}/100+${school}/100+${talent}/100+${skin}/100+${artifactSeid}/100)+${stone}+${teraph}+${title}+${scroll}+${artifactLv}+${artifactQuality}`;
} else {
// attr1 + attr2 + attr4 + attr5 + attr6 + attr7 + attr9
val = subBase + job + teraph + school + title + jewel + equipStar;
@@ -511,6 +512,86 @@ export class CalCe {
}
}
// 卸下宝物
public setPutOffArtifact(hid: number) {
this.data.clearHeroAttrByHid(hid, 'artifactLv');
this.data.clearHeroAttrByHid(hid, 'artifactQuality');
this.data.clearHeroAttrByHid(hid, 'artifactSeid');
}
// 装备宝物
public setPutArtifact(hid: number, skinId: number, job: number, artifact: ArtifactModelType) {
this.data.clearHeroAttrByHid(hid, 'artifactLv');
this.data.clearHeroAttrByHid(hid, 'artifactQuality');
this.data.clearHeroAttrByHid(hid, 'artifactSeid');
if(artifact) {
this.setArtifactLv(hid, artifact.artifactId, artifact.lv);
this.setArtifactQuality(hid, artifact.artifactId);
this.setArtifactSeid(hid, skinId, job, artifact.lv);
}
}
// 宝物等级
public setArtifactLv(hid: number, artifactId: number, lv: number) {
this.data.clearHeroAttrByHid(hid, 'artifactLv');
let dicArtifact = gameData.artifact.get(artifactId);
if(!dicArtifact) return;
let dicArtifactLv = getDicArtifactLvByPlanId(dicArtifact.lvAttrPlan, lv);
if(!dicArtifactLv) return;
let ceAttr = dicArtifactLv.attr||[];
for(let { id, attr } of ceAttr) {
let heroAttr = this.data.getHeroAttrByHidAndId(hid, id);
heroAttr.artifactLv = attr;
}
}
// 宝物品质
public setArtifactQuality(hid: number, artifactId: number) {
this.data.clearHeroAttrByHid(hid, 'artifactQuality');
let dicArtifact = gameData.artifact.get(artifactId);
if(!dicArtifact) return;
// 基础属性
let dicArtifactQualityPlan = gameData.artifactQualityPlan.get(dicArtifact.qualityAttrPlan);
if(!dicArtifactQualityPlan) return;
let ceAttr = dicArtifactQualityPlan.attr||[];
for(let { id, attr } of ceAttr) {
let heroAttr = this.data.getHeroAttrByHidAndId(hid, id);
heroAttr.artifactQuality = attr;
}
}
// 宝物词条
public setArtifactSeid(hid: number, skinId: number, job: number, artifactId: number) {
this.data.clearHeroAttrByHid(hid, 'artifactSeid');
let dicArtifact = gameData.artifact.get(artifactId);
if(!dicArtifact) return;
let dicJob = gameData.job.get(job);
if(!dicJob) return;
let seids: number[] = []; // id, seids
for(let seid of dicArtifact.seids) {
let dicArtifactSeid = gameData.artifactSeid.get(seid);
if(!dicArtifactSeid) continue;
if(dicArtifactSeid.jobClass != 0 && dicArtifactSeid.jobClass != dicJob.job_class) continue;
if(dicArtifactSeid.hid != 0 && dicArtifactSeid.hid != skinId) continue;
if(dicArtifactSeid.quality > dicArtifact.quality) continue;
seids.push(dicArtifactSeid.seid);
}
let { ratioUp } = this.addSeidEffect(seids);
for(let [attrId, val] of ratioUp) {
let heroAttr = this.data.getHeroAttrByHidAndId(hid, attrId);
heroAttr.artifactSeid = val;
}
}
// 添加技能增加的被动属性
private addSeidEffect(seidList: number[]) {
let fixUp = new Map<number, number>(), ratioUp = new Map<number, number>();
@@ -991,6 +1072,9 @@ abstract class HeroAllAttr {
jewel: number = 0; // hp9 & attr7天晶随机属性值(jewel的ranSe对应dic_zyz_randomEffectPool)
stone: number = 0; // hp10, 地玉增加的固定值(dic_zyz_stone的attribute)
mainBaseUp: number = 0; // hp2, 基础成长(dic_zyz_hero的hp_up)
artifactLv: number = 0; // hp14 宝物等级(dic_zyz_artifactLvPlan的attr)
artifactQuality: number = 0; // hp14 宝物品质(dic_zyz_artifactQualityPlan的attr)
artifactSeid: number = 0; // hp9 宝物词条(dic_zyz_artifactSeid算出来的)
constructor(hid: number, attrId: number, ) {
this.hid = hid;
@@ -1041,6 +1125,12 @@ class HeroMainAttr extends HeroAllAttr {
this.stone = value; break;
case HERO_MAIN_ATTR_INDEX.BASE_UP:
this.mainBaseUp = value; break;
case HERO_MAIN_ATTR_INDEX.ARTIFACT_LV:
this.artifactLv = value; break;
case HERO_MAIN_ATTR_INDEX.ARTIFACT_QUALITY:
this.artifactQuality = value; break;
case HERO_MAIN_ATTR_INDEX.ARTIFACT_SEID:
this.artifactSeid = value; break;
}
}
}
@@ -1089,6 +1179,15 @@ class HeroMainAttr extends HeroAllAttr {
case HERO_MAIN_ATTR_INDEX.BASE_UP:
values.push(this.mainBaseUp);
break;
case HERO_MAIN_ATTR_INDEX.ARTIFACT_LV:
values.push(this.artifactLv);
break;
case HERO_MAIN_ATTR_INDEX.ARTIFACT_QUALITY:
values.push(this.artifactQuality);
break;
case HERO_MAIN_ATTR_INDEX.ARTIFACT_SEID:
values.push(this.artifactSeid);
break;
}
}
return values;
@@ -1278,6 +1377,9 @@ enum HERO_MAIN_ATTR_INDEX {
JEWEL = 10, // hp9天晶随机属性值(jewel的ranSe对应dic_zyz_randomEffectPool)
STONE = 11, // hp10, 地玉增加的固定值(dic_zyz_stone的attribute)
BASE_UP = 12, // hp2, 角色基础属性成长(dic_zyz_hero的hp_up)
ARTIFACT_LV = 13, // hp14, 宝物等级
ARTIFACT_QUALITY = 14, // hp14, 宝物品质
ARTIFACT_SEID = 15, // hp9宝物词条
END
}

View File

@@ -1,23 +1,18 @@
import { ITID, CONSUME_TYPE, ITEM_TABLE, CURRENCY, CURRENCY_TYPE, MAIL_TYPE, HANDLE_REWARD_TYPE, HERO_SYSTEM_TYPE, CURRENCY_BY_TYPE, ITEM_CHANGE_REASON, TA_USERSET_TYPE, TA_EVENT, POP_UP_SHOP_CONDITION_TYPE, ROLE_SELECT, FIGURE_UNLOCK_CONDITION, PUSH_ROUTE } from '../../consts';
import { getDecimalCnt, getRandEelm, getRandEelmWithWeight, getRandSingleEelm, getRandValueByMinMax, resResult } from '../../pubUtils/util';
import { ITID, CONSUME_TYPE, ITEM_TABLE, CURRENCY_TYPE, MAIL_TYPE, HANDLE_REWARD_TYPE, HERO_SYSTEM_TYPE, CURRENCY_BY_TYPE, ITEM_CHANGE_REASON, TA_USERSET_TYPE, TA_EVENT, POP_UP_SHOP_CONDITION_TYPE, ROLE_SELECT, FIGURE_UNLOCK_CONDITION, PUSH_ROUTE } from '../../consts';
import { getDecimalCnt, getRandEelm, getRandEelmWithWeight, getRandValueByMinMax, } from '../../pubUtils/util';
import { RoleModel, RoleType } from '../../db/Role';
import { setAp } from '../actionPointService';
import { ItemModel, ItemType } from '../../db/Item';
import { STATUS } from '../../consts/statusCode';
import { pinus } from 'pinus';
import { ItemInter, RewardInter, } from '../../pubUtils/interface';
import { gameData } from '../../pubUtils/data';
import { ItemModel, } from '../../db/Item';
import { ItemInter, } from '../../pubUtils/interface';
import { gameData, getDefArtifactByGid } from '../../pubUtils/data';
import { uniq } from 'underscore';
import { EPlace, HeroModel, HeroType, HeroUpdate } from '../../db/Hero';
import { EPlace, HeroModel, HeroType, } from '../../db/Hero';
import { Figure } from '../../domain/dbGeneral';
import { CreateHeroParam, HeroShowParam, JewelParam } from '../../domain/roleField/hero';
import { ArtifactParam, JewelParam } from '../../domain/roleField/hero';
import { HeroSkin } from '../../db/Hero';
import { errlogger } from '../../util/logger';
import { BAG } from '../../pubUtils/dicParam';
import { sendMailByContent } from '../mailService';
import { SkinModel, SkinUpdate } from '../../db/Skin';
import { getInitHeroById } from '../roleService';
import { getActivities } from '../activity/activityService';
import { SkinModel, } from '../../db/Skin';
import { reportTAEvent, reportTAUserSet } from '../sdkService';
import { saveCoinChangeLog, saveFigureInfoLog, saveGoldChangeLog, saveItemChangeLog } from '../../pubUtils/logUtil';
import { JewelModel, JewelType, jewelUpdate, RandSe } from '../../db/Jewel';
@@ -25,16 +20,17 @@ import { updateEplaces } from '../equipService';
import { combineItems, getCoinEventProperties, getGoldEventProperties, sortItems } from './util';
import { nowSeconds } from '../../pubUtils/timeUtil';
import { calculateCeWithHero, calculateCeWithRole } from '../playerCeService';
import { sendMessageToUsersWithSuc, sendMessageToUserWithSuc } from '../pushService';
import { sendMessageToUserWithSuc } from '../pushService';
import { filterGoods } from '../dataService';
import { ArtifactModel, ArtifactModelType, ArtifactModelUpdate } from '../../db/Artifact';
export async function handleCost(roleId: string, sid: string, goods: Array<ItemInter>, reason: ITEM_CHANGE_REASON) {
let { items, jewels, gold, coin } = sortItems(goods, HANDLE_REWARD_TYPE.COST);
let { items, jewels, gold, coin, artifacts } = sortItems(goods, HANDLE_REWARD_TYPE.COST);
let jewelSeqIds = jewels.map(cur => cur.seqId);
let resJewels: JewelType[] = [];
let artifactSeqIds = artifacts.map(cur => cur.seqId);
let resArtifacts: ArtifactModelType[] = [];
// 检查货币是否充足
let role = await RoleModel.findByRoleId(roleId);
@@ -50,6 +46,12 @@ export async function handleCost(roleId: string, sid: string, goods: Array<ItemI
if (resJewels.length < jewels.length)
return false;
}
//检查宝物是否存在
if (artifacts.length > 0) {
resArtifacts = await ArtifactModel.findbySeqIds(roleId, artifactSeqIds);
if (resArtifacts.length < artifacts.length)
return false;
}
//检查并修改道具
if (items.length > 0) {
let { hasError, result } = await ItemModel.decreaseItems(roleId, items);
@@ -90,6 +92,25 @@ export async function handleCost(roleId: string, sid: string, goods: Array<ItemI
sendMessageToUserWithSuc(roleId, PUSH_ROUTE.JEWEL_DEL, { jewels: jewels.map(jewel => ({ seqId: jewel.seqId, id: jewel.id, inc: -1, reason })) }, sid);
}
//删除宝物
if (resArtifacts.length > 0) {
let heroMap = new Map<number, { artifact: ArtifactModelType}>();
for(let artifact of resArtifacts) {
if(artifact.hid > 0) {
heroMap.set(artifact.hid, { artifact });
}
}
for(let [hid, { artifact } ] of heroMap) {
// 脱下天晶石
await ArtifactModel.putOnOrOff(roleId, artifact.id, 0);
await calculateCeWithHero(HERO_SYSTEM_TYPE.PUT_ARTIFACT, roleId, role.serverId, sid, hid, { artifact: 0 });
}
let artifacts = await ArtifactModel.deleteBySeqIds(roleId, artifactSeqIds);
saveItemChangeLog(roleId, artifacts.map(artifact => ({ id: artifact.id, count: 1, inc: -1 })), reason);
sendMessageToUserWithSuc(roleId, PUSH_ROUTE.ARTIFACT_DEL, { artifacts: artifacts.map(artifact => ({ seqId: artifact.seqId, id: artifact.id, inc: -1, reason })) }, sid);
}
//消耗玩家货币
if (gold.length > 0 || coin.length > 0) {
let costGold = gold.reduce((pre, cur) => pre + cur.count, 0);
@@ -115,7 +136,7 @@ export async function handleCost(roleId: string, sid: string, goods: Array<ItemI
export async function addItems(roleId: string, roleName: string, sid: string, goods: Array<ItemInter>, reason: ITEM_CHANGE_REASON) {
goods = filterGoods(goods, obj => obj.id, roleId, reason);
let { items, jewels, gold, coin, ap, skins, figures } = sortItems(goods, HANDLE_REWARD_TYPE.RECEIVE);
let { items, jewels, gold, coin, ap, skins, figures, artifacts } = sortItems(goods, HANDLE_REWARD_TYPE.RECEIVE);
let showItems: { id: number, seqId?: number, count: number, isBag?: boolean }[] = [];
let role = await RoleModel.findByRoleId(roleId);
// 1. 装备处理
@@ -130,7 +151,7 @@ export async function addItems(roleId: string, roleName: string, sid: string, go
}
// 直接加的
let { jewels: jewelInfos } = await addJewels(roleId, roleName, <{id: number, hid?: number}[]>incJewels, reason);
let { jewels: jewelInfos } = await addJewels(roleId, roleName, <{id: number }[]>incJewels, reason);
for (let jewel of jewelInfos) {
showItems.push({ seqId: jewel.seqId, id: jewel.id, count: 1, isBag: true });
}
@@ -229,6 +250,39 @@ export async function addItems(roleId: string, roleName: string, sid: string, go
}
}
// 6. 宝物处理
if(artifacts.length > 0) {
let { artifactCount = 0 } = role;
let incArtifacts = artifacts, mailArtifacts: { id?: number, seqId?: number }[] = [];
if(artifacts.length + artifactCount > BAG.BAG_ARTIFACT_UPLIMITED) { // 装备上限
let inc = BAG.BAG_ARTIFACT_UPLIMITED - artifactCount;
if(inc < 0) inc = 0;
incArtifacts = artifacts.slice(0, inc);
mailArtifacts = artifacts.slice(inc);
}
// 直接加的
let { artifacts: artifactInfos } = await addArtifacts(roleId, roleName, <{id: number}[]>incArtifacts, reason);
for (let artifact of artifactInfos) {
showItems.push({ seqId: artifact.seqId, id: artifact.id, count: 1, isBag: true });
}
for(let artifact of combineItems(mailArtifacts)) {
showItems.push({ id: artifact.id, count: artifact.count, isBag: false });
}
//装备推送
if (!!artifactInfos.length)
sendMessageToUserWithSuc(roleId, PUSH_ROUTE.ARTIFACT_ADD, { artifacts: artifactInfos }, sid);
//统计装备
if (artifactInfos.length > 0) {
saveItemChangeLog(roleId, artifactInfos, reason);
}
// 发邮件的
if(mailArtifacts.length > 0) {
await sendMailByContent(MAIL_TYPE.ARTIFACT_OVER, roleId, { goods: combineItems(mailArtifacts) });
}
}
return showItems;
}
@@ -437,6 +491,20 @@ export function getJewelRandSe(id: number, seid: number) {
return new RandSe(id, dicRandom.id, rand);
}
export async function addArtifacts(roleId: string, roleName: string, artifacts: { id: number, }[], reason: number) {
let artifactInfos: ArtifactModelUpdate[] = [];
for(let { id } of artifacts) {
let dicArtifact = getDefArtifactByGid(id);
if(dicArtifact) {
let { goodId, artifactId, quality, qualityStage } = dicArtifact;
artifactInfos.push({ roleId, roleName, id: goodId, artifactId, quality, qualityStage });
}
}
const artifactResult = await ArtifactModel.createArtifacts(roleId, artifactInfos);
return { artifacts: artifactResult.map(artifact => new ArtifactParam(artifact, true, reason))}
}
export function getGoldId() {
return CURRENCY_BY_TYPE.get(CURRENCY_TYPE.GOLD);
}

View File

@@ -6,6 +6,7 @@ import { errlogger } from '../../util/logger';
export function sortItems(goods: ItemInter[], handleType: HANDLE_REWARD_TYPE) {
let items: { id: number, count: number }[] = []; // 可叠加道具
let jewels: { seqId?: number, id?: number, hid?: number }[] = []; // 不可叠加装备
let artifacts: { seqId?: number, id?: number }[] = []; // 不可叠加宝物
let gold: { count: number, isPay: boolean }[] = []; // 金币
let coin: number[] = [];
let ap: number = 0;
@@ -74,11 +75,21 @@ export function sortItems(goods: ItemInter[], handleType: HANDLE_REWARD_TYPE) {
}
}
}
} else if (table == ITEM_TABLE.ARTIFACT) {
if(handleType == HANDLE_REWARD_TYPE.RECEIVE) {
for(let i = 0; i < good.count; i++) {
artifacts.push({ id: good.id })
}
} else {
if(!!good.seqId) {
artifacts.push({ seqId: good.seqId });
}
}
}
}
return { items, jewels, gold, coin, ap, skins, figures }
return { items, jewels, gold, coin, ap, skins, figures, artifacts }
}
export function getGoldEventProperties(inc: number, count: number, reason: ITEM_CHANGE_REASON) {
@@ -98,7 +109,7 @@ export function combineItems(items: { id?: number, count?: number, seqId?: numbe
for(let { id, count = 1, seqId, isBag } of items) {
let dicGoods = gameData.goods.get(id);
let dicItid = ITID.get(dicGoods.itid);
if(dicItid.table != 'jewel') {
if(dicItid.table != 'jewel' && dicItid.table != 'artifact') {
let index = result.findIndex(cur => cur.id == id);
if(index == -1) {
result.push({ id, count, seqId, isBag });

View File

@@ -1185,7 +1185,7 @@ export class CheckSingleTask {
if(newUnlockSeCnt < dicTaskParam[1]) break;
let records = await getRecord();
if(records.indexOf(`${newJewel.seqId}`)) {
if(records.indexOf(`${newJewel.seqId}`) == -1) {
records.push(`${newJewel.seqId}`);
result = { records, inc: 1 };
}
@@ -1359,6 +1359,36 @@ export class CheckSingleTask {
}
break;
}
case TASK_TYPE.ARTIFACT_LV: // 127. 强化X件宝物至X级
{
let { artifacts } = param;
let records = await getRecord();
for(let { seqId, lv, hid } of artifacts) {
if(hid > 0 && lv >= dicTaskParam[1] && records.indexOf(`${seqId}`) == -1) {
records.push(`${seqId}`);
}
}
result = { records, set: records.length };
break;
}
case TASK_TYPE.ARTIFACT_QUALITY_EQUIP: // 128. 穿戴X件品质为X的宝物
{
let { artifacts } = param;
let records = await getRecord();
for(let { seqId, quality, hid } of artifacts) {
if(hid > 0 && quality >= dicTaskParam[1] && records.indexOf(`${seqId}`) == -1) {
records.push(`${seqId}`);
}
}
result = { records, set: records.length };
break;
}
case TASK_TYPE.ARTIFACT_COMPOSE: // 129. 合成X次宝物
{
let { count } = param;
result = { inc: count };
break;
}
}
return result
}

View File

@@ -157,6 +157,8 @@ export const PUSH_ROUTE = {
ITEM_UPDATE: 'onItemUpdate',
JEWEL_DEL: 'onJewelDel',
JEWEL_ADD: 'onJewelAdd',
ARTIFACT_DEL: 'onArtifactDel',
ARTIFACT_ADD: 'onArtifactAdd',
HEAD_CHANGE: 'onHeadChange',
TASK_UPDATE: 'onTaskUpdate',
ACTIVITY_TASK_UPDATE: 'onActivityTaskUpdate',

View File

@@ -34,6 +34,12 @@ export enum HERO_SYSTEM_TYPE {
RE_CAL = 31, // 重新计算
TALENT_LV = 32, // 天赋升级
TALENT_RESET = 33, // 天赋重置
PUT_ARTIFACT = 34, // 装备宝物
PUT_OFF_ARTIFACT = 35, // 卸下宝物
ARTIFACT_LV = 36, // 宝物等级
ARTIFACT_QUALITY = 37, // 宝物品质
ARTIFACT_TRANSFER = 38, // 宝物转换
ARTIFACT_REBUILD = 39, // 宝物重铸
};
// 武将上限

View File

@@ -38,6 +38,7 @@ export const CONSUME_TYPE = {
DICE: 16, // 骰子
DRAWING: 17, // 图纸
VOUCHER: 18, // 代金券
ARTIFACT_GENERAL: 19, // 宝物通用
};
export enum ROLE_TERAPH {
@@ -96,6 +97,7 @@ export const ITEM_TABLE = {
HERO: 'hero',
SKIN: 'skin',
JEWEL: 'jewel',
ARTIFACT: 'artifact',
}
const itid_array = [
@@ -148,7 +150,9 @@ const itid_array = [
{ id: 60, name: '衣服天晶石', table: 'jewel' },
{ id: 61, name: '头饰天晶石', table: 'jewel' },
{ id: 62, name: '行具天晶石', table: 'jewel' },
{ id: 63, name: '代金券', table: 'item', type: CONSUME_TYPE.VOUCHER }
{ id: 63, name: '代金券', table: 'item', type: CONSUME_TYPE.VOUCHER },
{ id: 64, name: '宝物', table: 'artifact' },
{ id: 65, name: '宝物通用材料', table: 'item', type: CONSUME_TYPE.ARTIFACT_GENERAL },
];
export const ITID = new Map<number, { id: number, name: string, table: string, type?: number, isCurrency?: boolean, equipJewel?: number }>();

View File

@@ -61,6 +61,7 @@ export enum MAIL_TYPE {
GUILD_MAIL = 31, // 军团邮件
REBATE = 32, // 返利邮件
GROUP_SHOP_REFUND = 33, // 退费
ARTIFACT_OVER = 34, // 退费
};
export const SEND_NAME = '系统';

View File

@@ -19,7 +19,7 @@ export enum ROLE_SELECT {
export enum HERO_SELECT {
ENTRY = '-_id -attr -__v',
HERO_DETAIL = 'roleId roleName hid hName ce lv star colorStar quality job skins attr ePlace skinId connections subHid',
HERO_DETAIL = 'roleId roleName hid hName ce lv star colorStar quality job skins attr ePlace skinId connections artifact subHid',
// 排行榜中lineup字段
RANK_LINEUP = 'seqId roleId hid star colorStar lv quality job ce updatedAt skinId'
}
@@ -57,8 +57,12 @@ export enum FRIEND_SHIP_SELECT {
GET_FRIEND_VALUE = 'friendValue friendLv'
}
export const ENTERY_ROLE_PICK = ['roleId', 'roleName', 'serverId', 'ce', 'topLineupCe', 'coin', 'lv', 'exp', 'vLv', 'gold', 'heros', 'jewels', 'consumeGoods', 'title', 'teraphs', 'showLineup', 'heads', 'head', 'frames', 'frame', 'spines', 'spine', 'hasGuild', 'guildCode', 'todayZeroPoint', 'apJson', 'skins', 'totalPay', 'guide', 'hasInit', 'renameCnt', 'totalCost', 'guildName', 'isVip', 'createTime', 'ipLocation'];
export const ENTERY_ROLE_PICK = ['roleId', 'roleName', 'serverId', 'ce', 'topLineupCe', 'coin', 'lv', 'exp', 'vLv', 'gold', 'heros', 'jewels', 'artifacts', 'consumeGoods', 'title', 'teraphs', 'showLineup', 'heads', 'head', 'frames', 'frame', 'spines', 'spine', 'hasGuild', 'guildCode', 'todayZeroPoint', 'apJson', 'skins', 'totalPay', 'guide', 'hasInit', 'renameCnt', 'totalCost', 'guildName', 'isVip', 'createTime', 'ipLocation'];
export enum SURVEY_SELECT {
FIND = '-__v -_id -surveyName -roleIndex -reward -mailContent -receivedRole -createdAt -updatedAt'
}
}
export enum ARTIFACT_SELECT {
ENTRY = '-_id -__v -roleId -roleName -createdAt -updatedAt -status'
}

View File

@@ -53,6 +53,7 @@ export const COUNTER = {
CITY_ACTIVITY: { name: 'cityAct', def: 1 },
RACE_ACTIVITY: { name: 'raceAct', def: 1 },
HIDDEN_DATA: { name: 'hiddendata', def: 1 },
ARTIFACT_ID: { name: 'artid', def: 1 },
};
export const DEFAULT_HEROES = [19, 53,];
@@ -558,6 +559,11 @@ export const FILENAME = {
DIC_LADDER_MATCH: 'dic_zyz_ladderMatch',
DIC_GK_BRANCH_ELITE: 'dic_zyz_gk_branchElite',
DIC_GENERAL_GOODS: 'dic_zyz_general_goods',
DIC_ARTIFACT: 'dic_zyz_artifact',
DIC_ARTIFACT_LV_PLAN: 'dic_zyz_artifactLvPlan',
DIC_ARTIFACT_QUALITY_PLAN: 'dic_zyz_artifactQualityPlan',
DIC_ARTIFACT_QUALITY: 'dic_zyz_artifactQuality',
DIC_ARTIFACT_SEID: 'dic_zyz_artifactSeid',
}
export const WAR_RELATE_TABLES = [
@@ -763,7 +769,7 @@ export enum TASK_TYPE {
JEWEL_QUENCH_SUCCESS = 107, // 天晶淬炼成功
COM_BATTLE_LV = 108, // 军团寻宝
GUILD_REFINE = 109, // 军团兑换
EQUIP_STAR_UP_CNT_SUM = 110, // 装备总共升星x次
EQUIP_STAR_UP_CNT_SUM = 110, // 装备总共升星x次
BATTLE_MAIN_START = 111, // 挑战主线x次
BATTLE_TOWER_START = 112, // 挑战镇念塔x次
BATTLE_VESTIGE_START = 113, // 挑战遗迹x次
@@ -773,12 +779,15 @@ export enum TASK_TYPE {
COM_BATTLE_WIN = 117, // 寻宝胜利x次
BATTLE_EXPEDITION_START = 118, // 挑战远征x次
BATTLE_DUNGEON_START = 119, // 挑战秘境x次
GUILD_GOLD_DONATE = 120, // 军团元宝捐献x次
GUILD_GOLD_DONATE = 120, // 军团元宝捐献x次
LADDER_CNT = 121, // 名将擂台挑战x次
LADDER_SUCCESS_CNT = 122, // 名将擂台挑战胜利x次
LADDER_RANK = 123, // 名将擂台排名
CONNECT_ONE_HERO_MAX_LV = 124, // 羁绊最高等级的那一级达到x级
CONNECT_ONE_HERO_SUM_LV = 125, // 单个武将全部羁绊到达
ARTIFACT_LV = 127, // 强化X件宝物至X级
ARTIFACT_QUALITY_EQUIP = 128, // 穿戴X件品质为X的宝物
ARTIFACT_COMPOSE = 129, // 合成X次宝物
}
// 任务累积类型
@@ -1048,6 +1057,11 @@ export enum ITEM_CHANGE_REASON {
ACT_GROUP_SHOP_BUY = 153, // 团购
ACT_TURNTABLE_RECEIVE_BOX = 154, // 活动 幸运转盘领取宝箱
ACT_BIND_PHONE = 155, // 活动 绑定手机奖励
ARTIFACT_DECOMPOSE = 156, // 宝物分解
ARTIFACT_LV = 157, // 宝物升级
ARTIFACT_QUALITY = 158, // 宝物升品
ARTIFACT_TRANSFER = 159, // 宝物转换
ARTIFACT_REBUILD = 160, // 宝物重铸
}
export enum TA_EVENT {

View File

@@ -388,6 +388,17 @@ export const STATUS = {
JEWEL_LOCKED_CANNOT_INHERIT: { code: 30536, simStr: '该天晶石锁定中,无法进行继承' },
JEWEL_HAS_EQUPED: { code: 30537, simStr: '天晶石已经被装备' },
JEWEL_CANNOT_INHERIT: { code: 30538, simStr: '不能继承给类型不同或比自己低阶的天晶石' },
ARTIFACT_IS_NOT_FIND: { code: 30539, simStr: '宝物不存在' },
ARTIFACT_IS_NOT_EQUIPED: { code: 30540, simStr: '宝物未装备中' },
ARTIFACT_LV_MAX: { code: 30541, simStr: '宝物已升到最大' },
ARTIFACT_IS_EQUIPED: { code: 30542, simStr: '宝物被装备中' },
ARTIFACT_CAN_NOT_STRENGTHEN: { code: 30543, simStr: '作为材料的宝物不可被强化' },
ARTIFACT_MATERIAL_QUALITY_ERR: { code: 30544, simStr: '作为材料的宝物品质错误' },
ARTIFACT_MATERIAL_GROUP_ERR: { code: 30545, simStr: '作为材料的宝物必须和目标宝物同名' },
ARTIFACT_TYPE_ERR: { code: 30546, simStr: '未找到该宝物的该形态' },
ARTIFACT_TYPE_SAME: { code: 30547, simStr: '该宝物已经是该形态了' },
ARTIFACT_HAS_NO_STRENGTH: { code: 30548, simStr: '选择的宝物未强化过无法重铸' },
ARTIFACT_CANNOT_DECOMPOSE: { code: 30549, simStr: '选择的宝物不可分解' },
//全局养成30600-30699
ROLE_REACH_MAX_TITLE_LEVEL: { code: 30600, simStr: '玩家已达到最高的爵位' },

119
shared/db/Artifact.ts Normal file
View File

@@ -0,0 +1,119 @@
import BaseModel from './BaseModel';
import { index, getModelForClass, prop, DocumentType, modelOptions } from '@typegoose/typegoose';
import { CounterModel } from './Counter';
import { COUNTER } from '../consts';
import { RoleModel } from './Role';
/**
* 宝物
*/
@modelOptions({ schemaOptions: { id: false } })
@index({ roleId: 1, seqId: 1, id: 1 })
@index({ roleId: 1, quality: 1 })
@index({ batchCode: 1 })
@index({ status: 1 })
export default class Artifact extends BaseModel {
// 主键: artifact不同形态的宝物分开词条
@prop({ required: true })
seqId: number; // 唯一id
@prop({ required: true })
roleId: string; // 玩家id
@prop({ required: true })
roleName: string; // 玩家名
@prop({ required: true })
id: number; // 物品id
@prop({ required: true })
artifactId: number; // 宝物id
@prop({ required: true, default: 0 })
lv: number; // 强化等级
@prop({ required: true })
quality: number; // 品质 1-5 蓝紫橙红金
@prop({ required: true })
qualityStage: number; // 品质+n0开始
@prop({ required: true, default: 0 })
hid: number; // 装备的武将
@prop({ required: true })
batchCode: string; // 一键合成批处理
@prop({ required: true, default: 1 })
status: number; // 装备 1-生成 0-被合成删除
public static async findbySeqIds(roleId: string, seqIds: number[], select?: string) {
const result: ArtifactModelType[] = await ArtifactModel.find({ roleId, seqId: { $in: seqIds }, status: 1 }).select(select).lean();
return result;
}
public static async findbySeqId(roleId: string, seqId: number, select?: string) {
const result: ArtifactModelType = await ArtifactModel.findOne({ roleId, seqId, status: 1 }).select(select).lean();
return result;
}
public static async findbyRole(roleId: string, select = '') {
const result: ArtifactModelType[] = await ArtifactModel.find({ roleId, status: 1 }).select(select).lean();
return result;
}
public static async createArtifact(artifactInfo: ArtifactModelUpdate) {
const seqId = await CounterModel.getNewCounter(COUNTER.ARTIFACT_ID);
const doc = new ArtifactModel();
const update = Object.assign(doc.toJSON(), seqId, artifactInfo);
delete update._id;
const artifact: ArtifactModelType = await ArtifactModel.findOneAndUpdate({ seqId }, update, { upsert: true, new: true }).lean();
return artifact;
}
public static async createArtifacts(roleId: string, artifactInfos: ArtifactModelUpdate[]) {
let result: ArtifactModelType[] = [];
for (let artifactInfo of artifactInfos) {
let artifact = await this.createArtifact(artifactInfo);
result.push(artifact);
}
await RoleModel.increaseArtifact(roleId, result.length);
return result;
}
public static async putOnOrOff(roleId: string, seqId: number, hid: number) {
let rec: ArtifactModelType = await ArtifactModel.findOneAndUpdate({ seqId }, { $set: { hid } }, { new: true }).lean();
return rec;
}
public static async deleteBySeqIds(roleId: string, seqIds: number[]) {
let result: ArtifactModelType[] = await ArtifactModel.findbySeqIds(roleId, seqIds);
let delResult: { n: number, nModified: number, ok: number } = await ArtifactModel.updateMany({ roleId, seqId: { $in: seqIds } }, { $set: { status: 0 } });
await RoleModel.increaseArtifact(roleId, -1 * delResult.nModified);
return result;
}
public static async updateInfoBySeqId(roleId: string, seqId: number, update: ArtifactModelUpdate) {
let rec: ArtifactModelType = await ArtifactModel.findOneAndUpdate({ roleId, seqId }, { $set: update }, { new: true }).lean();
return rec;
}
public static async findByQuality(roleId: string, quality: number) {
let result: ArtifactModelType[] = await ArtifactModel.find({ roleId, quality, status: 1, hid: 0, qualityStage: 0 }).lean();
return result;
}
public static async findByBatchCode(batchCode: string) {
let result: ArtifactModelType[] = await ArtifactModel.find({ batchCode, status: 1 }).lean();
return result;
}
}
export const ArtifactModel = getModelForClass(Artifact);
export interface ArtifactModelType extends Pick<DocumentType<Artifact>, keyof Artifact> { }
export type ArtifactModelUpdate = Partial<ArtifactModelType>; // 将所有字段变成可选项

View File

@@ -161,7 +161,10 @@ export default class Hero extends BaseModel {
ePlace: EPlace[]; // 武将装备引用数组
@prop({ required: true, type: Reward, default: [], _id: false })
consumes: Reward[]; // 武将装备引用数组
consumes: Reward[]; // 消耗
@prop({ required: true, default: 0 })
artifact: number; // 宝物
@prop({ required: true, default: 0 })
subHid: number; // 副将

View File

@@ -56,7 +56,7 @@ export default class LadderMatch extends BaseModel {
public static async findByRoleIdAndInclude(roleId: string) {
const result: LadderMatchType = await LadderMatchModel.findOne({ roleId })
.populate('role', 'roleId roleName head frame spine heads frames spines title lv updatedAt')
.populate('defense.heroes.hero', 'hid skinId quality star colorStar lv skins job subHid')
.populate('defense.heroes.hero', 'hid skinId quality star colorStar lv skins job artifact subHid')
.lean();
return result;
}
@@ -78,7 +78,7 @@ export default class LadderMatch extends BaseModel {
public static async updateByRoleIdAndInclude(roleId: string, params: LadderUpdateInter) {
const defense: LadderMatchType = await LadderMatchModel.findOneAndUpdate({ roleId }, { $set: params}, { new: true })
.populate('role', 'roleId roleName head frame spine heads frames spines title lv updatedAt')
.populate('defense.heroes.hero', 'hid skinId quality star colorStar lv skins job subHid')
.populate('defense.heroes.hero', 'hid skinId quality star colorStar lv skins job artifact subHid')
.lean();
return defense;
}
@@ -98,7 +98,7 @@ export default class LadderMatch extends BaseModel {
public static async lock(serverId: number, roleId: string, rank: number) {
const defense: LadderMatchType = await LadderMatchModel.findOneAndUpdate({ serverId, roleId, rank, locked: 0 }, { $set: { locked: 1 }}, { new: true })
.populate('role', 'roleId roleName head frame spine heads frames spines title lv updatedAt')
.populate('defense.heroes.hero', 'hid skinId quality star colorStar lv skins job subHid')
.populate('defense.heroes.hero', 'hid skinId quality star colorStar lv skins job artifact subHid')
.lean();
return defense;
}

View File

@@ -191,6 +191,8 @@ export default class Role extends BaseModel {
jewelCount: number; // 装备数量
@prop({ required: true })
equipStarSum: number; // 装备上的星级的数量
@prop({ required: true, default: 0 })
artifactCount: number; // 宝物数量
@prop({ required: true, default: 0 })
coin: number; // 总铜钱
@@ -737,6 +739,12 @@ export default class Role extends BaseModel {
return role;
}
// 宝物上限
public static async increaseArtifact(roleId: string, count: number) {
const role: RoleType = await RoleModel.findOneAndUpdate({ roleId }, { $inc: { artifactCount: count } }, { new: true }).lean();
return role;
}
// 支付记录
public static async increaseTotalPay(roleId: string, price: number) {
const role: RoleType = await RoleModel.findOneAndUpdate({ roleId }, { $inc: { totalPay: price } }, { new: true }).lean();

View File

@@ -1,5 +1,6 @@
import { mongoose, prop, Ref } from "@typegoose/typegoose";
import { LADDER_STATUS } from "../../consts";
import { ArtifactModelType } from "../../db/Artifact";
import Hero, { HeroType, Talent } from '../../db/Hero';
import { LadderMatchType } from "../../db/LadderMatch";
import { LadderMatchRecType } from "../../db/LadderMatchRec";
@@ -56,6 +57,15 @@ export class LadderOppPlayerInDB {
rank: number;
}
class HeroArtifact {
@prop({ required: true })
artifactId: number;
@prop({ required: true })
lv: number;
}
// ladderMatchRec
export class LadderOppPlayerHeroInfo {
@prop({ required: true })
@@ -70,6 +80,8 @@ export class LadderOppPlayerHeroInfo {
colorStar: number; // 彩星
@prop({ required: true })
lv: number; // 等级
@prop({ required: true, type: HeroArtifact, _id: false })
artifact: HeroArtifact[] = []; // 等级
setByWarJson(warJson: DicWarJson) {
this.hid = warJson.actorId;
@@ -96,6 +108,10 @@ export class LadderOppPlayerHeroInfo {
this.colorStar = hero.colorStar;
this.lv = hero.lv;
}
setArtifact(artifact: ArtifactModelType) {
if(artifact) this.artifact.push({ artifactId: artifact.artifactId, lv: artifact.lv });
}
}
// ladderMatchRec
@@ -343,8 +359,9 @@ export class LadderOppDetailHeroReturn {
spine: string = ''; // 动画
talent: Talent[] = [];
subHid: number = 0; // 副将
artifact: HeroArtifact[] = [];
constructor(warJson: DicWarJson, defensHero: LadderDefenseHero) {
constructor(warJson: DicWarJson, defensHero: LadderDefenseHero, artifacts: ArtifactModelType[]) {
this.dataId = warJson.dataId;
this.relation = warJson.relation;
this.dirction = warJson.dirction;
@@ -373,6 +390,8 @@ export class LadderOppDetailHeroReturn {
if(skin) this.talent = skin.talent;
this.job = hero.job;
this.subHid = hero.subHid;
let artifact = artifacts.find(cur => cur.seqId == hero.artifact);
if(artifact) this.artifact.push({ artifactId: artifact.artifactId, lv: artifact.lv });
}
}
}
@@ -405,7 +424,7 @@ export class LadderOppDetailReturn {
}
}
setByPlayer(ladderMatch: LadderMatchType, warJsons: DicWarJson[]) {
setByPlayer(ladderMatch: LadderMatchType, warJsons: DicWarJson[], artifacts: ArtifactModelType[]) {
this.isRobot = false;
let role = <RoleType>ladderMatch.role;
this.title = role.title;
@@ -415,7 +434,7 @@ export class LadderOppDetailReturn {
for(let hero of heroes) {
let warJson = warJsons.find(cur => cur.dataId == hero.dataId);
if(warJson) {
let obj = new LadderOppDetailHeroReturn(warJson, hero);
let obj = new LadderOppDetailHeroReturn(warJson, hero, artifacts);
this.heroes.push(obj);
this.defCe += hero.ce;
}

View File

@@ -3,6 +3,7 @@ import { DicWarJson } from '../pubUtils/dictionary/DicWarJson';
import Hero, { HeroType } from '../db/Hero';
import { nowSeconds } from '../pubUtils/timeUtil';
import { DicHero } from '../pubUtils/dictionary/DicHero';
import { ArtifactModelType } from '../db/Artifact';
class Talent {
@@ -11,6 +12,16 @@ class Talent {
@prop({ required: true })
level: number; // 激活等级
}
class HeroArtifact {
@prop({ required: true })
artifactId: number;
@prop({ required: true })
lv: number;
}
// 从玩家数据中覆盖warjson的部分字段
export class PvpHeroInfo {
@prop({ required: true })
@@ -44,8 +55,10 @@ export class PvpHeroInfo {
@prop({ required: true, _id: false })
attribute?: string; // 属性
@prop({ required: true, _id: false, type: HeroArtifact })
artifact?: HeroArtifact[] = []; // 宝物
setHeroInfo(hero: HeroType) {
setHeroInfo(hero: HeroType, artifact: ArtifactModelType) {
this.actorId = hero.hid;
this.skinId = hero.skinId;
this.actorName = hero.hName;
@@ -57,6 +70,7 @@ export class PvpHeroInfo {
let skin = hero.skins?.find(cur => cur.enable);
if(skin) this.talent = skin.talent;
this.subHid = hero.subHid;
if(artifact) this.artifact.push({ artifactId: artifact.artifactId, lv: artifact.lv })
}
setRobotInfo(dicHero: DicHero, lv: number) {
@@ -150,6 +164,9 @@ export class PvpEnemies extends Enemies {
talent: Talent[];
@prop({ required: true })
subHid: number;
@prop({ required: true, type: () => HeroArtifact, _id: false })
artifact: HeroArtifact[] = []; // 宝物
// score: 这个武将的军功
constructor(warjson: DicWarJson, heroInfo: PvpHeroInfo, score: number, ce: number) {
@@ -162,6 +179,7 @@ export class PvpEnemies extends Enemies {
this.talent = heroInfo.talent;
this.job = heroInfo.job;
this.subHid = heroInfo.subHid;
this.artifact = heroInfo.artifact||[];
}
}

View File

@@ -4,6 +4,7 @@ import * as friendUtil from '../../pubUtils/friendUtil'
import { FRIEND_RELATION_TYPE } from "../../consts";
import { Connect, EPlace, HeroType, Stone, Talent } from "../../db/Hero";
import { JewelType, RandSe } from "../../db/Jewel";
import { ArtifactModelType } from "../../db/Artifact";
export class FriendParams {
roleId: string;
@@ -201,6 +202,7 @@ export class HeroDetailParam {
school: number;
};
subHid: number = 0;
artifacts: {artifactId: number, lv: number }[] = []
constructor(hero: HeroType) {
this.roleId = hero.roleId;
@@ -239,4 +241,8 @@ export class HeroDetailParam {
setRole(title: number, scroll: number, teraph: number, school: number) {
this.role = { title, scroll, teraph, school };
}
setArtifact(artifact: ArtifactModelType) {
this.artifacts.push({ artifactId: artifact.artifactId, lv: artifact.lv });
}
}

View File

@@ -1,4 +1,5 @@
import { ArtifactModelType } from '../../db/Artifact';
import { Connect, EPlace, HeroSkin, HeroType, HeroUpdate, Talent } from '../../db/Hero';
import { JewelSe, JewelType, RandSe } from '../../db/Jewel';
import { gameData } from '../../pubUtils/data';
@@ -60,6 +61,7 @@ export class HeroParam {
skins: HeroSKinParam[] = []; // 皮肤
ePlace: EPlace[]; // 武将装备引用数组
artifact: number = 0;
talent: Talent[] = [];
usedTalentPoint: number = 0;
totalTalentPoint: number = 0;
@@ -93,6 +95,7 @@ export class HeroParam {
}
}
this.ePlace = hero.ePlace;
this.artifact = hero.artifact;
}
}
@@ -124,3 +127,27 @@ export class JewelParam {
}
}
}
export class ArtifactParam {
seqId: number; // 唯一id
artifactId: number; // 宝物id
id: number; // 物品id
lv: number; // 强化等级
hid: number; // 装备的武将
count: number;
inc: number; // 增减数量固定1
reason: number; // 来源id
constructor(artifact: ArtifactModelType, isPush?: boolean, reason?: number) {
this.seqId = artifact.seqId;
this.artifactId = artifact.artifactId;
this.id = artifact.id;
this.lv = artifact.lv;
this.hid = artifact.hid;
if(isPush) {
this.count = 1;
this.inc = 1;
this.reason = reason;
}
}
}

View File

@@ -1,3 +1,4 @@
import { ArtifactModelType } from "../../db/Artifact";
import { Connect, EPlace, HeroType } from "../../db/Hero";
import { JewelType } from "../../db/Jewel";
import { HeroScore } from "../battleField/pvp";
@@ -56,6 +57,8 @@ export class TaskParamInter {
jewels?: JewelType[]; // 天晶石
skinId?: number; // 皮肤id
artifacts?: ArtifactModelType[]; // 宝物
skipTower?: boolean;
debugInfo?: {condition: number};
};

View File

@@ -110,6 +110,13 @@ import { dicLadderMatch, loadLadderMatch } from "./dictionary/DicLadderMatch";
import { dicLadderDifficultRatio, loadLadderDifficultRatio } from "./dictionary/DicLadderDifficultRatio";
import { dicLadderRankReward, loadLadderRankReward } from "./dictionary/DicLadderRankReward";
import { dicGeneralGoods, loadGeneralGoods } from "./dictionary/DicGeneralGoods";
import { dicArtifact, dicArtifactByGid, dicArtifactByGidAndType, dicArtifactsByGroup, loadArtifact } from "./dictionary/DicArtifact";
import { DicArtifactLvPlan, dicArtifactLvPlan, loadArtifactLvPlan } from "./dictionary/DicArtifactLvPlan";
import { dicArtifactQuality, dicArtifactQualityById, loadArtifactQuality } from "./dictionary/DicArtifactQuality";
import { dicArtifactQualityPlan, loadArtifactQualityPlan } from "./dictionary/DicArtifactQualityPlan";
import { dicArtifactSeid, loadArtifactSeid } from "./dictionary/DicArtifactSeid";
import { DicArtifact } from "./dictionary/DicArtifact";
import { DicArtifactQuality } from "./dictionary/DicArtifactQuality";
export const gameData = {
daily: dicDaily,
@@ -277,6 +284,15 @@ export const gameData = {
comBattleRewardTime: new Array<{from: string, to: string}>(),
comBattleReward: dicComBattleReward,
relationGoods: dicGeneralGoods,
artifact: dicArtifact,
artifactByGid: dicArtifactByGid,
artifactByGidAndType: dicArtifactByGidAndType,
artifactLvPlan: dicArtifactLvPlan,
artifactQuality: dicArtifactQuality,
artifactQualityById: dicArtifactQualityById,
artifactQualityPlan: dicArtifactQualityPlan,
artifactSeid: dicArtifactSeid,
artifactByGroupAndQuality: dicArtifactsByGroup,
};
// 在此提供一些原先在gamedata中提供的方法以便更方便获取gameData数据
@@ -991,6 +1007,64 @@ export function getShopType(shop: number, type: number) {
return gameData.shopType.get(key)||null;
}
export function getDefArtifactByGid(gid: number): DicArtifact {
let artifactId = gameData.artifactByGid.get(gid);
return gameData.artifact.get(artifactId);
}
export function getDicArtifactQualityByStage(quality: number, qualityStage: number): DicArtifactQuality {
let uniqId = gameData.artifactQuality.get(`${quality}_${qualityStage}`);
return gameData.artifactQualityById.get(uniqId);
}
export function getNextArtifactQuality(quality: number, qualityStage: number): DicArtifactQuality {
let dicArtifactQuality = getDicArtifactQualityByStage(quality, qualityStage);
if(!dicArtifactQuality) return null;
return gameData.artifactQualityById.get(dicArtifactQuality.nextId);
}
export function getNextArtifact(artifactId: number): (DicArtifact&DicArtifactQuality) {
let dicArtifact = gameData.artifact.get(artifactId);
if(!dicArtifact) return null;
let dicNextArtifactQuality = getNextArtifactQuality(dicArtifact.quality, dicArtifact.qualityStage);
if(!dicNextArtifactQuality) return null;
let dicNextArtifact = getArtifactByGroupAndQuality(dicArtifact.group, dicArtifact.type, dicNextArtifactQuality.quality, dicNextArtifactQuality.qualityStage);
if(!dicNextArtifact) return null;
return {...dicNextArtifact, ...dicNextArtifactQuality}
}
export function getArtifactStageZero(artifactId: number): (DicArtifact&DicArtifactQuality) {
let dicArtifact = getArtifactWithQuality(artifactId);
if(!dicArtifact) return null;
let dicZeroArtifact = gameData.artifactByGroupAndQuality.get(`${dicArtifact.group}_${dicArtifact.type}_${dicArtifact.quality}_${0}`);
if(!dicZeroArtifact) return null;
let dicZeroArtifactQuality = getDicArtifactQualityByStage(dicArtifact.quality, dicArtifact.qualityStage);
if(!dicZeroArtifactQuality) return null;
return {...dicZeroArtifact, ...dicZeroArtifactQuality}
}
export function getArtifactByGroupAndQuality(group: string, type: number, quality: number, qualityStage: number): DicArtifact {
return gameData.artifactByGroupAndQuality.get(`${group}_${type}_${quality}_${qualityStage}`);
}
export function getDicArtifactLvByPlanId(planId: number, lv: number): DicArtifactLvPlan {
let map = gameData.artifactLvPlan.get(planId);
return map?.get(lv);
}
export function getArtifactByGidAndType(goodId: number, type: number): DicArtifact {
let artifactId = gameData.artifactByGidAndType.get(`${goodId}_${type}`);
return gameData.artifact.get(artifactId);
}
export function getArtifactWithQuality(artifactId: number): (DicArtifact&DicArtifactQuality) {
let dicArtifact = gameData.artifact.get(artifactId);
if(!dicArtifact) return null;
let dicArtifactQuality = getDicArtifactQualityByStage(dicArtifact.quality, dicArtifact.qualityStage);
if(!dicArtifactQuality) return null;
return {...dicArtifact, ...dicArtifactQuality}
}
// 初始加载
function initDatas() {
parseDicParam();
@@ -1180,6 +1254,11 @@ function loadDatas() {
loadLadderDifficultRatio();
loadLadderRankReward();
loadGeneralGoods();
loadArtifact();
loadArtifactLvPlan();
loadArtifactQuality();
loadArtifactQualityPlan();
loadArtifactSeid();
}
// 重载dicParam

View File

@@ -178,6 +178,8 @@ export const BAG = {
BAG_EQUIP_UPLIMITED: 500, // 背包中装备数量上限
BAG_GOODS_UPLIMITED: 4294967295, // 背包中可叠加的道具数量上限
BAG_RESOLVE_UPLIMITED: 500, // 背包中一键分解的上限
BAG_ARTIFACT_UPLIMITED: 500, // 背包中宝物数量上限
BAG_ARTIFACT_DECOMPOSE_UPLIMITED: 500, // 背包中宝物一键分解的上限
};
export const ATTRIBUTE = {
ATTRIBUTE_EQUIP_RATIO: '1&1|2&3|4&2|5&2', // 装备的基础属性系数
@@ -358,3 +360,10 @@ export const MINIGAME = {
MINIGAME_ARCHER_RANGE: '0&100|29&80|69&60|104&40|143&20|177&0', // 射箭小游戏圈数积分
MINIGAME_FLIPCARD_TYPE: 'baihe|guyuan|hongdou|huasheng|lianzi|nuomi|yimi|zao', // 翻牌游戏资源
};
export const JEWEL = {
JEWELQUALITY: '0&1|25&2|50&3|75&4|100&5', // 天晶词条颜色修改
};
export const ARTIFACT = {
TRANSFER_COST: '31002&100', // 宝物转换形态消耗
REBUILD_COST: '31002&100', // 宝物重铸消耗
};

View File

@@ -0,0 +1,73 @@
// 物品表
import { readFileAndParse, parseNumberList, } from '../util'
import { FILENAME, } from '../../consts'
const _ = require('lodash');
export interface DicArtifact {
// 宝物idt其中形态1和goodId必须一致
readonly artifactId: number;
// 宝物名
readonly name: string;
// 物品表id不同品质&品阶的同名宝物的物品id不同
readonly goodId: number;
// 同名宝物比如史记可以直接写shiji不过要当心多音词注意唯一性
readonly group: string;
// 形态
readonly type: number;
// 是否是初始形态,用于服务器获取
readonly isDefaultType: boolean;
// 品质每个宝物id直接对应一种品质
readonly quality: number;
// 品阶每个宝物id直接对应一种品阶
readonly qualityStage: number;
// 专属职业
readonly jobClass: number;
// 专属武将
readonly hid: number;
// 词条seid&seid
readonly seids: number[];
// 等级配置方案
readonly lvAttrPlan: number;
// 升品配置方案
readonly qualityAttrPlan: number;
}
type KeysEnum<T> = { [P in keyof Required<T>]: true };
const DicArtifactKeys: KeysEnum<DicArtifact> = {
artifactId: true,
name: true,
goodId: true,
group: true,
type: true,
isDefaultType: true,
quality: true,
qualityStage: true,
jobClass: true,
hid: true,
seids: true,
lvAttrPlan: true,
qualityAttrPlan: true,
}
export const dicArtifact = new Map<number, DicArtifact>();
export const dicArtifactByGid = new Map<number, number>();
export const dicArtifactByGidAndType = new Map<string, number>();
export const dicArtifactsByGroup = new Map<string, DicArtifact>();
export function loadArtifact() {
dicArtifact.clear();
dicArtifactByGid.clear();
dicArtifactByGidAndType.clear();
dicArtifactsByGroup.clear();
let arr = readFileAndParse(FILENAME.DIC_ARTIFACT);
arr.forEach(o => {
o.seids = parseNumberList(o.seids);
if(o.isDefaultType) dicArtifactByGid.set(o.goodId, o.artifactId);
dicArtifactByGidAndType.set(`${o.goodId}_${o.type}`, o.artifactId);
dicArtifact.set(o.artifactId, _.pick(o, Object.keys(DicArtifactKeys)));
dicArtifactsByGroup.set(`${o.group}_${o.type}_${o.quality}_${o.qualityStage}`, o);
});
arr = undefined;
}

View File

@@ -0,0 +1,54 @@
// 物品表
import { readFileAndParse, parseGoodStr, decodeArrayListStr, } from '../util'
import { FILENAME, } from '../../consts'
import { RewardInter } from '../interface';
const _ = require('lodash');
export interface DicArtifactLvPlan {
// 方案id
planId: number;
// 等级
lv: number;
// 升到这级需要消耗什么id&count
consumes: RewardInter[];
// 这级的属性
attr: {id: number, attr: number}[];
}
type KeysEnum<T> = { [P in keyof Required<T>]: true };
const DicArtifactLvPlanKeys: KeysEnum<DicArtifactLvPlan> = {
planId: true,
lv: true,
consumes: true,
attr: true,
}
export const dicArtifactLvPlan = new Map<number, Map<number, DicArtifactLvPlan>>(); // planId => lv => dic
export function loadArtifactLvPlan() {
dicArtifactLvPlan.clear();
let arr = readFileAndParse(FILENAME.DIC_ARTIFACT_LV_PLAN);
arr.forEach(o => {
o.consumes = parseGoodStr(o.consumes);
o.attr = parseAttr(o.attr);
if(!dicArtifactLvPlan.has(o.planId)) {
dicArtifactLvPlan.set(o.planId, new Map());
}
dicArtifactLvPlan.get(o.planId)?.set(o.lv, _.pick(o, Object.keys(DicArtifactLvPlanKeys)));
});
arr = undefined;
}
function parseAttr(str: string) {
let result = new Array<{id: number, attr: number}>();
if(!str) return result;
let decodeArr = decodeArrayListStr(str);
for(let [id, attr] of decodeArr) {
if(isNaN(parseInt(id)) || isNaN(parseInt(attr))) {
throw new Error('data table format wrong');
}
result.push({id: parseInt(id), attr: parseInt(attr)});
}
return result
}

View File

@@ -0,0 +1,66 @@
// 物品表
import { readFileAndParse, parseGoodStr, } from '../util'
import { FILENAME, } from '../../consts'
import { RewardInter } from '../interface';
const _ = require('lodash');
export interface DicArtifactQuality {
// 唯一id品质+品阶=唯一
uniqId: number;
// 品质key1
quality: number;
// 品阶key2
qualityStage: number;
// 这个品质下最大的等级
maxLv: number;
// 合成相关
// 可以合成到他这个品质的uniqId即原料的品质+品阶
previousId: number;
// 下一阶uniqId
nextId: number;
// 作为狗粮的宝物品质uniqId
materialId: number;
// 作为狗粮的宝物的数量
materialCnt: number;
// 作为狗粮的是否需要同名 1-是 0-不是
materialGroup: number;
// 是否可以分解 1-是 0-不是
canDecompose: number;
// 是否可以一键合成 1-是 0-不是
canComposeAll: number;
// 这个品质可以替换的通用道具id&count。分解同样用这个字段不可分解填&
generalItem: RewardInter[];
}
type KeysEnum<T> = { [P in keyof Required<T>]: true };
const DicArtifactQualityKeys: KeysEnum<DicArtifactQuality> = {
uniqId: true,
quality: true,
qualityStage: true,
maxLv: true,
previousId: true,
nextId: true,
materialId: true,
materialCnt: true,
materialGroup: true,
canDecompose: true,
canComposeAll: true,
generalItem: true,
}
export const dicArtifactQuality = new Map<string, number>(); // quality+qualityStage
export const dicArtifactQualityById = new Map<number, DicArtifactQuality>(); // uniqId
export function loadArtifactQuality() {
dicArtifactQuality.clear();
dicArtifactQualityById.clear();
let arr = readFileAndParse(FILENAME.DIC_ARTIFACT_QUALITY);
arr.forEach(o => {
o.generalItem = parseGoodStr(o.generalItem);
dicArtifactQualityById.set(o.uniqId, _.pick(o, Object.keys(DicArtifactQualityKeys)));
dicArtifactQuality.set(`${o.quality}_${o.qualityStage}`, o.uniqId);
});
arr = undefined;
}

View File

@@ -0,0 +1,44 @@
// 物品表
import { readFileAndParse, decodeArrayListStr, } from '../util'
import { FILENAME, } from '../../consts'
const _ = require('lodash');
export interface DicArtifactQualityPlan {
// 方案id
planId: number;
// 这级的属性
attr: {id: number, attr: number}[];
}
type KeysEnum<T> = { [P in keyof Required<T>]: true };
const DicArtifactQualityPlanKeys: KeysEnum<DicArtifactQualityPlan> = {
planId: true,
attr: true,
}
export const dicArtifactQualityPlan = new Map<number, DicArtifactQualityPlan>();
export function loadArtifactQualityPlan() {
dicArtifactQualityPlan.clear();
let arr = readFileAndParse(FILENAME.DIC_ARTIFACT_QUALITY_PLAN);
arr.forEach(o => {
o.attr = parseAttr(o.attr);
dicArtifactQualityPlan.set(o.planId, _.pick(o, Object.keys(DicArtifactQualityPlanKeys)));
});
arr = undefined;
}
function parseAttr(str: string) {
let result = new Array<{id: number, attr: number}>();
if(!str) return result;
let decodeArr = decodeArrayListStr(str);
for(let [id, attr] of decodeArr) {
if(isNaN(parseInt(id)) || isNaN(parseInt(attr))) {
throw new Error('data table format wrong');
}
result.push({id: parseInt(id), attr: parseInt(attr)});
}
return result
}

View File

@@ -0,0 +1,36 @@
// 物品表
import { readFileAndParse, } from '../util'
import { FILENAME, } from '../../consts'
const _ = require('lodash');
export interface DicArtifactQuality {
// 对应的se表的id
seid: number;
// 解锁的品质
quality: number;
// 生效的职业0表示全生效
jobClass: number;
// 生效的武将
hid: number;
}
type KeysEnum<T> = { [P in keyof Required<T>]: true };
const DicArtifactSeidKeys: KeysEnum<DicArtifactQuality> = {
seid: true,
quality: true,
jobClass: true,
hid: true,
}
export const dicArtifactSeid = new Map<number, DicArtifactQuality>(); // seid => dic
export function loadArtifactSeid() {
dicArtifactSeid.clear();
let arr = readFileAndParse(FILENAME.DIC_ARTIFACT_SEID);
arr.forEach(o => {
dicArtifactSeid.set(o.seid, _.pick(o, Object.keys(DicArtifactSeidKeys)));
});
arr = undefined;
}

View File

@@ -745,6 +745,15 @@ export function addToMap<T>(map: Map<T, number>, id: T, value: number) {
}
}
export function arrToMap<T>(arr: T[], getKey: (obj: T) => number): Map<number, T> {
let map = new Map();
for(let obj of arr) {
let key = getKey(obj);
map.set(key, obj);
}
return map;
}
// /**
// * 计算最强阵容战力
// * @param role

View File

@@ -236,5 +236,12 @@
"sendName": "您忠诚的小跟班",
"content": "亲爱的主公,在诸位百家传人的火热购买下,糜氏集市折上加折!您购买的%d最终达成%d折现退还您%d元宝请查收",
"time": 720
},
{
"id": 34,
"title": "&",
"sendName": "您忠诚的小跟班",
"content": "亲爱的主公,您的背包中宝物数量已满,请及时清理背包哦。溢出装备已通过邮件发放,请查收",
"time": 2160
}
]

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,152 @@
[
{
"uniqId": 1,
"name": "蓝",
"quality": 1,
"qualityStage": 0,
"maxLv": 20,
"previousId": 0,
"materialId": 0,
"materialCnt": 0,
"materialGroup": 0,
"canDecompose": 0,
"canComposeAll": 1,
"generalItem": "&",
"nextId": 2
},
{
"uniqId": 2,
"name": "紫",
"quality": 2,
"qualityStage": 0,
"maxLv": 40,
"previousId": 1,
"materialId": 1,
"materialCnt": 2,
"materialGroup": 1,
"canDecompose": 0,
"canComposeAll": 1,
"generalItem": "&",
"nextId": 3
},
{
"uniqId": 3,
"name": "橙",
"quality": 3,
"qualityStage": 0,
"maxLv": 60,
"previousId": 2,
"materialId": 2,
"materialCnt": 2,
"materialGroup": 1,
"canDecompose": 1,
"canComposeAll": 0,
"generalItem": "82002&1",
"nextId": 4
},
{
"uniqId": 4,
"name": "橙+1",
"quality": 3,
"qualityStage": 1,
"maxLv": 60,
"previousId": 3,
"materialId": 3,
"materialCnt": 1,
"materialGroup": 0,
"canDecompose": 1,
"canComposeAll": 0,
"generalItem": "82002&2",
"nextId": 5
},
{
"uniqId": 5,
"name": "橙+2",
"quality": 3,
"qualityStage": 2,
"maxLv": 60,
"previousId": 4,
"materialId": 3,
"materialCnt": 2,
"materialGroup": 0,
"canDecompose": 1,
"canComposeAll": 0,
"generalItem": "82002&3",
"nextId": 6
},
{
"uniqId": 6,
"name": "红",
"quality": 4,
"qualityStage": 0,
"maxLv": 80,
"previousId": 5,
"materialId": 5,
"materialCnt": 2,
"materialGroup": 1,
"canDecompose": 1,
"canComposeAll": 0,
"generalItem": "82003&1",
"nextId": 7
},
{
"uniqId": 7,
"name": "红+1",
"quality": 4,
"qualityStage": 1,
"maxLv": 80,
"previousId": 6,
"materialId": 6,
"materialCnt": 1,
"materialGroup": 0,
"canDecompose": 1,
"canComposeAll": 0,
"generalItem": "82003&2",
"nextId": 8
},
{
"uniqId": 8,
"name": "红+2",
"quality": 4,
"qualityStage": 2,
"maxLv": 80,
"previousId": 7,
"materialId": 6,
"materialCnt": 2,
"materialGroup": 0,
"canDecompose": 1,
"canComposeAll": 0,
"generalItem": "82003&3",
"nextId": 9
},
{
"uniqId": 9,
"name": "红+3",
"quality": 4,
"qualityStage": 3,
"maxLv": 80,
"previousId": 8,
"materialId": 6,
"materialCnt": 2,
"materialGroup": 0,
"canDecompose": 1,
"canComposeAll": 0,
"generalItem": "82003&4",
"nextId": 10
},
{
"uniqId": 10,
"name": "金",
"quality": 5,
"qualityStage": 0,
"maxLv": 100,
"previousId": 9,
"materialId": 9,
"materialCnt": 2,
"materialGroup": 1,
"canDecompose": 1,
"canComposeAll": 0,
"generalItem": "&",
"nextId": 0
}
]

View File

@@ -0,0 +1,632 @@
[
{
"id": 1,
"planId": 101,
"attr": "1&452|2&120|4&86|5&68"
},
{
"id": 2,
"planId": 102,
"attr": "1&1130|2&300|4&215|5&170"
},
{
"id": 3,
"planId": 103,
"attr": "1&2260|2&600|4&430|5&340"
},
{
"id": 4,
"planId": 104,
"attr": "1&3616|2&960|4&688|5&544"
},
{
"id": 5,
"planId": 105,
"attr": "1&4972|2&1320|4&946|5&748"
},
{
"id": 6,
"planId": 106,
"attr": "1&6780|2&1800|4&1290|5&1020"
},
{
"id": 7,
"planId": 107,
"attr": "1&9040|2&2400|4&1720|5&1360"
},
{
"id": 8,
"planId": 108,
"attr": "1&12204|2&3240|4&2322|5&1836"
},
{
"id": 9,
"planId": 109,
"attr": "1&15820|2&4200|4&3010|5&2380"
},
{
"id": 10,
"planId": 110,
"attr": "1&20340|2&5400|4&3870|5&3060"
},
{
"id": 11,
"planId": 201,
"attr": "1&432|2&126|4&80|5&74"
},
{
"id": 12,
"planId": 202,
"attr": "1&1080|2&315|4&200|5&185"
},
{
"id": 13,
"planId": 203,
"attr": "1&2160|2&630|4&400|5&370"
},
{
"id": 14,
"planId": 204,
"attr": "1&3456|2&1008|4&640|5&592"
},
{
"id": 15,
"planId": 205,
"attr": "1&4752|2&1386|4&880|5&814"
},
{
"id": 16,
"planId": 206,
"attr": "1&6480|2&1890|4&1200|5&1110"
},
{
"id": 17,
"planId": 207,
"attr": "1&8640|2&2520|4&1600|5&1480"
},
{
"id": 18,
"planId": 208,
"attr": "1&11664|2&3402|4&2160|5&1998"
},
{
"id": 19,
"planId": 209,
"attr": "1&15120|2&4410|4&2800|5&2590"
},
{
"id": 20,
"planId": 210,
"attr": "1&19440|2&5670|4&3600|5&3330"
},
{
"id": 21,
"planId": 301,
"attr": "1&420|2&134|4&78|5&72"
},
{
"id": 22,
"planId": 302,
"attr": "1&1050|2&335|4&195|5&180"
},
{
"id": 23,
"planId": 303,
"attr": "1&2100|2&670|4&390|5&360"
},
{
"id": 24,
"planId": 304,
"attr": "1&3360|2&1072|4&624|5&576"
},
{
"id": 25,
"planId": 305,
"attr": "1&4620|2&1474|4&858|5&792"
},
{
"id": 26,
"planId": 306,
"attr": "1&6300|2&2010|4&1170|5&1080"
},
{
"id": 27,
"planId": 307,
"attr": "1&8400|2&2680|4&1560|5&1440"
},
{
"id": 28,
"planId": 308,
"attr": "1&11340|2&3618|4&2106|5&1944"
},
{
"id": 29,
"planId": 309,
"attr": "1&14700|2&4690|4&2730|5&2520"
},
{
"id": 30,
"planId": 310,
"attr": "1&18900|2&6030|4&3510|5&3240"
},
{
"id": 31,
"planId": 401,
"attr": "1&414|2&136|4&74|5&76"
},
{
"id": 32,
"planId": 402,
"attr": "1&1035|2&340|4&185|5&190"
},
{
"id": 33,
"planId": 403,
"attr": "1&2070|2&680|4&370|5&380"
},
{
"id": 34,
"planId": 404,
"attr": "1&3312|2&1088|4&592|5&608"
},
{
"id": 35,
"planId": 405,
"attr": "1&4554|2&1496|4&814|5&836"
},
{
"id": 36,
"planId": 406,
"attr": "1&6210|2&2040|4&1110|5&1140"
},
{
"id": 37,
"planId": 407,
"attr": "1&8280|2&2720|4&1480|5&1520"
},
{
"id": 38,
"planId": 408,
"attr": "1&11178|2&3672|4&1998|5&2052"
},
{
"id": 39,
"planId": 409,
"attr": "1&14490|2&4760|4&2590|5&2660"
},
{
"id": 40,
"planId": 410,
"attr": "1&18630|2&6120|4&3330|5&3420"
},
{
"id": 41,
"planId": 501,
"attr": "1&406|2&128|4&76|5&84"
},
{
"id": 42,
"planId": 502,
"attr": "1&1015|2&320|4&190|5&210"
},
{
"id": 43,
"planId": 503,
"attr": "1&2030|2&640|4&380|5&420"
},
{
"id": 44,
"planId": 504,
"attr": "1&3248|2&1024|4&608|5&672"
},
{
"id": 45,
"planId": 505,
"attr": "1&4466|2&1408|4&836|5&924"
},
{
"id": 46,
"planId": 506,
"attr": "1&6090|2&1920|4&1140|5&1260"
},
{
"id": 47,
"planId": 507,
"attr": "1&8120|2&2560|4&1520|5&1680"
},
{
"id": 48,
"planId": 508,
"attr": "1&10962|2&3456|4&2052|5&2268"
},
{
"id": 49,
"planId": 509,
"attr": "1&14210|2&4480|4&2660|5&2940"
},
{
"id": 50,
"planId": 510,
"attr": "1&18270|2&5760|4&3420|5&3780"
},
{
"id": 51,
"planId": 601,
"attr": "1&374|2&138|4&70|5&90"
},
{
"id": 52,
"planId": 602,
"attr": "1&935|2&345|4&175|5&225"
},
{
"id": 53,
"planId": 603,
"attr": "1&1870|2&690|4&350|5&450"
},
{
"id": 54,
"planId": 604,
"attr": "1&2992|2&1104|4&560|5&720"
},
{
"id": 55,
"planId": 605,
"attr": "1&4114|2&1518|4&770|5&990"
},
{
"id": 56,
"planId": 606,
"attr": "1&5610|2&2070|4&1050|5&1350"
},
{
"id": 57,
"planId": 607,
"attr": "1&7480|2&2760|4&1400|5&1800"
},
{
"id": 58,
"planId": 608,
"attr": "1&10098|2&3726|4&1890|5&2430"
},
{
"id": 59,
"planId": 609,
"attr": "1&13090|2&4830|4&2450|5&3150"
},
{
"id": 60,
"planId": 610,
"attr": "1&16830|2&6210|4&3150|5&4050"
},
{
"id": 61,
"planId": 701,
"attr": "1&386|2&130|4&72|5&92"
},
{
"id": 62,
"planId": 702,
"attr": "1&965|2&325|4&180|5&230"
},
{
"id": 63,
"planId": 703,
"attr": "1&1930|2&650|4&360|5&460"
},
{
"id": 64,
"planId": 704,
"attr": "1&3088|2&1040|4&576|5&736"
},
{
"id": 65,
"planId": 705,
"attr": "1&4246|2&1430|4&792|5&1012"
},
{
"id": 66,
"planId": 706,
"attr": "1&5790|2&1950|4&1080|5&1380"
},
{
"id": 67,
"planId": 707,
"attr": "1&7720|2&2600|4&1440|5&1840"
},
{
"id": 68,
"planId": 708,
"attr": "1&10422|2&3510|4&1944|5&2484"
},
{
"id": 69,
"planId": 709,
"attr": "1&13510|2&4550|4&2520|5&3220"
},
{
"id": 70,
"planId": 710,
"attr": "1&17370|2&5850|4&3240|5&4140"
},
{
"id": 71,
"planId": 1101,
"attr": "1&4520|2&1200|4&860|5&680"
},
{
"id": 72,
"planId": 1102,
"attr": "1&6780|2&1800|4&1290|5&1020"
},
{
"id": 73,
"planId": 1103,
"attr": "1&10170|2&2700|4&1935|5&1530"
},
{
"id": 74,
"planId": 1104,
"attr": "1&14690|2&3900|4&2795|5&2210"
},
{
"id": 75,
"planId": 1105,
"attr": "1&20340|2&5400|4&3870|5&3060"
},
{
"id": 76,
"planId": 1106,
"attr": "1&27120|2&7200|4&5160|5&4080"
},
{
"id": 77,
"planId": 1107,
"attr": "1&35030|2&9300|4&6665|5&5270"
},
{
"id": 78,
"planId": 1108,
"attr": "1&45200|2&12000|4&8600|5&6800"
},
{
"id": 79,
"planId": 1201,
"attr": "1&4320|2&1260|4&800|5&740"
},
{
"id": 80,
"planId": 1202,
"attr": "1&6480|2&1890|4&1200|5&1110"
},
{
"id": 81,
"planId": 1203,
"attr": "1&9720|2&2835|4&1800|5&1665"
},
{
"id": 82,
"planId": 1204,
"attr": "1&14040|2&4095|4&2600|5&2405"
},
{
"id": 83,
"planId": 1205,
"attr": "1&19440|2&5670|4&3600|5&3330"
},
{
"id": 84,
"planId": 1206,
"attr": "1&25920|2&7560|4&4800|5&4440"
},
{
"id": 85,
"planId": 1207,
"attr": "1&33480|2&9765|4&6200|5&5735"
},
{
"id": 86,
"planId": 1208,
"attr": "1&43200|2&12600|4&8000|5&7400"
},
{
"id": 87,
"planId": 1301,
"attr": "1&4200|2&1340|4&780|5&720"
},
{
"id": 88,
"planId": 1302,
"attr": "1&6300|2&2010|4&1170|5&1080"
},
{
"id": 89,
"planId": 1303,
"attr": "1&9450|2&3015|4&1755|5&1620"
},
{
"id": 90,
"planId": 1304,
"attr": "1&13650|2&4355|4&2535|5&2340"
},
{
"id": 91,
"planId": 1305,
"attr": "1&18900|2&6030|4&3510|5&3240"
},
{
"id": 92,
"planId": 1306,
"attr": "1&25200|2&8040|4&4680|5&4320"
},
{
"id": 93,
"planId": 1307,
"attr": "1&32550|2&10385|4&6045|5&5580"
},
{
"id": 94,
"planId": 1308,
"attr": "1&42000|2&13400|4&7800|5&7200"
},
{
"id": 95,
"planId": 1401,
"attr": "1&4140|2&1360|4&740|5&760"
},
{
"id": 96,
"planId": 1402,
"attr": "1&6210|2&2040|4&1110|5&1140"
},
{
"id": 97,
"planId": 1403,
"attr": "1&9315|2&3060|4&1665|5&1710"
},
{
"id": 98,
"planId": 1404,
"attr": "1&13455|2&4420|4&2405|5&2470"
},
{
"id": 99,
"planId": 1405,
"attr": "1&18630|2&6120|4&3330|5&3420"
},
{
"id": 100,
"planId": 1406,
"attr": "1&24840|2&8160|4&4440|5&4560"
},
{
"id": 101,
"planId": 1407,
"attr": "1&32085|2&10540|4&5735|5&5890"
},
{
"id": 102,
"planId": 1408,
"attr": "1&41400|2&13600|4&7400|5&7600"
},
{
"id": 103,
"planId": 1501,
"attr": "1&4060|2&1280|4&760|5&840"
},
{
"id": 104,
"planId": 1502,
"attr": "1&6090|2&1920|4&1140|5&1260"
},
{
"id": 105,
"planId": 1503,
"attr": "1&9135|2&2880|4&1710|5&1890"
},
{
"id": 106,
"planId": 1504,
"attr": "1&13195|2&4160|4&2470|5&2730"
},
{
"id": 107,
"planId": 1505,
"attr": "1&18270|2&5760|4&3420|5&3780"
},
{
"id": 108,
"planId": 1506,
"attr": "1&24360|2&7680|4&4560|5&5040"
},
{
"id": 109,
"planId": 1507,
"attr": "1&31465|2&9920|4&5890|5&6510"
},
{
"id": 110,
"planId": 1508,
"attr": "1&40600|2&12800|4&7600|5&8400"
},
{
"id": 111,
"planId": 1601,
"attr": "1&3740|2&1380|4&700|5&900"
},
{
"id": 112,
"planId": 1602,
"attr": "1&5610|2&2070|4&1050|5&1350"
},
{
"id": 113,
"planId": 1603,
"attr": "1&8415|2&3105|4&1575|5&2025"
},
{
"id": 114,
"planId": 1604,
"attr": "1&12155|2&4485|4&2275|5&2925"
},
{
"id": 115,
"planId": 1605,
"attr": "1&16830|2&6210|4&3150|5&4050"
},
{
"id": 116,
"planId": 1606,
"attr": "1&22440|2&8280|4&4200|5&5400"
},
{
"id": 117,
"planId": 1607,
"attr": "1&28985|2&10695|4&5425|5&6975"
},
{
"id": 118,
"planId": 1608,
"attr": "1&37400|2&13800|4&7000|5&9000"
},
{
"id": 119,
"planId": 1701,
"attr": "1&3860|2&1300|4&720|5&920"
},
{
"id": 120,
"planId": 1702,
"attr": "1&5790|2&1950|4&1080|5&1380"
},
{
"id": 121,
"planId": 1703,
"attr": "1&8685|2&2925|4&1620|5&2070"
},
{
"id": 122,
"planId": 1704,
"attr": "1&12545|2&4225|4&2340|5&2990"
},
{
"id": 123,
"planId": 1705,
"attr": "1&17370|2&5850|4&3240|5&4140"
},
{
"id": 124,
"planId": 1706,
"attr": "1&23160|2&7800|4&4320|5&5520"
},
{
"id": 125,
"planId": 1707,
"attr": "1&29915|2&10075|4&5580|5&7130"
},
{
"id": 126,
"planId": 1708,
"attr": "1&38600|2&13000|4&7200|5&9200"
}
]

View File

@@ -0,0 +1,37 @@
[
{
"seid": 6201411,
"artifactName": "龙雀刀",
"quality": 1,
"jobClass": 1,
"hid": 0
},
{
"seid": 1000001051,
"artifactName": "龙雀刀",
"quality": 2,
"jobClass": 1,
"hid": 0
},
{
"seid": 6201511,
"artifactName": "龙雀刀",
"quality": 3,
"jobClass": 1,
"hid": 0
},
{
"seid": 1000002051,
"artifactName": "龙雀刀",
"quality": 4,
"jobClass": 1,
"hid": 0
},
{
"seid": 5601311,
"artifactName": "龙雀刀",
"quality": 5,
"jobClass": 1,
"hid": 0
}
]

View File

@@ -1058,5 +1058,35 @@
"content": 0,
"condition": "level&",
"sumType": 1
},
{
"id": 127,
"name": "宝物",
"info": "强化X件宝物至X级",
"param": "count&lv&",
"string": "数量&等级",
"content": 0,
"condition": "count",
"sumType": 1
},
{
"id": 128,
"name": "宝物",
"info": "穿戴X件品质为X的宝物",
"param": "count&quality&",
"string": "数量&品质",
"content": 0,
"condition": "count",
"sumType": 1
},
{
"id": 129,
"name": "宝物",
"info": "合成X次宝物",
"param": "count&",
"string": "次数&",
"content": 0,
"condition": "count",
"sumType": 2
}
]