Files
ZYZ/game-server/app/services/role/rewardService.ts
2023-04-11 17:58:24 +08:00

802 lines
33 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { ITID, CONSUME_TYPE, ITEM_TABLE, CURRENCY_TYPE, MAIL_TYPE, HANDLE_REWARD_TYPE, HERO_SYSTEM_TYPE, CURRENCY_BY_TYPE, ITEM_CHANGE_REASON, TA_USERSET_TYPE, TA_EVENT, POP_UP_SHOP_CONDITION_TYPE, ROLE_SELECT, FIGURE_UNLOCK_CONDITION, PUSH_ROUTE, ACTIVITY_TYPE } from '../../consts';
import { getDecimalCnt, getRandEelm, getRandEelmWithWeight, getRandValueByMinMax, } from '../../pubUtils/util';
import { RoleModel, RoleType } from '../../db/Role';
import { setAp } from '../actionPointService';
import { ItemModel, } from '../../db/Item';
import { ItemInter, } from '../../pubUtils/interface';
import { gameData, getDefArtifactByGid } from '../../pubUtils/data';
import { uniq } from 'underscore';
import { EPlace, HeroModel, HeroType, } from '../../db/Hero';
import { Figure } from '../../domain/dbGeneral';
import { ArtifactParam, JewelParam } from '../../domain/roleField/hero';
import { HeroSkin } from '../../db/Hero';
import { BAG } from '../../pubUtils/dicParam';
import { sendMailByContent } from '../mailService';
import { SkinModel, } from '../../db/Skin';
import { reportTAEvent, reportTAUserSet } from '../sdkService';
import { saveCoinChangeLog, saveFigureInfoLog, saveGoldChangeLog, saveItemChangeLog } from '../../pubUtils/logUtil';
import { JewelModel, JewelType, jewelUpdate, RandSe } from '../../db/Jewel';
import { updateEplaces } from '../equipService';
import { combineItems, getCoinEventProperties, getGoldEventProperties, sortItems } from './util';
import { nowSeconds } from '../../pubUtils/timeUtil';
import { calculateCeWithHero, calculateCeWithRole } from '../playerCeService';
import { sendMessageToUserWithSuc } from '../pushService';
import { filterGoods } from '../dataService';
import { ArtifactModel, ArtifactModelType, ArtifactModelUpdate } from '../../db/Artifact';
import { ActivityItemModel } from '../../db/ActivityItem';
import { getActivitiesByType } from '../activity/activityService';
import { ActivityModelType } from '../../db/Activity';
import { ForgeData } from '../../domain/activityField/forgeField';
import { getRoleCreateTime, getServerCreateTime } from '../redisService';
export async function handleCost(roleId: string, sid: string, goods: Array<ItemInter>, reason: ITEM_CHANGE_REASON) {
let { items, jewels, gold, coin, artifacts, activityItems } = sortItems(goods, HANDLE_REWARD_TYPE.COST);
let jewelSeqIds = jewels.map(cur => cur.seqId);
let resJewels: JewelType[] = [];
let artifactSeqIds = artifacts.map(cur => cur.seqId);
let resArtifacts: ArtifactModelType[] = [];
// 检查货币是否充足
let role = await RoleModel.findByRoleId(roleId);
if (gold.length > 0 || coin.length > 0) {
let { gold: originGold, coin: originCoin } = role;
for(let {count} of gold) { originGold -= count };
for(let count of coin) { originCoin -= count };
if(originGold < 0 || originCoin < 0) return false;
}
//检查装备是否存在
if (jewels.length > 0) {
resJewels = await JewelModel.findbySeqIds(jewelSeqIds);
if (resJewels.length < jewels.length)
return false;
}
//检查宝物是否存在
if (artifacts.length > 0) {
resArtifacts = await ArtifactModel.findbySeqIds(roleId, artifactSeqIds);
if (resArtifacts.length < artifacts.length)
return false;
}
//检查并修改道具
if (items.length > 0) {
let { hasError, result } = await ItemModel.decreaseItems(roleId, items);
if (hasError) return false;
sendMessageToUserWithSuc(roleId, PUSH_ROUTE.ITEM_UPDATE, { goods: result.map(cur => ({...cur, reason })) }, sid);
saveItemChangeLog(roleId, result, reason);
}
//检查并修改道具
if (activityItems.length > 0) {
let { hasError, result } = await ActivityItemModel.decreaseActivityItems(roleId, activityItems);
if (hasError) return false;
sendMessageToUserWithSuc(roleId, PUSH_ROUTE.ACTIVITY_ITEM_UPDATE, { goods: result.map(cur => ({...cur, reason })) }, sid);
saveItemChangeLog(roleId, result, reason);
}
//删除装备
if (resJewels.length > 0) {
let heroMap = new Map<number, { hero: HeroType, jewels: JewelType[]}>();
for(let jewel of resJewels) {
if(jewel.hid > 0) {
if(!heroMap.has(jewel.hid)) {
let hero = await HeroModel.findByHidAndRole(jewel.hid, roleId);
heroMap.set(jewel.hid, { hero, jewels: [] });
}
heroMap.get(jewel.hid).jewels.push(jewel);
}
}
for(let [hid, {hero, jewels} ] of heroMap) {
// 脱下天晶石
let update = new Map<number, Partial<EPlace>>();
for(let jewel of jewels) {
await JewelModel.putOnOrOff(jewel.id, 0, 0);
let curEquip = hero.ePlace.find(cur => cur.jewel == jewel.id);
if(!!curEquip) {
update.set(curEquip.id, { jewel: 0 });
}
}
let { newEplace } = updateEplaces(hero.ePlace, update);
await calculateCeWithHero(HERO_SYSTEM_TYPE.EQUIP_STRENGTH, roleId, role.serverId, sid, hid, { ePlace: newEplace }, { ePlaceIds: [...update.keys()] });
}
let jewels = await JewelModel.deleteBySeqIds(roleId, jewelSeqIds);
saveItemChangeLog(roleId, jewels.map(jewel => ({ id: jewel.id, count: 1, inc: -1 })), reason);
sendMessageToUserWithSuc(roleId, PUSH_ROUTE.JEWEL_DEL, { jewels: jewels.map(jewel => ({ seqId: jewel.seqId, id: jewel.id, inc: -1, reason })) }, sid);
}
//删除宝物
if (resArtifacts.length > 0) {
let heroMap = new Map<number, { artifact: ArtifactModelType}>();
for(let artifact of resArtifacts) {
if(artifact.hid > 0) {
heroMap.set(artifact.hid, { artifact });
}
}
for(let [hid, { artifact } ] of heroMap) {
// 脱下天晶石
await ArtifactModel.putOnOrOff(roleId, artifact.id, 0);
await calculateCeWithHero(HERO_SYSTEM_TYPE.PUT_ARTIFACT, roleId, role.serverId, sid, hid, { artifact: 0 });
}
let artifacts = await ArtifactModel.deleteBySeqIds(roleId, artifactSeqIds);
saveItemChangeLog(roleId, artifacts.map(artifact => ({ id: artifact.id, count: 1, inc: -1 })), reason);
sendMessageToUserWithSuc(roleId, PUSH_ROUTE.ARTIFACT_DEL, { artifacts: artifacts.map(artifact => ({ seqId: artifact.seqId, id: artifact.id, inc: -1, reason })) }, sid);
}
//消耗玩家货币
if (gold.length > 0 || coin.length > 0) {
let costGold = gold.reduce((pre, cur) => pre + cur.count, 0);
let costCoin = coin.reduce((pre, cur) => pre + cur, 0);
role = await RoleModel.decreaseGoldAndCoin(roleId, gold, costCoin);
sendMessageToUserWithSuc(roleId, PUSH_ROUTE.PLAYER_DATA_CHANGE, { gold: role.gold, coin: role.coin, totalCost: role.totalCost }, sid);
if(costGold > 0) {
reportTAEvent(roleId, TA_EVENT.ITEM_CONSUME, getGoldEventProperties(costGold, role.gold, reason));
reportTAUserSet(TA_USERSET_TYPE.SET, roleId, { current_gold: role.gold });
saveGoldChangeLog(roleId, role.gold, -1 * costGold, reason);
}
if(costCoin > 0) {
reportTAEvent(roleId, TA_EVENT.ITEM_CONSUME, getCoinEventProperties(costCoin, role.coin, reason));
reportTAUserSet(TA_USERSET_TYPE.SET, roleId, { current_coin: role.coin });
saveCoinChangeLog(roleId, role.coin, -1 * costCoin, reason);
}
}
return true;
}
export async function addItems(roleId: string, roleName: string, sid: string, goods: Array<ItemInter>, reason: ITEM_CHANGE_REASON) {
goods = filterGoods(goods, obj => obj.id, roleId, reason);
let { items, jewels, gold, coin, ap, skins, figures, artifacts, activityItems } = sortItems(goods, HANDLE_REWARD_TYPE.RECEIVE);
let showItems: { id: number, seqId?: number|string, count: number, isBag?: boolean, expireTime?: number }[] = [];
let role = await RoleModel.findByRoleId(roleId, '-warCount -topLineup');
// 1. 装备处理
if(jewels.length > 0) {
let { jewelCount = 0 } = role;
let incJewels = jewels, mailJewels: { id?: number, hid?: number, seqId?: number }[] = [];
if(jewels.length + jewelCount > BAG.BAG_EQUIP_UPLIMITED) { // 装备上限
let inc = BAG.BAG_EQUIP_UPLIMITED - jewelCount;
if(inc < 0) inc = 0;
incJewels = jewels.slice(0, inc);
mailJewels = jewels.slice(inc);
}
// 直接加的
let { jewels: jewelInfos } = await addJewels(roleId, roleName, <{id: number }[]>incJewels, reason);
for (let jewel of jewelInfos) {
showItems.push({ seqId: jewel.seqId, id: jewel.id, count: 1, isBag: true });
}
for(let jewel of combineItems(mailJewels)) {
showItems.push({ id: jewel.id, count: jewel.count, isBag: false });
}
//装备推送
if (!!jewelInfos.length)
sendMessageToUserWithSuc(roleId, PUSH_ROUTE.JEWEL_ADD, { jewelInfos }, sid);
//统计装备
if (jewelInfos.length > 0) {
saveItemChangeLog(roleId, jewelInfos, reason);
}
// 发邮件的
if(mailJewels.length > 0) {
await sendMailByContent(MAIL_TYPE.EQUIP_OVER, roleId, { goods: combineItems(mailJewels) });
}
}
// 2. 道具处理
if(items.length > 0) {
let { items: itemInfos } = await addBags(roleId, roleName, items, reason);
for (let item of items) {
showItems.push({ id: item.id, count: item.count });
}
//背包除去装备推送
if (!!itemInfos.length) {
sendMessageToUserWithSuc(roleId, PUSH_ROUTE.ITEM_UPDATE, { goods: itemInfos }, sid);
saveItemChangeLog(roleId, itemInfos, reason);
}
}
// 3. 货币推送
if(gold.length > 0 || coin.length > 0 || ap > 0) {
await setAp(role.serverId, roleId, null, role.lv, ap, sid, reason);
let incCoin = coin.reduce((pre, cur) => pre + cur, 0);
let incGold = gold.reduce((pre, cur) => pre + cur.count, 0);
role = await RoleModel.increaseGoldAndCoin(roleId, gold, incCoin);
sendMessageToUserWithSuc(roleId, PUSH_ROUTE.PLAYER_DATA_CHANGE, { gold: role.gold, coin: role.coin }, sid);
if(gold.length > 0) {
gold.forEach(({ count }) => {
showItems.push(getGoldObject(count));
});
reportTAEvent(roleId, TA_EVENT.ITEM_GET, getGoldEventProperties(incGold, role.gold, reason));
reportTAUserSet(TA_USERSET_TYPE.SET, roleId, { current_gold: role.gold });
saveGoldChangeLog(roleId, role.gold, incGold, reason );
}
if(coin.length > 0) {
coin.forEach(count => {
showItems.push(getCoinObject(count));
});
reportTAEvent(roleId, TA_EVENT.ITEM_GET, getCoinEventProperties(incCoin, role.coin, reason));
reportTAUserSet(TA_USERSET_TYPE.SET, roleId, { current_coin: role.coin });
saveCoinChangeLog(roleId, role.coin, incCoin, reason);
}
if(ap > 0) {
showItems.push(getApObject(ap));
}
}
// 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, count: number, inc: number, reason: number }[] = [];
let calAllHeroResult = undefined; // 全局战力变化推送
for (let skinId of skins) {//皮肤推送
let hero = await addSkin(roleId, roleName, role.serverId, sid, skinId, false);
skinInfos.push({ id: skinId, hid: hero? hero.hid: 0, count: 1, inc: 1, reason })
showItems.push({ id: skinId, count: 1 });
if(hero) heroskins.push({ skins: hero.skins, hid: hero.hid });
}
if (!!skinInfos.length) {
pushHeroSkinMsg(heroskins, skinInfos, roleId, sid); // 推送onHeroSkinChange
saveItemChangeLog(roleId, skinInfos, reason);
}
}
// 5. 获得头像和相框等
if(figures.length > 0) {
let figureInfo = await addFigure(roleId, figures, reason);
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) {
sendMessageToUserWithSuc(roleId, PUSH_ROUTE.HEAD_CHANGE, { ...figureInfo }, sid);
saveFigureInfoLog(roleId, figureInfo, reason)
}
}
// 6. 宝物处理
if(artifacts.length > 0) {
let { artifactCount = 0 } = role;
let incArtifacts = artifacts, mailArtifacts: { id?: number, seqId?: number|string }[] = [];
if(artifacts.length + artifactCount > BAG.BAG_ARTIFACT_UPLIMITED) { // 装备上限
let inc = BAG.BAG_ARTIFACT_UPLIMITED - artifactCount;
if(inc < 0) inc = 0;
incArtifacts = artifacts.slice(0, inc);
mailArtifacts = artifacts.slice(inc);
}
// 直接加的
let { artifacts: artifactInfos } = await addArtifacts(roleId, roleName, <{id: number}[]>incArtifacts, reason);
for (let artifact of artifactInfos) {
showItems.push({ seqId: artifact.seqId, id: artifact.id, count: 1, isBag: true });
}
for(let artifact of combineItems(mailArtifacts)) {
showItems.push({ id: artifact.id, count: artifact.count, isBag: false });
}
//装备推送
if (!!artifactInfos.length)
sendMessageToUserWithSuc(roleId, PUSH_ROUTE.ARTIFACT_ADD, { artifacts: artifactInfos }, sid);
//统计装备
if (artifactInfos.length > 0) {
saveItemChangeLog(roleId, artifactInfos, reason);
}
// 发邮件的
if(mailArtifacts.length > 0) {
await sendMailByContent(MAIL_TYPE.ARTIFACT_OVER, roleId, { goods: combineItems(mailArtifacts) });
}
}
// 7. 活动道具处理
if(activityItems.length > 0) {
let { items: itemInfos } = await addActivityItems(role, activityItems, reason);
for (let item of itemInfos) {
showItems.push({ id: item.id, count: item.inc, expireTime: item.expireTime });
}
//背包除去装备推送
if (!!itemInfos.length) {
sendMessageToUserWithSuc(roleId, PUSH_ROUTE.ACTIVITY_ITEM_UPDATE, { goods: itemInfos }, sid);
saveItemChangeLog(roleId, itemInfos, reason);
}
}
return showItems;
}
export async function checkGoods(roleId: string, goodIds: Array<number>) {
let jewelSeqIds: 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) {
jewelSeqIds.push(goodId);
} else if (table == ITEM_TABLE.ITEM) {
itemIds.push(goodId);
}
}
}
//检查装备是否存在
if (!!jewelSeqIds.length) {
let resJewels = await JewelModel.findbySeqIds(jewelSeqIds);
resJewels = uniq(resJewels, function (resEquip) {
return resEquip.id;
});
if (resJewels.length < jewelSeqIds.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 checkHeroes(roleId: string, hids: number[]) {
if (!!hids.length) {
let heros = await HeroModel.findByHidRange(hids, roleId);
if (heros.length < hids.length)
return false;
}
return true
}
export async function checkHeroEquips(roleId: string, quality: number) {
return await HeroModel.checkEquipByQuality(roleId, quality);
}
/**
* 解锁头像/相框
* @param roleId 玩家id
* @param conditions 解锁条件
* @param role 如果已查询过role表就直接可以使用
*/
export async function unlockFigure(sid: string, roleId: string, conditions: { type: number, paramHid?: number, paramFavourLv?: number, paramSkinId?: number, paramWinStreakNum?: number }[], role?: RoleType) {
if (!role || !role.heads || !role.frames) {
role = await RoleModel.findByRoleId(roleId, ROLE_SELECT.GET_HEADS);
}
let { figureInfo, heads, frames, spines } = unlockFigureWithoutSave(conditions, role);
role = await RoleModel.updateRoleInfo(roleId, { heads, frames, spines });
if (!!figureInfo && (figureInfo.heads.length > 0 || figureInfo.frames.length > 0 || figureInfo.spines.length > 0)) {
sendMessageToUserWithSuc(roleId, PUSH_ROUTE.HEAD_CHANGE, { ...figureInfo }, sid);
}
}
/**
* 皮肤数据变化去重、推送
* @param heroskins 推送的皮肤
* @param roleId 玩家
*/
function pushHeroSkinMsg(heroskins: {skins: HeroSkin[], hid: number}[], skinInfos: {id: number, hid: number }[], roleId: 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) {
sendMessageToUserWithSuc(roleId, PUSH_ROUTE.HERO_SKIN_CHANGE, { heros: heroskins, skins: skinInfos }, sid);
}
}
/**
* 只插入皮肤,不管那么多的
* @param roleId
* @param roleName
* @param skinId
* @returns
*/
export async function increaseSkin(roleId:string, roleName: string, skinId: number) {
let dicSkin = gameData.fashion.get(skinId);
if (!dicSkin) return false;
let skin = await SkinModel.increaseSkin(roleId, skinId, { roleId, roleName, id: skinId, skinName: dicSkin.name, hid: dicSkin.actorId, skinId: dicSkin.heroId });
if(!skin) return false; // 插入失败
return skin
}
/**
* 添加皮肤
* @param roleId 玩家id
* @param roleName 玩家名
* @param id 皮肤id
* @param hero 武将如果已经查询过这个武将就不用再查询一次主意要select skins字段
* @returns {{ hero, figureInfo, calAllHeroResult }} hero添加皮肤后的武将 figureInfo: 触发头像添加信息 calAllHeroResult全局战力加成后结果
*/
export async function addSkin(roleId: string, roleName: string, serverId: number, sid: string, skinId: number, enable: boolean, hero?: HeroType) {
let skin = await increaseSkin(roleId, roleName, skinId);
if(!skin) return false;
if(skin.hid && !hero) hero = await HeroModel.findByHidAndRole(skin.hid, roleId);
let condition = { type: FIGURE_UNLOCK_CONDITION.GET_SKIN, paramSkinId: skinId };
await unlockFigure(sid, roleId, [condition]); // 解锁头像
await calculateCeWithRole(HERO_SYSTEM_TYPE.ADD_SKIN, roleId, serverId, sid, {}, { skinId }); // 全局加成
if (hero) { // 有武将的,将皮肤链接到武将上
let curSkin = hero.skins.find(cur => cur.id == skinId);
if (!curSkin) {
hero.skins.push(new HeroSkin(skin, enable));
await HeroModel.updateHeroInfo(roleId, hero.hid, hero);
}
return hero;
} else {
return null
}
}
export async function addBags(roleId: string, roleName: string, datas: { id: number, count: number }[], reason: number) {
let items: { id: number, count: number, inc: number }[] = [];
for(let data of datas) {
let item = await addBag(roleId, roleName, data, reason);
items.push(item)
}
return { items }
}
export async function addBag(roleId: string, roleName: string, data: { id: number, count: number }, reason: number) {
let { id, count } = data;
let { name: itemName, itid, hid } = gameData.goods.get(id);
let { type } = ITID.get(itid);
let item = await ItemModel.increaseItem(roleId, id, count, { roleId, roleName, itemName, id, type, hid });
return { id: item.id, count: item.count, inc: count, reason };
}
export async function addActivityItems(role: RoleType, datas: { id: number, count: number }[], reason: number) {
let serverTime = await getServerCreateTime(role.serverId);
let createTime = await getRoleCreateTime(role.roleId, role);
let items: { id: number, count: number, inc: number, expireTime: number }[] = [];
for(let data of datas) {
let item = await addActivityItem(role.serverId, role.roleId, role.roleName, data, reason, createTime, serverTime);
if(item) items.push(item)
}
return { items }
}
export async function addActivityItem(serverId: number, roleId: string, roleName: string, data: { id: number, count: number }, reason: number, createTime: number, serverTime: number) {
let { id, count } = data;
let { name: itemName, activityType } = gameData.goods.get(id);
let activities = await getActivitiesByType(serverId, activityType);
if(activities.length > 0) {
let activityData = getActivityData(activities[0], createTime, serverTime);
if(!activityData || !activityData.canShow()) return null;
let item = await ActivityItemModel.increaseActivityItem(roleId, id, count, { roleId, roleName, itemName, id, expireTime: Math.floor(activityData.nextRefreshTime/1000) });
return { id: item.id, count: item.count, inc: count, expireTime: item.expireTime, reason };
}
}
function getActivityData(activity: ActivityModelType, createTime: number, serverTime: number) {
switch(activity.type) {
case ACTIVITY_TYPE.FORGE:
return new ForgeData(activity, createTime, serverTime)
default:
return null
}
}
export async function addJewels(roleId: string, roleName: string, jewels: { id: number, }[], reason: number) {
let jewelInfo: jewelUpdate[] = [];
for(let jewel of jewels) {
let info = await getAddJewelInfo(roleId, roleName, jewel);
jewelInfo.push(info);
}
const jewelResult = await JewelModel.createJewels(roleId, jewelInfo);
return { jewels: jewelResult.map(jewel => new JewelParam(jewel, true, reason))}
}
export async function getAddJewelInfo(roleId: string, roleName: string, jewel: { id: number, }) {
let { id, } = jewel;
let { name, randomEffect, effectCount, rareEffect } = gameData.jewel.get(id);
// 随机属性
let randomResult: number[] = getRandEelm(randomEffect, effectCount);
let rareResult: number[] = getRandEelm(rareEffect, 1);
let randSe: Array<RandSe> = randomResult.map((id: number, index: number) => {
return getJewelRandSe(index + 1, id);
});
let rareSe: Array<RandSe> = rareResult.map((id: number, index: number) => {
return getJewelRandSe(index + 1, id);
});
return { roleId, roleName, id, name, randSe, rareSe };
}
/**
* 天晶石已知词条随机值
* @param id 词条位置,第几条
* @param seid 词条id
* @returns
*/
export function getJewelRandSe(id: number, seid: number) {
let dicRandom = gameData.randomEffectPool.get(seid)
// console.log('#### dicRandom', dicRandom)
let rand = 0;
let planPool = gameData.randomEffectPoolPlan.get(dicRandom.planId);
if(planPool && planPool.length > 0) {
let result = getRandEelmWithWeight(planPool);
if(result) rand = Math.round(result.dic.num * 100)/100;
} else {
let randResult = getRandValueByMinMax(dicRandom.Min, dicRandom.Max, getDecimalCnt(dicRandom.gap));
let n = Math.floor((randResult - dicRandom.Min)/dicRandom.gap);
rand = Math.round(dicRandom.Min + n * dicRandom.gap * 100)/100;
}
return new RandSe(id, dicRandom.id, rand);
}
export async function addArtifacts(roleId: string, roleName: string, artifacts: { id: number, }[], reason: number) {
let artifactInfos: ArtifactModelUpdate[] = [];
for(let { id } of artifacts) {
let dicArtifact = getDefArtifactByGid(id);
if(dicArtifact) {
let { goodId, artifactId, quality, qualityStage } = dicArtifact;
artifactInfos.push({ roleId, roleName, id: goodId, artifactId, quality, qualityStage });
}
}
const artifactResult = await ArtifactModel.createArtifacts(roleId, artifactInfos);
return { artifacts: artifactResult.map(artifact => new ArtifactParam(artifact, true, reason))}
}
export function getGoldId() {
return CURRENCY_BY_TYPE.get(CURRENCY_TYPE.GOLD);
}
/**
* @description 获取元宝物品 { id, count }
* @param count 元宝数量
*/
export function getGoldObject(count: number) {
return { id: CURRENCY_BY_TYPE.get(CURRENCY_TYPE.GOLD), count };
}
/**
* @description 获取金币物品 { id, count }
* @param count 元宝数量
*/
export function getCoinObject(count: number) {
return { id: CURRENCY_BY_TYPE.get(CURRENCY_TYPE.COIN), count };
}
/**
* @description 获取体力物品 { id, count }
* @param count 体力数量
*/
export function getApObject(count: number) {
return { id: CURRENCY_BY_TYPE.get(CURRENCY_TYPE.ACTION_POINT), count };
}
/**
* @description 获取友情点物品 { id, count }
* @param count 友情点数量
*/
export function getFriendPointObject(count: number) {
return { id: CURRENCY_BY_TYPE.get(CURRENCY_TYPE.FRIEND_POINT), count };
}
/**
* @description 获取功勋物品 { id, count }
* @param count 功勋数量
*/
export function getHonourObject(count: number) {
return { id: CURRENCY_BY_TYPE.get(CURRENCY_TYPE.HONOUR), count };
}
/**
* @description 获取代金券物品 { id, count }
* @param count 元宝数量
*/
export function getVoucherObject(count: number) {
return { id: CURRENCY_BY_TYPE.get(CURRENCY_TYPE.VOUCHER), count };
}
export function getVoucherCoinObject(count: number) {
return { id: CURRENCY_BY_TYPE.get(CURRENCY_TYPE.VOUCHER_COIN), count };
}
export function checkVoucherId(id: number) {
let voucher = CURRENCY_BY_TYPE.get(CURRENCY_TYPE.VOUCHER);
let voucherCoin = CURRENCY_BY_TYPE.get(CURRENCY_TYPE.VOUCHER_COIN);
return id == voucher || id == voucherCoin;
}
/**
* 返回 解锁头像/相框
* @param conditions 解锁条件
* @param role 如果已查询过role表就直接可以使用
*/
export function unlockFigureWithoutSave(conditions: { type: number, paramHid?: number, paramFavourLv?: number, paramSkinId?: number, paramWinStreakNum?: number }[], role: RoleType) {
let { heads, frames, spines, roleId } = role;
let figureInfo = { heads: new Array<Figure>(), frames: new Array<Figure>(), spines: new Array<Figure>() };
for (let { type, paramHid, paramFavourLv, paramSkinId, paramWinStreakNum } of conditions) {
let canUnLockList = gameData.figureCondition.get(type);
if (canUnLockList) {
canUnLockList = filterGoods(canUnLockList, obj => obj.gid, roleId, ITEM_CHANGE_REASON.GET_HERO_UNLOCK_FIGURE);
let reason = 0;
for (let { id, params, gid } of canUnLockList) {
let flag = false; // 是否达成条件
if (type == FIGURE_UNLOCK_CONDITION.GET_HERO) {
let [hid] = params;
if (paramHid == hid) flag = true;
reason = ITEM_CHANGE_REASON.GET_HERO_UNLOCK_FIGURE;
} else if (type == FIGURE_UNLOCK_CONDITION.HERO_FAVOR) {
let [hid, favourLv] = params;
if (paramHid == hid && paramFavourLv >= favourLv) flag = true;
reason = ITEM_CHANGE_REASON.HERO_FAVOR_UNLOCK_FIGURE;
} else if (type == FIGURE_UNLOCK_CONDITION.GET_SKIN) {
let [id] = params;
if (paramSkinId == id) flag = true;
reason = ITEM_CHANGE_REASON.ADD_SKIN_UNLOCK_FIGURE;
} else if (type == FIGURE_UNLOCK_CONDITION.PVP_WIN_SERIES) {
let [winStreakNum] = params;
if (paramWinStreakNum >= winStreakNum) flag = true;
reason = ITEM_CHANGE_REASON.PVP_SERIES_UNLOCK_FIGURE;
}
if (!flag) continue;
let dicGood = gameData.goods.get(gid);
if (!dicGood) continue;
let dicItid = ITID.get(dicGood.itid);
if (!dicItid) continue;
if (dicItid.type == CONSUME_TYPE.HEAD) {
let figure = unlockSingleFigure(heads, gid, reason, false, id);
if (figure && figure.unlocked) figureInfo.heads.push(figure);
} else if (dicItid.type == CONSUME_TYPE.FRAME) {
let figure = unlockSingleFigure(frames, gid, reason, false, id);
if (figure && figure.unlocked) figureInfo.frames.push(figure);
} else if (dicItid.type == CONSUME_TYPE.SPINE) {
let figure = unlockSingleFigure(spines, gid, reason, false, id);
if (figure && figure.unlocked) figureInfo.spines.push(figure);
} else {
continue;
}
}
}
}
return { figureInfo, heads, frames, spines };
}
// 直接获得形象/相框
export async function addFigure(roleId: string, ids: number[], reason: number) {
let role = await RoleModel.findByRoleId(roleId, ROLE_SELECT.GET_HEADS);
if (!role) return false;
let { heads, frames, spines } = role;
let figureInfo = { heads: [], frames: [], spines: [] };
for (let gid of ids) {
let dicGoods = gameData.goods.get(gid);
if (!dicGoods) continue;
let dicItid = ITID.get(dicGoods.itid);
if (!dicItid) continue;
if (dicItid.type == CONSUME_TYPE.HEAD) {
let figure = unlockSingleFigure(heads, gid, reason, true);
if (figure && figure.unlocked) figureInfo.heads.push(figure);
} else if (dicItid.type == CONSUME_TYPE.FRAME) {
let figure = unlockSingleFigure(frames, gid, reason, true);
if (figure && figure.unlocked) figureInfo.frames.push(figure);
} else if (dicItid.type == CONSUME_TYPE.SPINE) {
let figure = unlockSingleFigure(spines, gid, reason, true);
if (figure && figure.unlocked) figureInfo.spines.push(figure);
} else {
continue;
}
}
role = await RoleModel.updateRoleInfo(roleId, { heads, frames, spines });
return figureInfo;
}
/**
* 根据物品id解锁/获得玩家数据
* @param dbFigures 数据库内字段
* @param id 物品id
* @param unlockDirect 是否不计算解锁条件直接解锁
* @param conditionId 条件id
*/
function unlockSingleFigure(dbFigures: Figure[], id: number, reason: number, unlockDirect = false, conditionId?: number) {
let index = dbFigures.findIndex(cur => cur.id == id);
let figure = dbFigures[index];
if (index == -1) {
figure = new Figure(id, false);
dbFigures.push(figure);
index = dbFigures.length - 1;
}
if (figure.unlocked) return; // 已解锁过
if (!figure.unlockedId) figure.unlockedId = new Array<number>();
let dicGoods = gameData.goods.get(id);
let hasUnlockedAll = true;
if (!unlockDirect) { // 不能直接获得需要通过type解锁
if (figure.unlockedId.includes(conditionId)) return;
figure.unlockedId.push(conditionId);
for (let { id: cid } of dicGoods.condition) {
if (!figure.unlockedId.includes(cid)) {
hasUnlockedAll = false; break;
}
}
}
if (hasUnlockedAll) {
figure.unlocked = true;
delete figure.unlockedId;
if (dicGoods.timeLimit) {
figure.time = nowSeconds() + dicGoods.timeLimit * 86400
}
}
figure.inc = 1;
figure.reason = reason;
dbFigures[index] = figure;
return figure
}
// async function getSkinsOfThisHero(roleId: string, roleName: string, hid: number, initialSkin: number, allSkins?: SkinType[]) {
// if(!allSkins) allSkins = await SkinModel.findbyRoleAndHid(roleId, hid);
// let skin = await increaseSkin(roleId, roleName, initialSkin);
// if(skin) allSkins.push(skin);
// let skins: { id: number, skin: string, enable: boolean }[] = [];
// for(let skin of allSkins) {
// skins.push({ id: skin.id, skin: skin._id, enable: skin.id == initialSkin });
// }
// return skins
// }
export function combineFigureInfo(figureInfos: { heads: Figure[], frames: Figure[], spines: Figure[] }[]) {
let figureInfo = { heads: new Array<Figure>(), frames: new Array<Figure>(), spines: new Array<Figure>() };
for(let {heads, frames, spines} of figureInfos) {
for(let head of heads) {
figureInfo.heads.push(head);
}
for(let frame of frames) {
figureInfo.frames.push(frame);
}
for(let spine of spines) {
figureInfo.spines.push(spine);
}
}
return figureInfo;
}
// export class CreateHero {
// roleId: string;
// roleName: string;
// serverId: number;
// constructor(roleId: string, roleName: string, serverId: number) {
// }
// }