523 lines
23 KiB
TypeScript
523 lines
23 KiB
TypeScript
import { BackendSession } from "pinus";
|
||
import { GVG_ACTIVE_TYPE, GVG_ITEM, GVG_PERIOD, GVG_RESOURCE_TYPE, GVG_SEED_TYPE, GVG_TECH_TYPE, ITEM_CHANGE_REASON, LEAGUE_JOB, MAIL_TYPE, PUSH_ROUTE } from "../../consts";
|
||
import { GVGLeagueFarmModel, GVGLeagueFarmType } from "../../db/GVGLeagueFarm";
|
||
import { GVGLeaguePrepareModel, Tech } from "../../db/GVGLeaguePrepare";
|
||
import { GVGUserDailyDataModel, GVGUserDailyDataType } from "../../db/GVGUserDailyData";
|
||
import { Contribute, GVGUserDataModel } from "../../db/GVGUserData";
|
||
import { GVGUserItemModel } from "../../db/GVGUserItem";
|
||
import { LeagueField } from "../../domain/gvgField/returnData";
|
||
import { calLeagueLv, gameData, getFieldMaxAddType } from "../../pubUtils/data";
|
||
import { GVG } from "../../pubUtils/dicParam";
|
||
import { RewardInter } from "../../pubUtils/interface";
|
||
import { nowSeconds } from "../../pubUtils/timeUtil";
|
||
import { arrToMap, getArrayOfNumber, getRandEelm, decodeIdCntArrayStr, parseGoodStr, sortArrRandom } from "../../pubUtils/util";
|
||
import { addGVGReward, combinePushItem, getProduceCoinCnt } from "./gvgItemService";
|
||
import { getGVGConfig, getGVGPeriodData } from "./gvgService";
|
||
import { GVGVestigeRankModel } from "../../db/GVGVestigeRank";
|
||
import { addLeagueLvUpMessage, addResourceRecord } from "./gvgRecService";
|
||
import { GVGLeagueType } from "../../db/GVGLeague";
|
||
import { sendMessageToGuildWithSuc, sendMessageToUserWithSuc } from "../pushService";
|
||
import { sendMailByContent } from "../mailService";
|
||
|
||
export function checkPreTech(techId: number, activeQueue: number[], techQueue: Tech[]) {
|
||
const dicTech = gameData.gvgTech.get(techId);
|
||
if(!dicTech) return false;
|
||
|
||
let hasOrUnlock = dicTech.prepositionId.length == 0;
|
||
for(let andArr of dicTech.prepositionId) { // or关系
|
||
let hasAndUnlock = true;
|
||
for(let id of andArr) { // and关系
|
||
if(!checkTechIsIng(id, activeQueue, techQueue)) {
|
||
hasAndUnlock = false; break;
|
||
}
|
||
}
|
||
if(hasAndUnlock) hasOrUnlock = true;
|
||
}
|
||
return hasOrUnlock;
|
||
}
|
||
|
||
export function checkTechIsIng(techId: number, activeQueue: number[], techQueue: Tech[]) {
|
||
return techQueue.findIndex(cur => cur.id == techId) != -1 || activeQueue.indexOf(techId) != -1
|
||
}
|
||
|
||
export function checkTechProgress(techId: number, techQueue: Tech[]) {
|
||
let queue = techQueue.find(cur => cur.id == techId);
|
||
return queue && queue.progress == 0;
|
||
}
|
||
|
||
export function calProducerContribute(obj: { food: number, mineral: number, wood: number }) {
|
||
let { food = 0, mineral = 0, wood = 0 } = obj||{};
|
||
let ratio = decodeIdCntArrayStr(GVG.GVG_PRODUCE_GAME_RATIO, 1);
|
||
let foodRatio = ratio.get(GVG_RESOURCE_TYPE.FOOD.toString())||0;
|
||
let mineralRatio = ratio.get(GVG_RESOURCE_TYPE.MINERAL.toString())||0;
|
||
let woodRatio = ratio.get(GVG_RESOURCE_TYPE.WOOD.toString())||0;
|
||
return food * foodRatio + mineral * mineralRatio + wood * woodRatio;
|
||
}
|
||
|
||
export function calFighterContribute(obj: { score: number }) {
|
||
return obj?.score||0
|
||
}
|
||
|
||
export async function getGVGActive(leagueCode: string, roleId: string) {
|
||
let { configId } = getGVGConfig();
|
||
let result = await GVGUserDataModel.findByRole(configId, leagueCode, roleId);
|
||
return result?.active||0;
|
||
}
|
||
|
||
/**
|
||
* 获得活跃
|
||
* @param leagueCode
|
||
* @param roleId
|
||
* @param type GVG_ACTIVE_TYPE
|
||
* @returns
|
||
*/
|
||
export async function addGVGActive(leagueCode: string, roleId: string, type: GVG_ACTIVE_TYPE, count = 1) {
|
||
let { configId } = getGVGConfig();
|
||
|
||
let add = gameData.gvgActive.get(type)||0;
|
||
let result = await GVGUserDataModel.addActive(configId, leagueCode, roleId, type, add * count);
|
||
return result.active;
|
||
}
|
||
|
||
export async function addGVGTechActive(leagueCode: string, roleId: string) {
|
||
let { configId } = getGVGConfig();
|
||
let check = await GVGUserDailyDataModel.checkGetTechActive(configId, leagueCode, roleId);
|
||
if(!check) {
|
||
await GVGUserDailyDataModel.setHasGetTechActive(configId, leagueCode, roleId);
|
||
return await addGVGActive(leagueCode, roleId, GVG_ACTIVE_TYPE.TECH_ACTIVATE);
|
||
} else {
|
||
const data = await GVGUserDataModel.findByRole(configId, leagueCode, roleId);
|
||
return data?.active||0;
|
||
}
|
||
}
|
||
|
||
export function getGVGDailyItems(job: number) {
|
||
return job == LEAGUE_JOB.PRODUCER? parseGoodStr(GVG.GVG_PRODUCER_GET): parseGoodStr(GVG.GVG_FIGHTER_GET);
|
||
}
|
||
|
||
export async function getDailyLoginReward(roleId: string, roleName: string, sid: string, leagueCode: string, job: number) {
|
||
let { configId } = getGVGConfig();
|
||
if(job && !await GVGUserDailyDataModel.checkHasLogin(configId, leagueCode, roleId)) {
|
||
// 发每日奖励
|
||
await GVGUserDailyDataModel.setHasLogin(configId, leagueCode, roleId);
|
||
let leagueGoods = await addGVGReward(roleId, roleName, leagueCode, sid, getGVGDailyItems(job), [], ITEM_CHANGE_REASON.GVG_LOGIN)
|
||
let active = await addGVGActive(leagueCode, roleId, GVG_ACTIVE_TYPE.LOGIN);
|
||
return { active, reward: leagueGoods }
|
||
}
|
||
return null;
|
||
}
|
||
|
||
export function getMyContribute(userDailyData: GVGUserDailyDataType, myRanks: {vestigeId: number, rank: number}[]) {
|
||
let score = 0;
|
||
for(let { vestigeId, rank} of myRanks) {
|
||
let dicRankMap = gameData.gvgVestige.get(vestigeId);
|
||
if(dicRankMap && dicRankMap.get(rank)) score += dicRankMap.get(rank).score;
|
||
}
|
||
return {
|
||
food: userDailyData?.food||0,
|
||
mineral: userDailyData?.mineral||0,
|
||
wood: userDailyData?.wood||0,
|
||
score: userDailyData?.score||score,
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 资源
|
||
* @param leagueCode 联军id
|
||
* @param roleId 玩家id
|
||
* @param resourceType 资源类型
|
||
* @param count 数量
|
||
* @returns
|
||
*/
|
||
export async function addResource(myLeague: GVGLeagueType, roleId: string, roleName: string, resourceType: GVG_RESOURCE_TYPE, count: number, sid?: string) {
|
||
let { leagueCode } = myLeague;
|
||
let { configId } = getGVGConfig();
|
||
let resources = getResourceCnt(resourceType, count);
|
||
if(!resources) return false;
|
||
let { food = 0, mineral = 0, wood = 0 } = resources;
|
||
|
||
// 联军更新资源
|
||
let league = await GVGLeaguePrepareModel.addResource(configId, leagueCode, food, mineral, wood);
|
||
let originLv = league?.lv||1;
|
||
// 联军升级
|
||
let lv = calLeagueLv(league.resources);
|
||
league = await GVGLeaguePrepareModel.setLv(configId, leagueCode, lv);
|
||
// 个人贡献更新
|
||
await GVGUserDataModel.addResource(configId, leagueCode, roleId, food, mineral, wood);
|
||
// 个人今日贡献更新
|
||
let userDailyData = await GVGUserDailyDataModel.addResource(configId, leagueCode, roleId, food, mineral, wood);
|
||
let myRanks = await GVGVestigeRankModel.findAllByRole(roleId);
|
||
|
||
let myContribute = getMyContribute(userDailyData, myRanks);
|
||
addResourceRecord(roleId, roleName, leagueCode, resourceType, count);
|
||
if(lv > originLv) addLeagueLvUpMessage(roleId, roleName, myLeague, lv);
|
||
await sendMessageToUserWithSuc(roleId, PUSH_ROUTE.GVG_CONTRIBUTE_UPDATE, { leagueCode, job: LEAGUE_JOB.PRODUCER, sumContribute: calProducerContribute(myContribute) }, sid);
|
||
|
||
return { resources: league.resources, leagueLv: league.lv, myContribute }
|
||
}
|
||
|
||
function getResourceCnt(resourceType: GVG_RESOURCE_TYPE, count: number) {
|
||
switch(resourceType) {
|
||
case GVG_RESOURCE_TYPE.FOOD:
|
||
return { food: count };
|
||
case GVG_RESOURCE_TYPE.MINERAL:
|
||
return { mineral: count };
|
||
case GVG_RESOURCE_TYPE.WOOD:
|
||
return { wood: count };
|
||
}
|
||
}
|
||
|
||
export async function lockField(leagueCode: string, roleId: string, roleName: string, farmId: number) {
|
||
let { configId } = getGVGConfig();
|
||
const produceCoinCnt = await getLockFieldCnt(leagueCode, roleId);
|
||
if(produceCoinCnt == 0) return
|
||
|
||
const leagueFarms = await GVGLeagueFarmModel.findByFarmId(configId, leagueCode, farmId);
|
||
// 查询现有的田
|
||
let { maxAddTypeCntMap, myAddTypeCntMap, allLands, myFieldCnt, myLockField } = calCntFromFarms(farmId, leagueFarms, roleId);
|
||
if(allLands.length <= 0 || myLockField >= produceCoinCnt) return; // 田数量不足 or 已经锁过了
|
||
|
||
let allAdd = calAddType(myFieldCnt, myAddTypeCntMap, maxAddTypeCntMap, produceCoinCnt - myLockField);
|
||
let randLand = sortArrRandom(getRandEelm(allLands, produceCoinCnt - myLockField));
|
||
let lands: { fieldId: number, addType: number }[] = [];
|
||
for(let fieldId of randLand) {
|
||
let addType = 0;
|
||
for(let [_addType, addCnt] of allAdd) {
|
||
if(addCnt > 0) {
|
||
addType = _addType;
|
||
allAdd.set(_addType, addCnt - 1);
|
||
break;
|
||
}
|
||
}
|
||
lands.push({ fieldId, addType });
|
||
}
|
||
// 更新田
|
||
let dicFarm = gameData.gvgResource.get(farmId);
|
||
await GVGLeagueFarmModel.lockFields(configId, leagueCode, farmId, dicFarm?.type, roleId, roleName, lands);
|
||
return await GVGLeagueFarmModel.findByFarmIdAndRoleId(configId, leagueCode, farmId, roleId);
|
||
}
|
||
|
||
function calCntFromFarms(farmId: number, leagueFarms: GVGLeagueFarmType[], roleId: string) {
|
||
let maxAddTypeCntMap = getFieldMaxAddType(farmId); // 加成田最大数量
|
||
let myAddTypeCntMap = new Map<number, number>();
|
||
let myFieldCnt = 0; // 玩家已有的田有
|
||
let myLockField = 0; // 玩家没有种只是锁住了的田
|
||
let allLands = getArrayOfNumber(gameData.gvgResource.get(farmId)?.sum??0); // 全部可使用的田
|
||
for(let leagueFarm of leagueFarms) {
|
||
// 加成
|
||
for(let {addType, roleId: addTypeRoleId} of leagueFarm.addTypes) {
|
||
maxAddTypeCntMap.set(addType, maxAddTypeCntMap.get(addType) - 1);
|
||
if(addTypeRoleId == roleId) {
|
||
if(!myAddTypeCntMap.has(addType)) myAddTypeCntMap.set(addType, 0);
|
||
myAddTypeCntMap.set(addType, myAddTypeCntMap.get(addType) + 1);
|
||
}
|
||
}
|
||
if(leagueFarm.unlockTime >= nowSeconds()) {
|
||
let index = allLands.indexOf(leagueFarm.fieldId);
|
||
if(index > -1) allLands.splice(index, 1);
|
||
}
|
||
|
||
// 玩家数据
|
||
if(leagueFarm.lockRoleId == roleId && leagueFarm.unlockTime >= nowSeconds()) {
|
||
myFieldCnt++;
|
||
if(leagueFarm.harvestTime == 0) myLockField++;
|
||
}
|
||
}
|
||
return { maxAddTypeCntMap, myAddTypeCntMap, allLands, myFieldCnt, myLockField }
|
||
}
|
||
|
||
/**
|
||
*
|
||
* @param myFieldCnt 我已种的田的数量
|
||
* @param myAddTypeCntMap 我已种的田的有加成的田分别的数量
|
||
* @param maxAddTypeCntMap 联军最多可以加成田的数量
|
||
* @param count 本次可以加的田
|
||
* @returns
|
||
*/
|
||
function calAddType(myFieldCnt: number, myAddTypeCntMap: Map<number, number>, maxAddTypeCntMap: Map<number, number>, count: number) {
|
||
let result = new Map<number, number>(); // 加成类型, 数量
|
||
|
||
for(let [addType, ratio] of gameData.gvgPlayerFieldAddType) { // 按比例加田
|
||
let maxCnt = maxAddTypeCntMap.get(addType)||0;
|
||
if(maxCnt == 0) continue;
|
||
let needCnt = Math.floor((myFieldCnt + count) * ratio / 100); // 玩家按照比例需要的加成数量
|
||
let cnt = myAddTypeCntMap.get(addType)||0; // 我当前的加成数量
|
||
let resultCnt = needCnt - cnt;
|
||
if(resultCnt < 0) resultCnt = 0;
|
||
if(resultCnt > maxCnt) resultCnt = maxCnt;
|
||
maxAddTypeCntMap.set(addType, maxAddTypeCntMap.get(addType) - resultCnt);
|
||
result.set(addType, resultCnt);
|
||
}
|
||
return result;
|
||
}
|
||
|
||
export async function rollbackUnPlantFields(cost: RewardInter[], plantResult: GVGLeagueFarmType[], session: BackendSession, leagueCode: string) {
|
||
const roleId = session.get('roleId');
|
||
const roleName = session.get('roleName');
|
||
const sid = session.get('sid');
|
||
let add: RewardInter[] = [];
|
||
for(let { id, count } of cost) add.push({ id, count });
|
||
for(let { seedType } of plantResult) {
|
||
let index = add.findIndex(({ id }) => id == getItemIdOfSeedType(seedType));
|
||
if(index != -1) {
|
||
add[index].count --;
|
||
if(add[index].count <= 0) add.splice(index);
|
||
}
|
||
}
|
||
await addGVGReward(roleId, roleName, leagueCode, sid, add, [], ITEM_CHANGE_REASON.PLANT_ROLLBACK);
|
||
return add;
|
||
}
|
||
|
||
// 计算实际消耗的种子
|
||
export function getCostSeedReward(plantResult: GVGLeagueFarmType[]) {
|
||
const reward: RewardInter[] = [], leagueReward: RewardInter[] = [];
|
||
for(let { seedType } of plantResult) {
|
||
let itemId = getItemIdOfSeedType(seedType);
|
||
let dicGVGItem = gameData.gvgItem.get(itemId);
|
||
if(!dicGVGItem) continue;
|
||
for(let { id, count } of dicGVGItem.reward) {
|
||
let rewardObj = reward.find(({ id }) => id == id);
|
||
rewardObj? rewardObj.count += count: reward.push({ id, count: count });
|
||
}
|
||
for(let { id, count } of dicGVGItem.leagueReward) {
|
||
let rewardObj = leagueReward.find(({ id }) => id == id);
|
||
rewardObj? rewardObj.count += count: leagueReward.push({ id, count: count });
|
||
}
|
||
}
|
||
return { reward, leagueReward }
|
||
}
|
||
|
||
export function getItemIdOfSeedType(seedType: GVG_SEED_TYPE) {
|
||
switch(seedType) {
|
||
case GVG_SEED_TYPE.WHEAT:
|
||
return GVG_ITEM.WHEAT;
|
||
case GVG_SEED_TYPE.CORN:
|
||
return GVG_ITEM.CORN;
|
||
case GVG_SEED_TYPE.RICE:
|
||
return GVG_ITEM.RICE;
|
||
}
|
||
}
|
||
|
||
export async function getLockFieldCnt(leagueCode: string, roleId: string) {
|
||
let { configId } = getGVGConfig();
|
||
const itemIds = [GVG_ITEM.WHEAT, GVG_ITEM.CORN, GVG_ITEM.RICE, GVG_ITEM.PRODUCE_COIN];
|
||
const items = await GVGUserItemModel.findByRoleAndIds(configId, leagueCode, roleId, itemIds);
|
||
return items.reduce((pre, cur) => pre + cur.count, 0);
|
||
}
|
||
|
||
export async function getmyContributeRank(leagueCode: string, members: { roleId: string }[], targetRoleId: string) {
|
||
let { configId } = getGVGConfig();
|
||
|
||
const roleIds = members.map(member => member.roleId);
|
||
const userDatas = await GVGUserDataModel.findByRoles(configId, leagueCode, roleIds);
|
||
userDatas.sort((a, b) => calProducerContribute(b.contribute) - calProducerContribute(a.contribute));
|
||
for(let i = 0; i < userDatas.length; i++) {
|
||
if(userDatas[i].roleId == targetRoleId) return i + 1;
|
||
}
|
||
return 0
|
||
}
|
||
|
||
export async function getLeagueFarmShowResult(leagueCode: string, roleId: string, farmId: number, needField = true) {
|
||
let { configId } = getGVGConfig();
|
||
const leagueFarms = await GVGLeagueFarmModel.findLockedByFarmId(configId, leagueCode, farmId);
|
||
if(!needField) return { farmId, count: leagueFarms.length };
|
||
|
||
const fields = await GVGLeagueFarmModel.findByFarmIdAndRoleId(configId, leagueCode, farmId, roleId);
|
||
const result = fields.map(field => new LeagueField(field));
|
||
return { farmId, count: leagueFarms.length, fields: result }
|
||
}
|
||
|
||
export function calFarmOutput(seedType: number, addType: number, farmId: number, cities: number[], activeTech: number[]) {
|
||
// 种子基础产量 * ( 1 + 格子加成 + 农庄等级加成 + 战力城池加成 + 科技树加成)
|
||
let itemId = getItemIdOfSeedType(seedType);
|
||
let dicGVGItem = gameData.gvgItem.get(itemId);
|
||
let dicFarm = gameData.gvgResource.get(farmId);
|
||
if(!dicGVGItem || !dicFarm) return { output: 0, outputStr: '' };
|
||
let { value: foodBase } = dicGVGItem;
|
||
let addRatio = seedType == addType? GVG.GVG_SP_FIELD_ADD * 100: 0;
|
||
let farmRatio = dicFarm.fieldAdd;
|
||
let cityRatio = getCitiesAdd(cities, GVG_RESOURCE_TYPE.FOOD);
|
||
let techRatio = getTechAdd(activeTech);
|
||
|
||
return {
|
||
output: Math.floor(foodBase * (1 + (addRatio + farmRatio + cityRatio + techRatio)/100)),
|
||
outputStr: `Math.floor(${foodBase} * (1 + (${addRatio} + ${farmRatio} + ${cityRatio} + ${techRatio})/100))`
|
||
}
|
||
}
|
||
|
||
export async function sumOutputByResults(myResultFields: GVGLeagueFarmType[]) {
|
||
let [foodSum = 0, rewardSum = new Array<RewardInter>(), leagueRewardSum = new Array<RewardInter>(), activeSum = 0] = [];
|
||
for(let { seedType, output: food } of myResultFields) {
|
||
let itemId = getItemIdOfSeedType(seedType);
|
||
let dicGVGItem = gameData.gvgItem.get(itemId);
|
||
if(!dicGVGItem) continue;
|
||
let { reward, leagueReward, leagueConsume } = dicGVGItem;
|
||
let produceCoin = getProduceCoinCnt(leagueConsume);
|
||
foodSum += food;
|
||
for(let { id, count } of reward) {
|
||
let rewardObj = rewardSum.find(cur => cur.id == id);
|
||
rewardObj? rewardObj.count += count: rewardSum.push({id, count});
|
||
}
|
||
for(let { id, count } of leagueReward) {
|
||
let rewardObj = leagueRewardSum.find(cur => cur.id == id);
|
||
rewardObj? rewardObj.count += count: leagueRewardSum.push({id, count});
|
||
}
|
||
activeSum += produceCoin;
|
||
}
|
||
return { foodSum, rewardSum, leagueRewardSum, activeSum }
|
||
}
|
||
|
||
/**
|
||
* 计算挖矿产量
|
||
* @param farmId 矿场id
|
||
* @param result 小游戏的结果
|
||
* @param cities 上周占领城镇加成
|
||
* @param activeTech 千机阁加成
|
||
* @returns
|
||
*/
|
||
export function calMineOutput(farmId: number, result: [{ type: number, count: number }], cities: number[], activeTech: number[]) {
|
||
// =(100*1.5【中铁块单块产量倍数】*4【可挖出的中铁块数量】+100*2【大铁块单块产量倍数】*8【可挖出的大铁块数量】+100*3【特大铁块单块产量倍数】*8【可挖出的特大铁块数量】)*(1+0.5【大城产量加成】)
|
||
let dicMine = gameData.gvgResource.get(farmId);
|
||
if(!dicMine) return { output: 0, outputStr: '' };
|
||
let output = 0, addStrArr = [];
|
||
for(let { type, count } of result) {
|
||
let dic = dicMine.mineralValue.find(cur => cur.type == type);
|
||
if(!dic) continue;
|
||
output += dic.output * count;
|
||
addStrArr.push(`${dic.output}*${count}`);
|
||
}
|
||
let cityRatio = getCitiesAdd(cities, GVG_RESOURCE_TYPE.MINERAL);
|
||
let techRatio = getTechAdd(activeTech);
|
||
return {
|
||
output: Math.floor(output * (1 + (cityRatio + techRatio)/100)),
|
||
outputStr: `Math.floor(${addStrArr.join('+')} * (1 + (${cityRatio} + ${techRatio})/100))`
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 计算木块产量
|
||
* @param farmId 林场id
|
||
* @param result 小游戏的结果
|
||
* @param cities 上周占领城镇加成
|
||
* @param activeTech 千机阁加成
|
||
* @returns
|
||
*/
|
||
export function calForestryOutput(farmId: number, result: number, cities: number[], activeTech: number[]) {
|
||
// =100*2【10级木堆木块单块基础产量倍数】*(1+0.3【城镇加成倍数】)*40【使用铁斧头最大分块】
|
||
let dicForestry = gameData.gvgResource.get(farmId);
|
||
if(!dicForestry) return { output: 0, outputStr: '' };
|
||
let base = dicForestry.woodOutput;
|
||
let cityRatio = getCitiesAdd(cities, GVG_RESOURCE_TYPE.WOOD);
|
||
let techRatio = getTechAdd(activeTech);
|
||
return {
|
||
output: Math.floor( base * (1 + (cityRatio + techRatio)/100) * result),
|
||
outputStr: `Math.floor(${base} * (1 + (${cityRatio} + ${techRatio})/100) * ${result})`
|
||
}
|
||
|
||
}
|
||
|
||
// 城池加成,多城池取最大加成
|
||
function getCitiesAdd(cities: number[], resourceType: number) {
|
||
let outputAdd: number = 0;
|
||
for(let cityId of cities) {
|
||
let dicCity = gameData.gvgCity.get(cityId);
|
||
let dicCityAdd = gameData.gvgCityAdd.get(dicCity?.cityType);
|
||
if(!dicCity || !dicCityAdd) continue;
|
||
if(resourceType == GVG_RESOURCE_TYPE.FOOD) {
|
||
outputAdd += dicCityAdd.foodAdd;
|
||
} else if (resourceType == GVG_RESOURCE_TYPE.MINERAL) {
|
||
outputAdd += dicCityAdd.mineralAdd;
|
||
} else if (resourceType == GVG_RESOURCE_TYPE.WOOD) {
|
||
outputAdd += dicCityAdd.woodAdd;
|
||
}
|
||
}
|
||
return outputAdd;
|
||
}
|
||
|
||
// 科技树加成 叠加
|
||
function getTechAdd(activeTech: number[]) {
|
||
let ratio = 0;
|
||
for(let techId of activeTech) {
|
||
let dicTech = gameData.gvgTech.get(techId);
|
||
if(dicTech.type == GVG_TECH_TYPE.PRODUCE_UP) {
|
||
ratio += dicTech.param[0];
|
||
}
|
||
}
|
||
return ratio;
|
||
}
|
||
|
||
// 锁定
|
||
export async function lockMineOrForestry(leagueCode: string, roleId: string, farmId: number, itemId: number) {
|
||
let { configId } = getGVGConfig();
|
||
const leagueFarms = await GVGLeagueFarmModel.findByFarmId(configId, leagueCode, farmId);
|
||
// 查询现有的田
|
||
let fieldId = getUnlockedMine(farmId, leagueFarms);
|
||
if(!fieldId) return null;
|
||
|
||
let dicFarm = gameData.gvgResource.get(farmId);
|
||
|
||
let lockResult = await GVGLeagueFarmModel.lockMineOrForestry(configId, leagueCode, farmId, dicFarm?.type, roleId, fieldId, itemId);
|
||
if(!lockResult) return null;
|
||
|
||
return lockResult;
|
||
}
|
||
|
||
function getUnlockedMine(farmId: number, leagueFarms: GVGLeagueFarmType[]) {
|
||
let leagueFarmMap = arrToMap(leagueFarms, obj => obj.fieldId);
|
||
let fieldId = 0;
|
||
let sum = gameData.gvgResource.get(farmId)?.sum??0;
|
||
for(let i = 1; i <= sum; i++) {
|
||
if(!leagueFarmMap.has(i)) {
|
||
fieldId = i; break;
|
||
}
|
||
}
|
||
return fieldId;
|
||
}
|
||
|
||
export function checkItemCanUserInFarm(farmId: number, itemId: number) {
|
||
let dicFarm = gameData.gvgResource.get(farmId);
|
||
let dicGVGItem = gameData.gvgItem.get(itemId);
|
||
if(!dicFarm || !dicGVGItem) return false;
|
||
return dicFarm.type == dicGVGItem.type;
|
||
}
|
||
|
||
// 推送千机阁状态变化
|
||
export async function pushTechChange(guildCodes: string[], isActive: boolean, id: number, progress: number, maxProgress: number) {
|
||
for(let guildCode of guildCodes) {
|
||
await sendMessageToGuildWithSuc(guildCode, PUSH_ROUTE.LEAGUE_TECH_CHANGE, {
|
||
id, progress, maxProgress, isActive
|
||
});
|
||
}
|
||
}
|
||
|
||
export async function pushTechRollback(guildCodes: string[], ids: number[]) {
|
||
for(let guildCode of guildCodes) {
|
||
await sendMessageToGuildWithSuc(guildCode, PUSH_ROUTE.LEAGUE_TECH_ROLLBACK, {
|
||
ids
|
||
});
|
||
}
|
||
}
|
||
|
||
export async function sendUngotBoxReward(configId: number, leagueCode: string, roleId: string, sid: string) {
|
||
let { period } = getGVGPeriodData();
|
||
if(period != GVG_PERIOD.BATTLE) return;
|
||
let userData = await GVGUserDataModel.checkBox(configId, leagueCode, roleId);
|
||
if(userData) {
|
||
let { contribute = new Contribute(), box = [] } = userData||{};
|
||
|
||
let rewards: RewardInter[] = [], leagueReward: RewardInter[] = [], receiveBoxes: number[] = [];
|
||
for(let [boxId, dicBox] of gameData.gvgContributeBox) {
|
||
if(box.indexOf(boxId) != -1) continue;
|
||
let sumContribute = dicBox.job == LEAGUE_JOB.PRODUCER? calProducerContribute(contribute): calFighterContribute(contribute);
|
||
if(sumContribute < dicBox.boxPoint) continue;
|
||
receiveBoxes.push(boxId);
|
||
combinePushItem(rewards, dicBox.boxReward);
|
||
combinePushItem(leagueReward, dicBox.boxLeagueReward);
|
||
}
|
||
if(leagueReward.length > 0) await addGVGReward(roleId, '', leagueCode, sid, leagueReward, [], ITEM_CHANGE_REASON.GVG_VESTIGE_RECEIVE_RANK);
|
||
if(rewards.length > 0) await sendMailByContent(MAIL_TYPE.GVG_BOX_REWARD, roleId, { params: [`${configId}`, receiveBoxes.join()], goods: rewards });
|
||
|
||
await GVGUserDataModel.receiveBoxes(configId, leagueCode, roleId, receiveBoxes);
|
||
}
|
||
}
|