358 lines
19 KiB
TypeScript
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) });
|
|
}
|
|
} |