413 lines
17 KiB
TypeScript
413 lines
17 KiB
TypeScript
import { ITID, CONSUME_TYPE, ITEM_TABLE, REDIS_KEY, TASK_TYPE, CURRENCY, CURRENCY_TYPE, MAIL_TYPE, HANDLE_REWARD_TYPE } from './../consts';
|
|
import { EquipModel } from './../db/Equip';
|
|
import { resResult } from '../pubUtils/util';
|
|
import { RoleModel, RoleType } from '../db/Role';
|
|
import { setAp } from './actionPointService';
|
|
import { pushCalPlayerCe, pushCalAllHeroCe } from './playerCeService';
|
|
import { ItemModel } from '../db/Item';
|
|
import { STATUS } from '../consts/statusCode';
|
|
import { pinus } from 'pinus';
|
|
import { addEquips, addBags, addSkin, addFigure, unlockFigure as pubUnlockFigure, createHeroes as pubCreateHeroes, transPiece } from '../pubUtils/itemUtils';
|
|
import { ItemInter, RewardInter, } from '../pubUtils/interface';
|
|
import { gameData } from '../pubUtils/data';
|
|
import { uniq } 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';
|
|
import { HeroSkin } from '../db/Hero';
|
|
import { errlogger } from '../util/logger';
|
|
import { BAG } from '../pubUtils/dicParam';
|
|
import { sendMailByContent } from './mailService';
|
|
|
|
export async function handleCost(roleId: string, sid: string, goods: Array<ItemInter>) {
|
|
|
|
let uids = [{ uid: roleId, sid }];
|
|
let { items, equips, gold, coin } = sortItems(goods, HANDLE_REWARD_TYPE.COST);
|
|
let equipSeqIds = equips.map(cur => cur.seqId);
|
|
|
|
// 检查货币是否充足
|
|
let role = await RoleModel.findByRoleId(roleId);
|
|
if (gold.length > 0 || coin > 0) {
|
|
let { gold: originGold, coin: originCoin } = role;
|
|
for(let {count} of gold) { originGold -= count };
|
|
if(originGold < 0 || originCoin < coin) return false;
|
|
}
|
|
//检查装备是否存在
|
|
if (equips.length > 0) {
|
|
let resEquips = await EquipModel.getEquips(equipSeqIds);
|
|
if (resEquips.length < equips.length)
|
|
return false;
|
|
}
|
|
//检查并修改道具
|
|
if (items.length > 0) {
|
|
let { hasError, result } = await ItemModel.decreaseItems(roleId, items);
|
|
if (hasError) return false;
|
|
pinus.app.get('channelService').pushMessageByUids('onItemUpdate', resResult(STATUS.SUCCESS, { goods: result }), uids);
|
|
}
|
|
|
|
//删除装备
|
|
if (equips.length > 0) {
|
|
await EquipModel.deleteEquips(roleId, equipSeqIds);
|
|
pinus.app.get('channelService').pushMessageByUids('onEquipDel', resResult(STATUS.SUCCESS, { equips }), uids);
|
|
}
|
|
|
|
//消耗玩家货币
|
|
if (gold.length > 0 || coin > 0) {
|
|
role = await RoleModel.decreaseGoldAndCoin(roleId, gold, coin);
|
|
pinus.app.get('channelService').pushMessageByUids('onPlayerDataChange', resResult(STATUS.SUCCESS, {
|
|
gold: role.gold, coin: role.coin
|
|
}), uids);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
// TODO: sid 在方法内部获取,且不一定存在
|
|
export async function addItems(roleId: string, roleName: string, sid: string, goods: Array<ItemInter>) {
|
|
let uids = [{ uid: roleId, sid }];
|
|
let { items, equips, gold, coin, ap, skins, figures } = sortItems(goods, HANDLE_REWARD_TYPE.RECEIVE);
|
|
let showItems: { id: number, seqId?: number, count: number, isBag?: boolean }[] = [];
|
|
let role = await RoleModel.findByRoleId(roleId);
|
|
// 1. 装备处理
|
|
if(equips.length > 0) {
|
|
let { equipCount = 0 } = role;
|
|
let incEquips = equips, mailEquips: { id?: number, hid?: number, seqId?: number }[] = [];
|
|
if(equips.length + equipCount > BAG.BAG_EQUIP_UPLIMITED) { // 装备上限
|
|
let inc = BAG.BAG_EQUIP_UPLIMITED - equipCount;
|
|
if(inc < 0) inc = 0;
|
|
incEquips = equips.slice(0, inc);
|
|
mailEquips = equips.slice(inc);
|
|
}
|
|
|
|
// 直接加的
|
|
let { equips: equipInfos, pushMessages } = await addEquips(roleId, roleName, <{id: number, hid?: number}[]>incEquips);
|
|
for (let equip of equipInfos) {
|
|
showItems.push({ seqId: equip.seqId, id: equip.id, count: 1, isBag: true });
|
|
}
|
|
for(let equip of combineEquips(mailEquips)) {
|
|
showItems.push({ id: equip.id, count: equip.count, isBag: false });
|
|
}
|
|
//装备推送
|
|
if (!!equipInfos.length)
|
|
pinus.app.get('channelService').pushMessageByUids('onEquipAdd', resResult(STATUS.SUCCESS, { equipInfos }), uids);
|
|
pushTaskUpdate(roleId, sid, null, pushMessages);
|
|
//统计装备
|
|
if (equipInfos.length > 0) {
|
|
let { serverId } = await RoleModel.findByRoleId(roleId);
|
|
await checkActivityTask(serverId, sid, [], roleId, TASK_TYPE.EQUIP_QUALITY_COUNT, equipInfos.length, { equips: equipInfos.map(obj => { return { quality: obj.quality } }) })
|
|
}
|
|
// 发邮件的
|
|
if(mailEquips.length > 0) {
|
|
await sendMailByContent(MAIL_TYPE.EQUIP_OVER, roleId, { goods: combineEquips(mailEquips) });
|
|
}
|
|
}
|
|
|
|
// 2. 道具处理
|
|
if(items.length > 0) {
|
|
let { items: itemInfos } = await addBags(roleId, roleName, items);
|
|
for (let item of items) {
|
|
showItems.push({ id: item.id, count: item.count });
|
|
}
|
|
//背包除去装备推送
|
|
if (!!itemInfos.length)
|
|
pinus.app.get('channelService').pushMessageByUids('onItemUpdate', resResult(STATUS.SUCCESS, { goods: itemInfos }), uids);
|
|
|
|
}
|
|
|
|
// 3. 货币推送
|
|
if(gold.length > 0 || coin > 0 || ap > 0) {
|
|
let { ap: addAp } = await setAp(roleId, role.lv, ap, sid, []);
|
|
|
|
role = await RoleModel.increaseGoldAndCoin(roleId, gold, coin);
|
|
pinus.app.get('channelService').pushMessageByUids('onPlayerDataChange', resResult(STATUS.SUCCESS, {
|
|
gold: role.gold, coin: role.coin, ap: addAp
|
|
}), uids);
|
|
}
|
|
|
|
// 4. 皮肤处理
|
|
let figureInfos:{ heads: Figure[], frames: Figure[], spines: Figure[] }[] = []; // 头像变化推送信息
|
|
if(skins.length > 0) {
|
|
let heroskins: {skins: HeroSkin[], hid: number}[] = []; // 皮肤推送信息
|
|
let skinInfos: {id: number, hid: number }[] = [];
|
|
let calAllHeroResult = undefined; // 全局战力变化推送
|
|
|
|
for (let skinId of skins) {//皮肤推送
|
|
let result = await addSkin(roleId, roleName, skinId, false);
|
|
console.log(result)
|
|
if (!!result) {
|
|
showItems.push({ id: skinId, count: 1 });
|
|
figureInfos.push(result.figureInfo);
|
|
if(result.hero) {
|
|
heroskins.push({ skins: result.hero.skins, hid: result.hero.hid });
|
|
if(result.calAllHeroResult) calAllHeroResult = result.calAllHeroResult;
|
|
}
|
|
skinInfos.push({ id: skinId, hid: result.hero?.hid||0 })
|
|
}
|
|
}
|
|
if (!!skinInfos.length) {
|
|
pushHeroSkinMsg(heroskins, skinInfos, uids); // 推送onHeroSkinChange
|
|
}
|
|
// 推送全局加成信息
|
|
if(calAllHeroResult) await pushCalAllHeroCe(roleId, sid, calAllHeroResult);
|
|
}
|
|
|
|
// 5. 获得头像和相框等
|
|
if(figures.length > 0) {
|
|
let figureInfo = await addFigure(roleId, figures);
|
|
if(figureInfo) figureInfos.push(figureInfo);
|
|
for (let id of figures) {//皮肤推送
|
|
showItems.push({ id, count: 1 });
|
|
}
|
|
}
|
|
|
|
// 获得头像或相框或形象推送
|
|
if(!!figureInfos && figureInfos.length > 0) {
|
|
for(let figureInfo of figureInfos) {
|
|
pinus.app.get('channelService').pushMessageByUids('onHeadChange', resResult(STATUS.SUCCESS, { ...figureInfo }), uids);
|
|
}
|
|
}
|
|
|
|
return showItems;
|
|
}
|
|
|
|
function combineEquips(equips: { id?: number }[]) {
|
|
let result: { id: number, count: number }[] = [];
|
|
for(let { id } of equips) {
|
|
let index = result.findIndex(cur => cur.id == id);
|
|
if(index == -1) {
|
|
result.push({ id, count: 1 });
|
|
} else {
|
|
result[index].count ++;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
function sortItems(goods: ItemInter[], handleType: HANDLE_REWARD_TYPE) {
|
|
let items: { id: number, count: number }[] = []; // 可叠加道具
|
|
let equips: { seqId?: number, id?: number, hid?: number }[] = []; // 不可叠加装备
|
|
let gold: { count: number, isPay: boolean }[] = []; // 金币
|
|
let coin: number = 0;
|
|
let ap: number = 0;
|
|
let skins: number[] = [];
|
|
let figures: number[] = [];
|
|
|
|
for(let good of goods) {
|
|
if(good.count == 0) continue;
|
|
let dicGood = gameData.goods.get(good.id);
|
|
if(!dicGood) {
|
|
errlogger.error(`物品 ${good.id} 未配置`);
|
|
continue;
|
|
}
|
|
let dicItid = ITID.get(dicGood.itid);
|
|
if(!dicItid) {
|
|
errlogger.error(`itid ${dicGood.itid} 未配置`);
|
|
continue;
|
|
}
|
|
let { type, table, isCurrency } = dicItid;
|
|
if(table == ITEM_TABLE.EQUIP) { // 装备
|
|
if(handleType == HANDLE_REWARD_TYPE.RECEIVE) {
|
|
for(let i = 0; i < good.count; i++) {
|
|
equips.push({ id: good.id, hid: good.hid })
|
|
}
|
|
} else {
|
|
if(!!good.seqId) {
|
|
equips.push({ seqId: good.seqId });
|
|
}
|
|
}
|
|
} else if (table == ITEM_TABLE.ITEM) { // 可叠加道具
|
|
let index = items.findIndex(cur => cur.id == good.id);
|
|
if(index > 0) {
|
|
items[index].count += good.count;
|
|
} else {
|
|
items.push({ id: good.id, count: good.count });
|
|
}
|
|
} else if (table == ITEM_TABLE.SKIN) { // 皮肤,不可重复获得,不可删
|
|
if(handleType == HANDLE_REWARD_TYPE.RECEIVE) {
|
|
let index = skins.indexOf(good.id);
|
|
if (index == -1) {
|
|
skins.push(good.id);
|
|
}
|
|
}
|
|
} else if (table == ITEM_TABLE.ROLE) {
|
|
if(isCurrency) { // 3种货币
|
|
let dicCurrency = CURRENCY.get(good.id);
|
|
if(dicCurrency) {
|
|
if(dicCurrency.type == CURRENCY_TYPE.GOLD) { // 金币,区分付费和免费,默认免费
|
|
let index = gold.findIndex(cur => cur.isPay == !!good.isPay);
|
|
if(index > 0) {
|
|
gold[index].count += good.count;
|
|
} else {
|
|
gold.push({ count: good.count, isPay: !!good.isPay });
|
|
}
|
|
} else if (dicCurrency.type == CURRENCY_TYPE.COIN) { // 铜钱
|
|
coin += good.count;
|
|
} else if (dicCurrency.type == CURRENCY_TYPE.ACTION_POINT) { // 体力
|
|
ap += good.count;
|
|
}
|
|
}
|
|
} else {
|
|
if (type == CONSUME_TYPE.HEAD || type == CONSUME_TYPE.FRAME || type == CONSUME_TYPE.SPINE) { // 头像等,不可重复获得,不可删
|
|
let index = figures.indexOf(good.id);
|
|
if (index == -1) {
|
|
figures.push(good.id);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
return { items, equips, gold, coin, ap, skins, figures }
|
|
}
|
|
|
|
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<number>) {
|
|
let equipIds: Array<number> = [];
|
|
let itemIds: Array<number> = [];
|
|
let hids: Array<number> = [];
|
|
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: RewardInter[] = [];
|
|
if (newHeroInfo.length > 0) {
|
|
|
|
let { heroes, role, figureInfo, calHeroResults, calAllHeroResult, 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);
|
|
}
|
|
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;
|
|
}
|
|
|
|
/**
|
|
* 皮肤数据变化去重、推送
|
|
* @param heroskins 推送的皮肤
|
|
* @param uids 玩家
|
|
*/
|
|
function pushHeroSkinMsg(heroskins: {skins: HeroSkin[], hid: number}[], skinInfos: {id: number, hid: number }[], uids: {uid: string, sid: string}[]) {
|
|
let pushSkinInfos: {skins: HeroSkin[], hid: number}[] = []; // 可能会有重复的
|
|
for(let { skins, hid } of heroskins) {
|
|
let index = pushSkinInfos.findIndex(cur => cur.hid == hid);
|
|
if(index == -1) {
|
|
pushSkinInfos.push({skins, hid});
|
|
} else {
|
|
if(skins.length > pushSkinInfos[index].skins.length) {
|
|
pushSkinInfos[index] = {skins, hid};
|
|
}
|
|
}
|
|
}
|
|
if(pushSkinInfos.length > 0 || skinInfos.length > 0) {
|
|
pinus.app.get('channelService').pushMessageByUids('onHeroSkinChange', resResult(STATUS.SUCCESS, { heros: heroskins, skins: skinInfos }), uids);
|
|
}
|
|
} |