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? artifact.lv + 5: artifact.lv + 1; if(toLv > dicArtifact.maxLv) toLv = dicArtifact.maxLv; 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 && remainCnt > 0) { // 可使用材料代替,不是必须同名的那种 let dicMaterialArtifactQuality = gameData.artifactQualityById.get(dicNextArtifact.materialId); 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) }); } }