diff --git a/game-server/app/servers/role/handler/roleHandler.ts b/game-server/app/servers/role/handler/roleHandler.ts index e9a2f5c75..85fe71b8a 100644 --- a/game-server/app/servers/role/handler/roleHandler.ts +++ b/game-server/app/servers/role/handler/roleHandler.ts @@ -10,7 +10,7 @@ import { getAtrrNameById } from '../../../consts/constModules/abilityConst' import { findIndex } from 'underscore'; import { SclResultInter, SclPosInter } from '../../../pubUtils/interface'; import { SchoolModel } from '../../../db/School'; -import { checkTeraphMaterialEnough, getSchoolList } from '../../../services/roleService' +import { getTeraphStrengthenResult, getSchoolList } from '../../../services/roleService' import { calPlayerCeAndSave, calAllHeroCe } from '../../../services/playerCeService'; import { HERO_SYSTEM_TYPE, LINEUP_NUM, ROLE_SELECT, REDIS_KEY, TASK_TYPE, DEFAULT_HEROES, DEFAULT_HERO_LV, DEFAULT_ITEMS, DEFAULT_EQUIPS, DEFAULT_GOLD, DEFAULT_COIN } from '../../../consts'; import { checkBattleHeroesByHid } from '../../../services/normalBattleService'; @@ -115,7 +115,7 @@ export class RoleHandler { let sid: string = session.get('sid'); let funcs: number[] = session.get('funcs'); - let role = await RoleModel.findByRoleId(roleId); + let role = await RoleModel.findByRoleId(roleId, 'roleId teraphs gold coin'); let teraphs = role.teraphs; let index = findIndex(teraphs, { id }); if (index < 0) @@ -125,20 +125,10 @@ export class RoleHandler { if (!dicTeraph) return resResult(STATUS.DIC_DATA_NOT_FOUND); - let attrs = new Array(); // 可以强化的属性 - dicTeraph.mainAttrMax.forEach((max, id) => { - let attrName = getAtrrNameById(id); - if (teraph[attrName] < max) { - attrs.push(id); - } - }); - - if (!attrs.length) + let { times, consumes, criAttr } = await getTeraphStrengthenResult(role, count, dicTeraph, teraph); + if (times == 0) return resResult(STATUS.ROLE_TERAPH_NOT_STRENGTHEN); - // 随机神像中的一条属性并检查道具是否足够,以及更新teraph - let { consumes, criAttr } = checkTeraphMaterialEnough(count, attrs, dicTeraph, teraph); - let result = await handleCost(roleId, sid, consumes); if (!result) return resResult(STATUS.BATTLE_CONSUMES_NOT_ENOUGH); diff --git a/game-server/app/services/rewardService.ts b/game-server/app/services/rewardService.ts index e2db36fd1..159094ef1 100644 --- a/game-server/app/services/rewardService.ts +++ b/game-server/app/services/rewardService.ts @@ -1,10 +1,10 @@ -import { ITID, CONSUME_TYPE, ITEM_TABLE, REDIS_KEY, TASK_TYPE, CURRENCY, CURRENCY_TYPE, MAIL_TYPE, HANDLE_REWARD_TYPE, HERO_SYSTEM_TYPE } from './../consts'; +import { ITID, CONSUME_TYPE, ITEM_TABLE, REDIS_KEY, TASK_TYPE, CURRENCY, CURRENCY_TYPE, MAIL_TYPE, HANDLE_REWARD_TYPE, HERO_SYSTEM_TYPE, CURRENCY_BY_TYPE } from './../consts'; import { EquipModel, EquipType } from './../db/Equip'; import { resResult } from '../pubUtils/util'; import { RoleModel, RoleType } from '../db/Role'; import { setAp } from './actionPointService'; import { pushCalPlayerCe, pushCalAllHeroCe, calPlayerCeAndSave } from './playerCeService'; -import { ItemModel } from '../db/Item'; +import { ItemModel, ItemType } from '../db/Item'; import { STATUS } from '../consts/statusCode'; import { pinus } from 'pinus'; import { addEquips, addBags, addSkin, addFigure, unlockFigure as pubUnlockFigure, createHeroes as pubCreateHeroes, transPiece, getGoldObject, getCoinObject, getApObject } from '../pubUtils/itemUtils'; @@ -22,6 +22,72 @@ import { BAG } from '../pubUtils/dicParam'; import { sendMailByContent } from './mailService'; import { calEquipSeids } from '../pubUtils/playerCe'; +export class CheckMeterial { + private roleId: string; + private itemsIndb: Map = new Map(); // 玩家已有的东西 + private consumes: ItemInter[] = []; // 消耗,正向数 + + private goldId = CURRENCY_BY_TYPE.get(CURRENCY_TYPE.GOLD); + private coinId = CURRENCY_BY_TYPE.get(CURRENCY_TYPE.COIN); + + constructor(roleId: string, role?: RoleType, items?: ItemType[]) { + this.roleId = roleId; + if(role) { + this.itemsIndb.set(this.goldId, role.gold); + this.itemsIndb.set(this.coinId, role.coin); + } + if(items && items.length) { + for(let {id, count} of items) { + this.itemsIndb.set(id, count); + } + } + } + + public async decrease(goods: {id: number, count: number}[]) { + let { items, gold, coin } = sortItems(goods, HANDLE_REWARD_TYPE.COST); + let isEnough = true; + for(let { id, count} of items) { + if(!this.itemsIndb.has(id)) { + let item = await ItemModel.findbyRoleAndGidAndCount(this.roleId, id, count); + if(!item) { + isEnough = false; break; + } + this.itemsIndb.set(id, item.count); + } + if(this.itemsIndb.get(id) < count) { + isEnough = false; break; + } + this.itemsIndb.set(id, this.itemsIndb.get(id) - count); + } + + if(gold.length > 0) { + if(!this.itemsIndb.has(this.goldId)) { + let role = await RoleModel.findByRoleId(this.roleId, 'gold coin'); + this.itemsIndb.set(this.goldId, role.gold); + this.itemsIndb.set(this.coinId, role.coin); + } + let goldCost = gold.reduce((pre, cur) => { return pre + cur.count }, 0); + if(this.itemsIndb.get(this.goldId) < goldCost) isEnough = false; + } + if(isEnough && coin > 0) { + if(!this.itemsIndb.has(this.coinId)) { + let role = await RoleModel.findByRoleId(this.roleId, 'gold coin'); + this.itemsIndb.set(this.goldId, role.gold); + this.itemsIndb.set(this.coinId, role.coin); + } + if(this.itemsIndb.get(this.coinId) < coin) isEnough = false; + } + + if(isEnough) this.consumes.push(...goods); + return isEnough; + } + + public getConsume() { + return this.consumes; + } +} + + export async function handleCost(roleId: string, sid: string, goods: Array) { let uids = [{ uid: roleId, sid }]; diff --git a/game-server/app/services/roleService.ts b/game-server/app/services/roleService.ts index ee3cb31e4..b3dda95f5 100644 --- a/game-server/app/services/roleService.ts +++ b/game-server/app/services/roleService.ts @@ -3,86 +3,64 @@ import { Channel } from 'pinus'; import { getRandValueByMinMax, getRandEelm, decodeIdCntArrayStr } from '../pubUtils/util'; import { TERAPH_RANDOM } from "../consts"; import { DicTeraph } from '../pubUtils/dictionary/DicTeraph'; -import { Teraph, RoleModel } from '../db/Role'; +import { Teraph, RoleModel, RoleType } from '../db/Role'; import { ROLE_SELECT } from '../consts'; import { SCHOOL } from '../pubUtils/dicParam'; import { gameData } from '../pubUtils/data'; import { SchoolModel } from '../db/School'; import { SclResultInter, SclPosInter } from '../pubUtils/interface'; -const TERAPH_STRENGTHEN = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; -/** - * 计算强化次数和消耗 - * @param count 强化次数 - * @param attrs 可以强化的属性名字 - * @param teraphInfo 字典表对应的神像信息 - * @param teraph 数据库内单个神像信息 - */ -export function checkTeraphMaterialEnough(count: number, attrs:number[], teraphInfo: DicTeraph, teraph: Teraph) { - let consumes = []; - let criAttr: number[] = []; - let times = 0; - if (count < 10) { - for (let i = 0; i < count; i++) { - if (!attrs.length) { - break; - } - let num = getRandValueByMinMax(TERAPH_RANDOM.MIN, TERAPH_RANDOM.MAX); // 强化时随机增加 2-4 属性 - let arr = getRandEelm(attrs, num); // 随机出的属性id - let critical = getRandValueByMinMax(0, 100);//属性暴击率 - let isCritical = critical <= teraphInfo.criRate; - let criEffect = 1; // 暴击效果 - if (isCritical) - criEffect = teraphInfo.criEffect; - for (let attrId of arr) { - let val = teraph.attr.get(attrId); // 已有的强化值 - val += teraphInfo.mainAttrUp.get(attrId) * criEffect; - let max = teraphInfo.mainAttrMax.get(attrId); - if(val > max) { - val = max; - let attrIndex = attrs.indexOf(attrId); - attrs.splice(attrIndex, 1); - } - teraph.attr.set(attrId, val); - if(isCritical) criAttr.push(attrId); - } - times++; - } - } else if (count == 10){ - let criticalArrTimes = getRandEelm(TERAPH_STRENGTHEN, 2);//10次中随机2次发生暴击 - for (let item of TERAPH_STRENGTHEN) { - if (!attrs.length) { - break; - } - let criEffect = 1; - let index = criticalArrTimes.indexOf(item); - let isCritical = index >= 0; - if (isCritical) { - criEffect = teraphInfo.criEffect;//本次是暴击 item 在 criticalArrTimes 中 - } - let num = getRandValueByMinMax(TERAPH_RANDOM.MIN, TERAPH_RANDOM.MAX); - let arr: number[] = getRandEelm(attrs, num); - for (let attrId of arr) { - let val = teraph.attr.get(attrId); // 已有的强化值 - val += teraphInfo.mainAttrUp.get(attrId) * criEffect; - let max = teraphInfo.mainAttrMax.get(attrId); +import { CheckMeterial } from './rewardService'; - if(val > max) { - val = max; - let attrIndex = attrs.indexOf(attrId); - attrs.splice(attrIndex, 1); - } - teraph.attr.set(attrId, val); - if(isCritical) criAttr.push(attrId); +export async function getTeraphStrengthenResult(role: RoleType, count: number, dicTeraph: DicTeraph, teraph: Teraph) { + let criAttr: number[] = [], times = 0; + let check = new CheckMeterial(role.roleId, role); + for(let i = 0; i < count; i++) { + let attrs: number[] = []; // 可以强化的属性 + dicTeraph.mainAttrMax.forEach((max, id) => { + if (teraph.attr.get(id) < max) { + attrs.push(id); } - times++; + }); + if(attrs.length <= 0) break; // 如果所有属性都到最高 + let isEnough = await check.decrease(dicTeraph.upMaterial); + + if(!isEnough) break; // 消耗不足 + + let num = getRandValueByMinMax(TERAPH_RANDOM.MIN, TERAPH_RANDOM.MAX); // 强化时随机增加 2-4 属性 + let arr = getRandEelm(attrs, num); // 随机出的属性id + let critical = getRandValueByMinMax(0, 100);//属性暴击率 + if(teraph.criCount == undefined || teraph.count == undefined) { + teraph.criCount = 0; + teraph.count = 0; } - } - //计算消耗 - for (let {id, count} of teraphInfo.upMaterial) { - consumes.push({ id, count: count * times}); + let isCritical = critical <= dicTeraph.criRate; // 每10次需要2次保底暴击 + if(!isCritical && Math.floor((teraph.count + 2)/10) * 2 > teraph.criCount) { + isCritical = true; + } else if (isCritical && Math.ceil(teraph.count/10) * 2 <= teraph.criCount) { + isCritical = false; + } + teraph.count ++; + if(isCritical) teraph.criCount ++; + + let criEffect = isCritical?dicTeraph.criEffect: 1; // 暴击效果 + for (let attrId of arr) { + let val = teraph.attr.get(attrId); // 已有的强化值 + val += dicTeraph.mainAttrUp.get(attrId) * criEffect; + let max = dicTeraph.mainAttrMax.get(attrId); + if(val > max) { + val = max; + let attrIndex = attrs.indexOf(attrId); + attrs.splice(attrIndex, 1); + } + teraph.attr.set(attrId, val); + if(isCritical) criAttr.push(attrId); + } + times++; + } - return { consumes, criAttr }; + return { times, consumes: check.getConsume(), criAttr } } + /** * * @param channel diff --git a/shared/consts/statusCode.ts b/shared/consts/statusCode.ts index 6b45fc9bc..06e2b6474 100644 --- a/shared/consts/statusCode.ts +++ b/shared/consts/statusCode.ts @@ -288,7 +288,7 @@ export const STATUS = { EQUIP_DECOMPOSE_IS_UPLIMIT: { code: 30516, simStr: '装备分解数量已达上限' }, //全局养成30600-30699 ROLE_REACH_MAX_TITLE_LEVEL: { code: 30600, simStr: '玩家已达到最高的爵位' }, - ROLE_TERAPH_NOT_STRENGTHEN: { code: 30601, simStr: '玩家神像不能强化' }, + ROLE_TERAPH_NOT_STRENGTHEN: { code: 30601, simStr: '材料不足或玩家神像不能强化' }, ROLE_TERAPH_NOT_QUILITY: { code: 30602, simStr: '玩家神像不能进阶' }, ROLE_SCHOOL_HERO_USED: { code: 30603, simStr: '该武将已配置' }, diff --git a/shared/db/Role.ts b/shared/db/Role.ts index b83d2d52d..5adbe386d 100644 --- a/shared/db/Role.ts +++ b/shared/db/Role.ts @@ -59,7 +59,7 @@ export class Teraph { @prop({ required: true, default: 1 }) id: number; // 神像的id @prop({ required: true, default: 1 }) - grade: number = 1; // 等级 + grade: number = 1; // 等级 @prop({ required: true, default: 0 }) hp: number = 0; @prop({ required: true, default: 0 }) @@ -68,6 +68,10 @@ export class Teraph { def: number = 0; @prop({ required: true, default: 0 }) mdef: number = 0; + @prop({ required: true, default: 0 }) + count: number = 0; // 次数 + @prop({ required: true, default: 0 }) + criCount: number = 0; // 暴击次数 constructor(id: number) { this.id = id;