Files
ZYZ/game-server/app/servers/role/handler/artifactHandler.ts
2023-05-06 17:07:48 +08:00

358 lines
19 KiB
TypeScript

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 Hero 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, RewardInter } 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, isExtendLv: boolean }, session: BackendSession) {
let roleId: string = session.get('roleId');
let roleName: string = session.get('roleName');
let sid: string = session.get('sid');
let serverId: number = session.get('serverId');
let { seqId, hid, isExtendLv } = msg;
let hero = await Hero.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);
if(chosenArtifact.lv > 0) isExtendLv = false;
let artifacts: ArtifactModelType[] = [];
let artifactOfHero = hero.artifact? await ArtifactModel.findbySeqId(roleId, hero.artifact): null; // 原本自己的天晶石
let targetLv = artifactOfHero?.lv, returnCoin: RewardInter[] = [];
let dicChosenArtifact = getArtifactWithQuality(chosenArtifact.artifactId);
if(!dicChosenArtifact) return resResult(STATUS.DIC_DATA_NOT_FOUND);
if(isExtendLv && targetLv > dicChosenArtifact.maxLv) {
for(let lv = dicChosenArtifact.maxLv + 1; lv <= targetLv; lv++) {
let dicArtifactLv = getDicArtifactLvByPlanId(dicChosenArtifact.lvAttrPlan, lv);
if(!dicArtifactLv) break;
returnCoin.push(...dicArtifactLv.consumes);
}
targetLv = dicChosenArtifact.maxLv;
};
if(artifactOfHero) { // 更新自己的天晶石
artifactOfHero = await ArtifactModel.putOnOrOff(roleId, artifactOfHero.seqId, 0, isExtendLv? 0: undefined);
if(artifactOfHero) artifacts.push(artifactOfHero);
}
if(chosenArtifact.hid != 0) {
let heroOfChosenArtifact = await Hero.findByHidAndRole(chosenArtifact.hid, roleId); // 我想要的宝物的原持有者
if(heroOfChosenArtifact) {
await calculateCeWithHero(HERO_SYSTEM_TYPE.PUT_OFF_ARTIFACT, roleId, serverId, sid, heroOfChosenArtifact.hid, { artifact: 0 }); // 对方卸下
}
}
chosenArtifact = await ArtifactModel.putOnOrOff(roleId, seqId, hid, isExtendLv? targetLv: undefined);
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 });
let goods = returnCoin.length > 0? await addItems(roleId, roleName, sid, combineItems(returnCoin), ITEM_CHANGE_REASON.ARTIFACT_LV_RETURN): undefined;
return resResult(STATUS.SUCCESS, { artifacts: artifacts.map(artifact => new ArtifactParam(artifact)), goods });
}
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 Hero.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 Hero.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|string)[] = [];
for(let [_, { quality, canComposeAll }] of gameData.artifactQualityById) {
if(!canComposeAll) continue;
let artifacts = await ArtifactModel.findByQuality(roleId, quality);
let used: (number|string)[] = [], materials: ItemInter[] = [], target: ArtifactModelUpdate[] = [];
for(let artifact of artifacts) {
if(used.indexOf(artifact.seqId) > -1) continue;
let tmpUsed: (number|string)[] = [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 Hero.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 Hero.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|string)[] = [];
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) });
}
}