254 lines
11 KiB
TypeScript
254 lines
11 KiB
TypeScript
import { Application, BackendSession, pinus } from "pinus";
|
||
import { gameData, hasShopType } from "../../../pubUtils/data";
|
||
import { arrToMap, parseGoodStr, resResult } from "../../../pubUtils/util";
|
||
import { STATUS, GUILD_STRUCTURE, ITID, CONSUME_TYPE, HERO_QUALITY_TYPE, HERO_GROW_MAX, ITEM_CHANGE_REASON } from "../../../consts";
|
||
import { UserShopModel } from "../../../db/UserShop";
|
||
import { handleCost, addItems } from "../../../services/role/rewardService";
|
||
import { SHOP } from "../../../pubUtils/dicParam";
|
||
import { HeroModel, HeroType } from "../../../db/Hero";
|
||
import { checkShopInPurchase, getShopDicById, getShopListByType, getShopPrice } from "../../../services/shopService";
|
||
import { RewardInter, recycleSoulFastPara } from "../../../pubUtils/interface";
|
||
import { UserShopTypeModel } from "../../../db/UserShopType";
|
||
import { nowSeconds } from "../../../pubUtils/timeUtil";
|
||
import { isGoodsHidden, isHeroHidden } from "../../../services/dataService";
|
||
import { RoleModel } from './../../../db/Role';
|
||
import { calUpSixColorsResidueFragment } from "../../../services/role/checkMaterial";
|
||
import { ItemModel } from "../../../db/Item";
|
||
|
||
export default function (app: Application) {
|
||
return new ShopHandler(app);
|
||
}
|
||
|
||
export class ShopHandler {
|
||
constructor(private app: Application) {
|
||
}
|
||
|
||
// 获得商品列表
|
||
async getShopList(msg: { shop: number, type: number }, session: BackendSession) {
|
||
let roleId = session.get('roleId');
|
||
let serverId = session.get('serverId');
|
||
let { shop, type } = msg;
|
||
|
||
if (!hasShopType(shop, type)) {
|
||
return resResult(STATUS.WRONG_PARMS);
|
||
}
|
||
|
||
const result = await getShopListByType(shop, type, roleId, serverId);
|
||
return resResult(STATUS.SUCCESS, result);
|
||
}
|
||
|
||
// 读取红点
|
||
async readShop(msg: { shop: number, type: number }, session: BackendSession) {
|
||
let roleId = session.get('roleId');
|
||
let { shop, type } = msg;
|
||
|
||
if (!hasShopType(shop, type)) {
|
||
return resResult(STATUS.WRONG_PARMS);
|
||
}
|
||
|
||
await UserShopTypeModel.read(roleId, shop, type);
|
||
return resResult(STATUS.SUCCESS);
|
||
}
|
||
|
||
// 购买商品
|
||
async purchase(msg: { activityId: number, shopItemId: number, count: number }, session: BackendSession) {
|
||
let roleId = session.get('roleId');
|
||
let roleName = session.get('roleName');
|
||
let sid = session.get('sid');
|
||
let serverId = session.get('serverId');
|
||
let seasonNum = pinus.app.get('pvpSeasonNum');
|
||
|
||
let { activityId = 0, shopItemId, count } = msg;
|
||
|
||
let dicShopItem = await getShopDicById(activityId, shopItemId, roleId, serverId);
|
||
if (!dicShopItem) return resResult(STATUS.DIC_DATA_NOT_FOUND);
|
||
if (dicShopItem['productID'] && dicShopItem['productID'] != '&') return resResult(STATUS.CAN_NOT_PURCHASE);
|
||
if (dicShopItem['beginTime'] && dicShopItem['beginTime'] > nowSeconds()) return resResult(STATUS.SHOP_CLOSED);
|
||
if (dicShopItem['endTime'] && dicShopItem['endTime'] < nowSeconds()) return resResult(STATUS.SHOP_CLOSED);
|
||
|
||
let userShop = await UserShopModel.findByRoleAndItem(roleId, dicShopItem, seasonNum);
|
||
|
||
let checkResult = await checkShopInPurchase(session, activityId, count, userShop?.count || 0, dicShopItem);
|
||
if (checkResult.code != STATUS.SUCCESS.code) {
|
||
return resResult(checkResult);
|
||
}
|
||
|
||
// 总计可买次数(从配置表读取)
|
||
const totalCanBuyTimes = dicShopItem.purchaseLimit;
|
||
if (!totalCanBuyTimes || totalCanBuyTimes <= 0) {
|
||
return resResult(STATUS.BATTLE_CONSUMES_NOT_ENOUGH);
|
||
}
|
||
|
||
// 消耗
|
||
let cost = getShopPrice(dicShopItem.money, count, userShop?.count || 0, dicShopItem.price);
|
||
let costResult = await handleCost(roleId, sid, cost, ITEM_CHANGE_REASON.SHOP_PURCHASE);
|
||
if (!costResult) return resResult(STATUS.BATTLE_CONSUMES_NOT_ENOUGH);
|
||
|
||
// 次数
|
||
userShop = await UserShopModel.purchase(roleId, roleName, activityId, dicShopItem, count, seasonNum);
|
||
if (!userShop || (userShop && userShop.count > totalCanBuyTimes)) {
|
||
// rollback 消耗
|
||
let role = await RoleModel.findByRoleId(roleId);
|
||
addItems(roleId, role.roleName, sid, cost, ITEM_CHANGE_REASON.SHOP_PURCHASE);
|
||
|
||
// rollback 购买次数
|
||
await UserShopModel.updateCount(roleId, dicShopItem, -count, seasonNum)
|
||
return resResult(STATUS.BUY_COUNT_OVER);
|
||
}
|
||
|
||
// 获得
|
||
let reward = [{
|
||
id: dicShopItem.goodId,
|
||
count: count * (dicShopItem.num || 1)
|
||
}];
|
||
let goods = await addItems(roleId, roleName, sid, reward, ITEM_CHANGE_REASON.SHOP_PURCHASE);
|
||
|
||
return resResult(STATUS.SUCCESS, {
|
||
shopItemId, count,
|
||
goods
|
||
});
|
||
|
||
}
|
||
|
||
// 将魂回收
|
||
async recycleSoul(msg: { goodsId: number, count: number }, session: BackendSession) {
|
||
let roleId = session.get('roleId');
|
||
let roleName = session.get('roleName');
|
||
let sid = session.get('sid');
|
||
let { goodsId, count } = msg;
|
||
|
||
if (isGoodsHidden(goodsId)) return resResult(STATUS.ITEM_IS_HIDDEN);
|
||
let dicGoods = gameData.goods.get(goodsId);
|
||
if (!dicGoods) return resResult(STATUS.DIC_DATA_NOT_FOUND);
|
||
let dicItid = ITID.get(dicGoods.itid);
|
||
if (!dicItid) return resResult(STATUS.DIC_DATA_NOT_FOUND);
|
||
if (dicItid.type != CONSUME_TYPE.SOUL) {
|
||
return resResult(STATUS.ITEM_NOT_SOUL);
|
||
}
|
||
|
||
let hero = await HeroModel.findByHidAndRole(dicGoods.hid, roleId);
|
||
if (!hero) return resResult(STATUS.HERO_NOT_MAX);
|
||
if (hero.colorStar != HERO_GROW_MAX.COLORSTAR) {
|
||
let residueFragment = await calUpSixColorsResidueFragment(roleId, hero, dicGoods.hid);
|
||
if (!residueFragment || count > residueFragment) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH);
|
||
// return resResult(STATUS.HERO_NOT_MAX);
|
||
}
|
||
|
||
// 检查自己的数量
|
||
let cost = [{
|
||
id: goodsId, count
|
||
}];
|
||
let costResult = await handleCost(roleId, sid, cost, ITEM_CHANGE_REASON.RECYCLE_SOUL);
|
||
if (!costResult) return resResult(STATUS.BATTLE_CONSUMES_NOT_ENOUGH);
|
||
|
||
let reward: RewardInter[] = [];
|
||
switch (dicGoods.quality) {
|
||
case HERO_QUALITY_TYPE.BLUE:
|
||
reward = parseGoodStr(SHOP.HERO_SOUL_BULE); break;
|
||
case HERO_QUALITY_TYPE.PURPLE:
|
||
reward = parseGoodStr(SHOP.HERO_SOUL_PURPLE); break;
|
||
case HERO_QUALITY_TYPE.GOLD:
|
||
reward = parseGoodStr(SHOP.HERO_SOUL_GOLDEN); break;
|
||
case HERO_QUALITY_TYPE.UR:
|
||
reward = parseGoodStr(SHOP.HERO_SOUL_UR); break;
|
||
}
|
||
// 增加货币
|
||
let goods = await addItems(roleId, roleName, sid, reward.map(cur => { return { id: cur.id, count: cur.count * count } }), ITEM_CHANGE_REASON.RECYCLE_SOUL);
|
||
|
||
return resResult(STATUS.SUCCESS, {
|
||
goodsId, count,
|
||
goods
|
||
});
|
||
}
|
||
|
||
|
||
/**
|
||
* 将魂一键回收
|
||
* @param msg
|
||
* @param session
|
||
* @returns
|
||
*/
|
||
async recycleSoulFast(msg: { recycleSoulFastPara: recycleSoulFastPara[] }, session: BackendSession) {
|
||
let roleId = session.get('roleId');
|
||
let roleName = session.get('roleName');
|
||
let sid = session.get('sid');
|
||
|
||
let { recycleSoulFastPara } = msg;
|
||
// 检测参数,防止hid重复
|
||
let checkHid = new Map<number, number>();
|
||
for (let { hid, count } of recycleSoulFastPara) {
|
||
if (checkHid.get(hid)) return resResult(STATUS.WRONG_PARMS);
|
||
checkHid.set(hid, 1);
|
||
}
|
||
|
||
// 从db获取所有武将数据
|
||
const dbHeros = await HeroModel.findByHidsAndRole(roleId, recycleSoulFastPara.map(obj => obj.hid)) as HeroType[];
|
||
let heroesMap = new Map<number, HeroType>();
|
||
let items = []
|
||
for (const val of dbHeros) {
|
||
let hid = val.hid
|
||
heroesMap.set(hid, val);
|
||
|
||
let dicHero = gameData.hero.get(hid);
|
||
if (!dicHero || !dicHero.pieceId) continue;
|
||
items.push(dicHero.pieceId);
|
||
}
|
||
// 从db获取相关碎片道具数据
|
||
if (!items || items.length == 0) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH);
|
||
const dbItems = await ItemModel.findbyRoleAndIds(roleId, items);
|
||
if (!dbItems || dbItems.length == 0) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH);
|
||
const itemsMap = arrToMap(dbItems, obj => obj.id);
|
||
|
||
let allAddItem = [];
|
||
let allCostItem = [];
|
||
for (let { hid, count } of recycleSoulFastPara) {
|
||
let residueFragment = 0;
|
||
let goodsId = gameData.hero.get(hid)?.pieceId || 0;
|
||
const curItemCount = itemsMap.get(goodsId)?.count || 0;
|
||
if (curItemCount <= 0) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH);
|
||
|
||
let hero = heroesMap.get(hid);
|
||
if (!hero) return resResult(STATUS.HERO_IS_HIDDEN);
|
||
|
||
if (hero.colorStar != HERO_GROW_MAX.COLORSTAR) {
|
||
residueFragment = await calUpSixColorsResidueFragment(roleId, hero, hid, curItemCount);
|
||
if (!residueFragment || count > residueFragment) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH);
|
||
}
|
||
|
||
allCostItem.push({ id: goodsId, count: count });
|
||
|
||
let dicGoods = gameData.goods.get(goodsId);
|
||
if (!dicGoods) return resResult(STATUS.DIC_DATA_NOT_FOUND)
|
||
|
||
let reward: RewardInter[] = [];
|
||
switch (dicGoods.quality) {
|
||
case HERO_QUALITY_TYPE.BLUE:
|
||
reward = parseGoodStr(SHOP.HERO_SOUL_BULE); break;
|
||
case HERO_QUALITY_TYPE.PURPLE:
|
||
reward = parseGoodStr(SHOP.HERO_SOUL_PURPLE); break;
|
||
case HERO_QUALITY_TYPE.GOLD:
|
||
reward = parseGoodStr(SHOP.HERO_SOUL_GOLDEN); break;
|
||
case HERO_QUALITY_TYPE.UR:
|
||
reward = parseGoodStr(SHOP.HERO_SOUL_UR); break;
|
||
}
|
||
allAddItem.push(...reward.map(cur => { return { id: cur.id, count: cur.count * count } }));
|
||
}
|
||
|
||
let costResult = await handleCost(roleId, sid, allCostItem, ITEM_CHANGE_REASON.RECYCLE_SOUL);
|
||
if (!costResult) return resResult(STATUS.BATTLE_CONSUMES_NOT_ENOUGH);
|
||
// 增加货币
|
||
let goods = await addItems(roleId, roleName, sid, allAddItem, ITEM_CHANGE_REASON.RECYCLE_SOUL);
|
||
|
||
return resResult(STATUS.SUCCESS, { goods });
|
||
}
|
||
|
||
|
||
|
||
// !测试接口。 去除限购次数
|
||
async debugClearPurchaseLimit(msg: {}, session: BackendSession) {
|
||
let roleId = session.get('roleId');
|
||
|
||
await UserShopModel.deleteAccount(roleId);
|
||
return resResult(STATUS.SUCCESS);
|
||
}
|
||
} |