Files
ZYZ/game-server/app/services/role/rewardService.ts
T

806 lines
33 KiB
TypeScript

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);
for(let activity of activities) {
let activityData = getActivityData(activity, createTime, serverTime);
if(!activityData || !activityData.canShow()) continue;
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;
}
export function getRougeTechScoreObject(count: number) {
return { id: CURRENCY_BY_TYPE.get(CURRENCY_TYPE.ROUGE_TECH)||0, count };
}
/**
* 返回 解锁头像/相框
* @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) {
// }
// }