import { ITID, CONSUME_TYPE, getCurNameById, ITEM_TABLE, HERO_SYSTEM_TYPE, CURRENCY_BY_TYPE, FIGURE_UNLOCK_CONDITION, REDIS_KEY, TASK_TYPE } from './../consts'; import { EquipModel } from './../db/Equip'; import { resResult } from '../pubUtils/util'; import { RoleModel, RoleType } from '../db/Role'; import { setAp } from './actionPointService'; import { calAllHeroCe, pushCalPlayerCe, pushCalAllHeroCe } from './playerCeService'; import { ItemModel } from '../db/Item'; import { STATUS } from '../consts/statusCode'; import { pinus } from 'pinus'; import { addEquips, addBags, addSkins, addFigure, unlockFigure as pubUnlockFigure, createHeroes as pubCreateHeroes, transPiece } from '../pubUtils/itemUtils'; import { EquipInter, ItemInter, BagInter } from '../pubUtils/interface'; import { gameData } from '../pubUtils/data'; import { uniq, indexOf, findIndex } from 'underscore'; import { HeroModel, HeroType } from '../db/Hero'; import { Figure } from '../domain/dbGeneral'; import { Rank } from './rankService'; import { checkActivityTask, pushActivityUpdate, pushTaskUpdate } from './taskService'; import { CreateHeroParam } from '../domain/roleField/hero'; export async function handleCost(roleId: string, sid: string, goods: Array) { let currencysMap: any = {}; let equips: Array = []; let bags: Array<{ id: number, count: number }> = []; let uids = [{ uid: roleId, sid }]; if (!sortConsumes(goods, bags, currencysMap, equips)) return false; // 检查货币是否充足 if (!!Object.keys(currencysMap).length) { let role = await RoleModel.findByRoleId(roleId); for (let key in currencysMap) { currencysMap[key] = role[key] - currencysMap[key]; if (currencysMap[key] < 0) { return false; } } } //检查装备是否存在 if (!!equips.length) { let resEquips = await EquipModel.getEquips(equips); if (resEquips.length < equips.length) return false; } //检查并修改道具 if (bags.length > 0) { let { hasError, result } = await ItemModel.decreaseItems(roleId, bags); if (hasError) return false; pinus.app.get('channelService').pushMessageByUids('onItemUpdate', resResult(STATUS.SUCCESS, { goods: result }), uids); } //删除装备 if (!!equips.length) { await EquipModel.deleteEquips(equips); pinus.app.get('channelService').pushMessageByUids('onEquipDel', resResult(STATUS.SUCCESS, { equips }), uids); } //消耗玩家货币 if (!!Object.keys(currencysMap).length) { await RoleModel.updateRoleInfo(roleId, currencysMap); pinus.app.get('channelService').pushMessageByUids('onPlayerDataChange', resResult(STATUS.SUCCESS, currencysMap), uids); } return true; } function sortConsumes(goods: Array, bags: Array, currencysMap: any, equips: Array) { for (let good of goods) { if (good.count == 0) continue; let goodInfo = gameData.goods.get(good.id); let { type, table } = ITID.get(goodInfo.itid); if (table == ITEM_TABLE.EQUIP) { if (!!good.seqId) { equips.push(good.seqId); } else { return false; } } else if (table == ITEM_TABLE.ITEM) { let index = indexOf(bags, { id: good.id }); if (index > 0) { bags[index].count = bags[index].count + good.count; } else { bags.push(good); } } else if (table == ITEM_TABLE.HERO) { return false } else if (table == ITEM_TABLE.ROLE) { let curname = getCurNameById(goodInfo.good_id); if (!!curname) { if (curname != 'ap') { currencysMap[curname] = (currencysMap[curname] || 0) + good.count; } else { return false; } } } } return true; } // TODO: sid 在方法内部获取,且不一定存在 export async function addItems(roleId: string, roleName: string, sid: string, goods: Array) { let showItems: Array = []; let currencysMap: any = {}; let equips: Array = []; let bags: Array = []; let skins: Array = []; let figures: Array = []; let uids = [{ uid: roleId, sid }]; sortItems(goods, bags, skins, figures, currencysMap, equips, showItems); let equipInfos = [], taskPushMessage = []; for (let equip of equips) { let { equipInfo, pushMessage } = await addEquips(roleId, roleName, equip); showItems.push({ seqId: equipInfo.seqId, id: equip.id, count: 1 }); equipInfos.push(equipInfo); taskPushMessage.concat(pushMessage); } //装备推送 if (!!equipInfos.length) pinus.app.get('channelService').pushMessageByUids('onEquipAdd', resResult(STATUS.SUCCESS, { equipInfos }), uids); pushTaskUpdate(roleId, sid, null, taskPushMessage); //统计装备 if (equipInfos.length > 0) { let { serverId } = await RoleModel.findByRoleId(roleId); await checkActivityTask(serverId, sid, [], roleId, TASK_TYPE.EQUIP_QUALITY_COUNT, equipInfos.length, { equips: equipInfos }) } //货币推送 if (!!Object.keys(currencysMap).length) { let role = await RoleModel.findByRoleId(roleId); for (let key in currencysMap) { if (key == 'ap') { let { ap } = await setAp(Date.now(), roleId, sid, null, currencysMap[key]); currencysMap.ap = ap; } else { currencysMap[key] += role[key]; } } await RoleModel.updateRoleInfo(roleId, currencysMap); pinus.app.get('channelService').pushMessageByUids('onPlayerDataChange', resResult(STATUS.SUCCESS, currencysMap), uids); } let bagInfos = []; for (let item of bags) { let bagInfo = await addBags(roleId, roleName, item); showItems.push({ id: item.id, count: item.count }); bagInfos.push(bagInfo); } //背包除去装备推送 if (!!bagInfos.length) pinus.app.get('channelService').pushMessageByUids('onItemUpdate', resResult(STATUS.SUCCESS, { goods: bagInfos }), uids); let figureInfo = await addFigure(roleId, figures); for (let id of figures) {//皮肤推送 showItems.push({ id, count: 1 }); } if (!!figureInfo && (figureInfo.heads.length > 0 || figureInfo.frames.length > 0 || figureInfo.spines.length > 0)) { pinus.app.get('channelService').pushMessageByUids('onHeadChange', resResult(STATUS.SUCCESS, { ...figureInfo }), uids); } let skinInfos = []; let addSkinIds = []; for (let skinId of skins) {//皮肤推送 let result = await addSkins(roleId, skinId); if (!!result) { showItems.push({ id: skinId, count: 1 }); skinInfos.push(result); addSkinIds.push(skinId); } } if (!!skinInfos.length) { let unlockedType = addSkinIds.map(cur => { return { type: FIGURE_UNLOCK_CONDITION.GET_SKIN, paramSkinId: cur } }); await unlockFigure(sid, roleId, unlockedType); calAllHeroCe(HERO_SYSTEM_TYPE.ADD_SKIN, sid, roleId, {}, addSkinIds); pinus.app.get('channelService').pushMessageByUids('onHeroSkinChange', resResult(STATUS.SUCCESS, { skinInfos }), uids); } return showItems; } function sortItems(goods: Array, bags: Array, skins: Array, figures: Array, currencysMap: any, equips: Array, showItems: Array) { for (let good of goods) { let goodInfo = gameData.goods.get(good.id); // 道具不存在时先跳过 if (!goodInfo) { console.log('sortItems 道具不存在:', good.id); continue; } let { type, table, isCurrency } = ITID.get(goodInfo.itid); if (table == ITEM_TABLE.EQUIP) { for (let i = 0; i < good.count; i++) { equips.push({ id: good.id, ...goodInfo }); } } else if (table == ITEM_TABLE.ITEM) { let index = findIndex(bags, { id: good.id }); if (index > 0) { bags[index].count = bags[index].count + good.count; } else { bags.push({ id: good.id, count: good.count, itemName: goodInfo.name, hid: goodInfo.hid || 0, type }); } } else if (table == ITEM_TABLE.HERO) { if (type == CONSUME_TYPE.SKIN) { let index = indexOf(skins, good.id); if (index == -1) { skins.push(good.id); } } } else if (table == ITEM_TABLE.ROLE) { if (!!isCurrency) { let curname = getCurNameById(goodInfo.good_id); if (!!curname) { let index = findIndex(showItems, { id: good.id }); if (index > 0) { showItems[index].count = showItems[index].count + good.count; } else { showItems.push(good); } currencysMap[curname] = (currencysMap[curname] || 0) + good.count; } } else { if (type == CONSUME_TYPE.HEAD || type == CONSUME_TYPE.FRAME || type == CONSUME_TYPE.SPINE) { let index = indexOf(figures, good.id); if (index == -1) { figures.push(good.id); } } } } } } export async function decreaseItems(roleId: string, sid: string, bags: Array<{ id: number, count: number, ratio?: number }>) { let uids = [{ uid: roleId, sid }]; if (bags.length > 0) { let { hasError, result } = await ItemModel.decreaseItems(roleId, bags); if (hasError) return true; pinus.app.get('channelService').pushMessageByUids('onItemUpdate', resResult(STATUS.SUCCESS, { goods: result }), uids); } return false; } export async function checkGoods(roleId: string, goodIds: Array) { let equipIds: Array = []; let itemIds: Array = []; let hids: Array = []; goodIds = uniq(goodIds); for (let goodId of goodIds) { let goodInfo = gameData.goods.get(goodId); if (!!goodInfo) { let { table } = ITID.get(goodInfo.itid); if (table == ITEM_TABLE.EQUIP) { equipIds.push(goodId); } else if (table == ITEM_TABLE.ITEM) { itemIds.push(goodId); } } else { hids.push(goodId); } } if (!!hids.length) { let heros = await HeroModel.findByHidRange(hids, roleId); if (heros.length < hids.length) return false; } //检查装备是否存在 if (!!equipIds.length) { let resEquips = await EquipModel.getEquipsByIds(roleId, equipIds); resEquips = uniq(resEquips, function (resEquip) { return resEquip.id; }); if (resEquips.length < equipIds.length) return false; } //检查并修改道具 if (itemIds.length > 0) { let items = await ItemModel.findbyRoleAndIds(roleId, itemIds); if (items.length < itemIds.length) return false; } return true; } export async function unlockFigure(sid: string, roleId: string, conditions: { type: number, paramHid?: number, paramFavourLv?: number, paramSkinId?: number }[], role?: RoleType) { let figureInfo = await pubUnlockFigure(roleId, conditions, role); await pushFigureUpdate(roleId, sid, figureInfo); } export async function pushFigureUpdate(roleId: string, sid: string, figureInfo: { heads: Figure[], frames: Figure[], spines: Figure[] }) { if (!!figureInfo && (figureInfo.heads.length > 0 || figureInfo.frames.length > 0 || figureInfo.spines.length > 0)) { let uids = [{ uid: roleId, sid }]; pinus.app.get('channelService').pushMessageByUids('onHeadChange', resResult(STATUS.SUCCESS, { ...figureInfo }), uids); } } /** * 创建多个武将 * @param roleId * @param sid * @param serverId * @param heroInfo */ export async function createHeroes(roleId: string, roleName: string, sid: string, serverId: number, funcs: number[], heroInfo: CreateHeroParam[]) { let hids = heroInfo.map(cur => cur.hid); let userHeroesMap = await HeroModel.findMapByHidRange(hids, roleId); let newHeroInfo: CreateHeroParam[] = [], pieces: ItemInter[] = []; for (let h of heroInfo) { let heroCount = h.count || 1; if (userHeroesMap.has(h.hid)) { let { pieceId, count } = transPiece(h.hid); pieces.push({ id: pieceId, count: count * heroCount }); } else { newHeroInfo.push(h) userHeroesMap.set(h.hid, null); if (heroCount > 1) { let { pieceId, count } = transPiece(h.hid); pieces.push({ id: pieceId, count: count * (heroCount - 1) }); } } } let resultHeroes: HeroType[] = [], resultItems: ItemInter[] = []; if (newHeroInfo.length > 0) { let { heroes, role, figureInfo, calHeroResults, calAllHeroResults, taskPushMessage, activityTaskPushMessage } = await pubCreateHeroes(roleId, roleName, serverId, newHeroInfo, funcs); let r = new Rank(REDIS_KEY.HERO_NUM_RANK, { serverId }); await r.setRankWithRoleInfo(roleId, role.heroNum, role.heroNumUpdatedAt, role); await pushFigureUpdate(roleId, sid, figureInfo); for (let calHeroResult of calHeroResults) { await pushCalPlayerCe(roleId, sid, calHeroResult); } for (let calAllHeroResult of calAllHeroResults) { await pushCalAllHeroCe(roleId, sid, calAllHeroResult); } pushTaskUpdate(roleId, sid, null, taskPushMessage); pushActivityUpdate(roleId, sid, null, activityTaskPushMessage); resultHeroes = heroes; } if (pieces.length > 0) { let goods = await addItems(roleId, roleName, sid, pieces); resultItems = goods; } return { heroes: resultHeroes, goods: resultItems } } export async function createHero(roleId: string, roleName: string, sid: string, serverId: number, funcs: number[], heroInfo: CreateHeroParam) { let result = await createHeroes(roleId, roleName, sid, serverId, funcs, [heroInfo]); return result; }