Files
ZYZ/game-server/app/services/rewardService.ts
2021-03-31 21:01:12 +08:00

296 lines
11 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { ITID, CONSUME_TYPE, getCurNameById, ITEM_TABLE, HERO_SYSTEM_TYPE, CURRENCY_BY_TYPE, FIGURE_UNLOCK_CONDITION } from './../consts';
import { EquipModel } from './../db/Equip';
import { resResult, parseGoodStr } from '../pubUtils/util';
import { getGoodById } from '../pubUtils/gamedata';
import { RoleModel, RoleType } from '../db/Role';
import { setAp } from './actionPointService';
import { calAllHeroCe } from './playerCeService';
import { ItemModel } from '../db/Item';
import { STATUS } from '../consts/statusCode';
import { pinus } from 'pinus';
import { addEquips, addBags, addSkins, addFigure, unlockFigure as pubUnlockFigure } from '../pubUtils/itemUtils';
import { EquipInter, ItemInter, BagInter } from '../pubUtils/interface';
import { gameData } from '../pubUtils/data';
import { uniq, indexOf, findIndex } from 'underscore';
import { HeroModel } from '../db/Hero';
export async function handleFixedReward(roleId: string, roleName: string, sid: string, rewardStr: string, multi: number) {
let reward = parseGoodStr(rewardStr);
let rewards = [];
for(let obj of reward)
rewards.push({ ...obj, count: Math.ceil(obj.count * multi)});
const result = await addItems(roleId, roleName, sid, reward);
return result;
}
export async function handleCost(roleId: string, sid: string, goods: Array<ItemInter>) {
let currencysMap: any = {};
let equips: Array<number> = [];
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<ItemInter>, bags: Array<ItemInter>, currencysMap: any, equips: Array<number>) {
for (let good of goods) {
let goodInfo = getGoodById(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<ItemInter>) {
let showItems: Array<ItemInter> = [];
let currencysMap: any = {};
let equips: Array<EquipInter> = [];
let bags: Array<BagInter> = [];
let skins: Array<number> = [];
let figures: Array<number> = [];
let uids = [{uid: roleId, sid}];
sortItems(goods, bags, skins, figures, currencysMap, equips, showItems);
let equipInfos = [];
for (let equip of equips) {
let equipInfo = await addEquips(roleId, roleName, equip);
showItems.push({seqId: equipInfo.seqId, id: equip.id, count: 1});
equipInfos.push(equipInfo);
}
//装备推送
if (!!equipInfos.length)
pinus.app.get('channelService').pushMessageByUids('onEquipAdd', resResult(STATUS.SUCCESS, {equipInfos}), uids);
//货币推送
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, 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<ItemInter>, bags: Array<BagInter>, skins: Array<number>, figures: Array<number>, currencysMap: any, equips: Array<EquipInter>, showItems: Array<ItemInter>) {
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<number>) {
let equipIds: Array<number> = [];
let itemIds: Array<number> = [];
let hids: Array<number> = [];
goodIds = uniq(goodIds);
for (let goodId of goodIds) {
let goodInfo = getGoodById(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);
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);
}
}