✨ feat(gvg): 矿场
This commit is contained in:
@@ -2,15 +2,18 @@ import { Application, BackendSession, ChannelService, HandlerService } from "pin
|
|||||||
import { GVG_ACTIVE_TYPE, GVG_ITEM, GVG_ITEM_TYPE, GVG_PERIOD, GVG_RESOURCE_TYPE, ITEM_CHANGE_REASON, MAIL_TYPE, STATUS } from "../../../consts";
|
import { GVG_ACTIVE_TYPE, GVG_ITEM, GVG_ITEM_TYPE, GVG_PERIOD, GVG_RESOURCE_TYPE, ITEM_CHANGE_REASON, MAIL_TYPE, STATUS } from "../../../consts";
|
||||||
import { GVGLeagueModel } from "../../../db/GVGLeague";
|
import { GVGLeagueModel } from "../../../db/GVGLeague";
|
||||||
import { GVGLeagueFarmModel, GVGLeagueFarmType } from "../../../db/GVGLeagueFarm";
|
import { GVGLeagueFarmModel, GVGLeagueFarmType } from "../../../db/GVGLeagueFarm";
|
||||||
|
import { GVGLeagueFarmRecModel } from "../../../db/GVGLeagueFarmRec";
|
||||||
import { GVGLeaguePrepareModel } from "../../../db/GVGLeaguePrepare";
|
import { GVGLeaguePrepareModel } from "../../../db/GVGLeaguePrepare";
|
||||||
|
import { GVGUserItemModel } from "../../../db/GVGUserItem";
|
||||||
import { RoleModel } from "../../../db/Role";
|
import { RoleModel } from "../../../db/Role";
|
||||||
import { LeagueFarmListInfo, LeagueFarmMember, LeagueField } from "../../../domain/gvgField/returnData";
|
import { LeagueFarmListInfo, LeagueFarmMember, LeagueField } from "../../../domain/gvgField/returnData";
|
||||||
import { gameData, getGVGResourceBasesByType } from "../../../pubUtils/data";
|
import { gameData, getGVGResourceBasesByType } from "../../../pubUtils/data";
|
||||||
import { ItemInter, RewardInter } from "../../../pubUtils/interface";
|
import { ItemInter, RewardInter } from "../../../pubUtils/interface";
|
||||||
import { nowSeconds } from "../../../pubUtils/timeUtil";
|
import { nowSeconds } from "../../../pubUtils/timeUtil";
|
||||||
import { resResult } from "../../../pubUtils/util";
|
import { resResult } from "../../../pubUtils/util";
|
||||||
|
import { getGVGCities } from "../../../services/gvg/gvgBattleService";
|
||||||
import { addGVGReward, getProduceCoinCnt, handleGVGCost } from "../../../services/gvg/gvgItemService";
|
import { addGVGReward, getProduceCoinCnt, handleGVGCost } from "../../../services/gvg/gvgItemService";
|
||||||
import { addGVGActive, addResource, calFarmOutputs, getCostSeedReward, getItemIdOfSeedType, getLeagueFarmShowResult, getLockFieldCnt, getmyDistributeRank, rollbackUnPlantFields, unlockField } from "../../../services/gvg/gvgPrepareService";
|
import { addGVGActive, addResource, getCostSeedReward, getItemIdOfSeedType, getLeagueFarmShowResult, getLockFieldCnt, getmyDistributeRank, rollbackUnPlantFields, lockField, calFarmOutput, sumOutputByResults, lockMineOrForestry, calMineOutput, calForestryOutput, checkItemCanUserInFarm } from "../../../services/gvg/gvgPrepareService";
|
||||||
import { getGVGConfig, getGVGPeriodData } from "../../../services/gvg/gvgService";
|
import { getGVGConfig, getGVGPeriodData } from "../../../services/gvg/gvgService";
|
||||||
import { sendMailByContent } from "../../../services/mailService";
|
import { sendMailByContent } from "../../../services/mailService";
|
||||||
import { getAllServerName, getRoleOnlineInfo } from "../../../services/redisService";
|
import { getAllServerName, getRoleOnlineInfo } from "../../../services/redisService";
|
||||||
@@ -77,10 +80,10 @@ export class GVGProduceHandler {
|
|||||||
|
|
||||||
const dicFarms = getGVGResourceBasesByType(type);
|
const dicFarms = getGVGResourceBasesByType(type);
|
||||||
const result: LeagueFarmListInfo[] = [];
|
const result: LeagueFarmListInfo[] = [];
|
||||||
for(let { id, lv } of dicFarms) {
|
for(let { id, lv, type } of dicFarms) {
|
||||||
if(lv > leagueLv) continue;
|
if(lv > leagueLv) continue;
|
||||||
const leagueFarm = leagueFarms.filter(cur => cur.farmId == id && cur.unlockTime >= nowSeconds()); // 已种植单位
|
const leagueFarm = leagueFarms.filter(cur => cur.farmId == id && cur.unlockTime >= nowSeconds()); // 已种植单位
|
||||||
const canHarvestFarms = leagueFarms.filter(cur => cur.farmId == id && cur.lockRoleId == roleId && cur.harvestTime > 0 && cur.harvestTime <= nowSeconds());
|
const canHarvestFarms = leagueFarms.filter(cur => type == GVG_RESOURCE_TYPE.FOOD && cur.farmId == id && cur.harvestTime > 0 && cur.harvestTime <= nowSeconds());
|
||||||
let obj = new LeagueFarmListInfo(id, leagueFarm.length, canHarvestFarms.length > 0);
|
let obj = new LeagueFarmListInfo(id, leagueFarm.length, canHarvestFarms.length > 0);
|
||||||
result.push(obj);
|
result.push(obj);
|
||||||
}
|
}
|
||||||
@@ -103,8 +106,6 @@ export class GVGProduceHandler {
|
|||||||
let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode);
|
let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode);
|
||||||
if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST);
|
if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST);
|
||||||
|
|
||||||
const leaguePrepare = await GVGLeaguePrepareModel.findByLeague(configId, myLeague.leagueCode);
|
|
||||||
|
|
||||||
const fields = await GVGLeagueFarmModel.findPlantedByFarmId(configId, myLeague.leagueCode, farmId);
|
const fields = await GVGLeagueFarmModel.findPlantedByFarmId(configId, myLeague.leagueCode, farmId);
|
||||||
const roleIds: string[] = [], fieldByRoleId = new Map<string, GVGLeagueFarmType[]>();
|
const roleIds: string[] = [], fieldByRoleId = new Map<string, GVGLeagueFarmType[]>();
|
||||||
for(let field of fields) {
|
for(let field of fields) {
|
||||||
@@ -122,8 +123,6 @@ export class GVGProduceHandler {
|
|||||||
let obj = new LeagueFarmMember(role, serverNames);
|
let obj = new LeagueFarmMember(role, serverNames);
|
||||||
let myFields = fieldByRoleId.get(role.roleId)||[]
|
let myFields = fieldByRoleId.get(role.roleId)||[]
|
||||||
obj.setByFields(myFields);
|
obj.setByFields(myFields);
|
||||||
const { foodSum } = await calFarmOutputs(myFields, myLeague, leaguePrepare);
|
|
||||||
obj.setOutput(foodSum);
|
|
||||||
result.push(obj);
|
result.push(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -146,7 +145,7 @@ export class GVGProduceHandler {
|
|||||||
let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode);
|
let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode);
|
||||||
if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST);
|
if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST);
|
||||||
|
|
||||||
await unlockField(myLeague.leagueCode, roleId, farmId);
|
await lockField(myLeague.leagueCode, roleId, farmId);
|
||||||
const myRank = await getmyDistributeRank(myLeague.leagueCode, myLeague.members, roleId);
|
const myRank = await getmyDistributeRank(myLeague.leagueCode, myLeague.members, roleId);
|
||||||
|
|
||||||
return resResult(STATUS.SUCCESS, {
|
return resResult(STATUS.SUCCESS, {
|
||||||
@@ -156,24 +155,36 @@ export class GVGProduceHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 种田
|
// 种田
|
||||||
async plant(msg: { farmId: number, results: { fieldId: number, seedType: number }[] }, session: BackendSession) {
|
async plant(msg: { farmId: number, seeds: { fieldId: number, seedType: number }[] }, session: BackendSession) {
|
||||||
const roleId = session.get('roleId');
|
const roleId = session.get('roleId');
|
||||||
const roleName = session.get('roleName');
|
const roleName = session.get('roleName');
|
||||||
const guildCode = session.get('guildCode');
|
const guildCode = session.get('guildCode');
|
||||||
const sid = session.get('sid');
|
const sid = session.get('sid');
|
||||||
|
|
||||||
const { farmId, results } = msg;
|
const { farmId, seeds } = msg;
|
||||||
let { configId, period } = getGVGPeriodData();
|
let { configId, period } = getGVGPeriodData();
|
||||||
if(period != GVG_PERIOD.PREPARE) return resResult(STATUS.GVG_NOT_PREPARE_PERIOD);
|
if(period != GVG_PERIOD.PREPARE) return resResult(STATUS.GVG_NOT_PREPARE_PERIOD);
|
||||||
|
|
||||||
let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode);
|
let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode);
|
||||||
if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST);
|
if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST);
|
||||||
|
|
||||||
const cost: RewardInter[] = [], updateFields: { fieldId: number, seedType: number, time: number }[] = [];
|
const fields = await GVGLeagueFarmModel.findByFieldIds(configId, myLeague.leagueCode, farmId, seeds.map(({fieldId}) => fieldId));
|
||||||
for(let { fieldId, seedType } of results) {
|
for(let field of fields) {
|
||||||
|
if(!field) return resResult(STATUS.GVG_FIELD_NOT_FOUND);
|
||||||
|
if(field.lockRoleId != roleId && field.unlockTime > nowSeconds()) return resResult(STATUS.GVG_FIELD_HAS_LOCKED);
|
||||||
|
}
|
||||||
|
|
||||||
|
const cities = await getGVGCities(myLeague);
|
||||||
|
const leaguePrepare = await GVGLeaguePrepareModel.findByLeague(configId, myLeague.leagueCode);
|
||||||
|
|
||||||
|
const cost: RewardInter[] = [], updateFields: { fieldId: number, seedType: number, time: number, output: number, outputStr: string }[] = [];
|
||||||
|
for(let { fieldId, seedType } of seeds) {
|
||||||
let itemId = getItemIdOfSeedType(seedType);
|
let itemId = getItemIdOfSeedType(seedType);
|
||||||
let dicItem = gameData.gvgItem.get(itemId);
|
let dicItem = gameData.gvgItem.get(itemId);
|
||||||
updateFields.push({ fieldId, seedType, time: dicItem.ripeTime });
|
let field = fields.find(cur => cur.fieldId == field);
|
||||||
|
if(!field) continue;
|
||||||
|
let output = calFarmOutput(seedType, field.addType, farmId, cities, leaguePrepare?.activeTech||[]);
|
||||||
|
updateFields.push({ fieldId, seedType, time: dicItem.ripeTime, ...output });
|
||||||
// 算消耗的种子
|
// 算消耗的种子
|
||||||
let costObj = cost.find(({ id }) => id == itemId);
|
let costObj = cost.find(({ id }) => id == itemId);
|
||||||
costObj? costObj.count++: cost.push({ id: itemId, count: 1 });
|
costObj? costObj.count++: cost.push({ id: itemId, count: 1 });
|
||||||
@@ -183,6 +194,7 @@ export class GVGProduceHandler {
|
|||||||
|
|
||||||
const plantResult = await GVGLeagueFarmModel.plant(configId, myLeague.leagueCode, farmId, updateFields, roleId);
|
const plantResult = await GVGLeagueFarmModel.plant(configId, myLeague.leagueCode, farmId, updateFields, roleId);
|
||||||
await rollbackUnPlantFields(cost, plantResult, session, myLeague.leagueCode); // 可能会有田已经被其他人占领的情况,将种子还回去
|
await rollbackUnPlantFields(cost, plantResult, session, myLeague.leagueCode); // 可能会有田已经被其他人占领的情况,将种子还回去
|
||||||
|
await GVGLeagueFarmRecModel.insertRecs(plantResult);
|
||||||
|
|
||||||
return resResult(STATUS.SUCCESS, {
|
return resResult(STATUS.SUCCESS, {
|
||||||
...await getLeagueFarmShowResult(myLeague.leagueCode, roleId, farmId)
|
...await getLeagueFarmShowResult(myLeague.leagueCode, roleId, farmId)
|
||||||
@@ -203,12 +215,10 @@ export class GVGProduceHandler {
|
|||||||
let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode);
|
let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode);
|
||||||
if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST);
|
if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST);
|
||||||
|
|
||||||
const leaguePrepare = await GVGLeaguePrepareModel.findByLeague(configId, myLeague.leagueCode);
|
|
||||||
|
|
||||||
const myResultFields = await GVGLeagueFarmModel.harvest(configId, myLeague.leagueCode, farmId, fieldIds, roleId); // 解锁
|
const myResultFields = await GVGLeagueFarmModel.harvest(configId, myLeague.leagueCode, farmId, fieldIds, roleId); // 解锁
|
||||||
if(myResultFields.length <= 0) return resResult(STATUS.GVG_CANNOT_HARVEST);
|
if(myResultFields.length <= 0) return resResult(STATUS.GVG_CANNOT_HARVEST);
|
||||||
// 计算产量
|
// 计算产量
|
||||||
const { foodSum, rewardSum, leagueRewardSum, activeSum } = await calFarmOutputs(myResultFields, myLeague, leaguePrepare);
|
const { foodSum, rewardSum, leagueRewardSum, activeSum } = await sumOutputByResults(myResultFields);
|
||||||
// 资源
|
// 资源
|
||||||
let resourceResult = await addResource(myLeague.leagueCode, roleId, GVG_RESOURCE_TYPE.FOOD, foodSum)||{};
|
let resourceResult = await addResource(myLeague.leagueCode, roleId, GVG_RESOURCE_TYPE.FOOD, foodSum)||{};
|
||||||
// 相关物品
|
// 相关物品
|
||||||
@@ -216,7 +226,8 @@ export class GVGProduceHandler {
|
|||||||
// 活跃
|
// 活跃
|
||||||
const active = await addGVGActive(myLeague.leagueCode, roleId, GVG_ACTIVE_TYPE.COST_PRODUCE_COIN, activeSum);
|
const active = await addGVGActive(myLeague.leagueCode, roleId, GVG_ACTIVE_TYPE.COST_PRODUCE_COIN, activeSum);
|
||||||
// 收获后再次预锁定一批田
|
// 收获后再次预锁定一批田
|
||||||
await unlockField(myLeague.leagueCode, roleId, farmId);
|
await lockField(myLeague.leagueCode, roleId, farmId);
|
||||||
|
await GVGLeagueFarmRecModel.updateRecs(myResultFields, roleId);
|
||||||
|
|
||||||
return resResult(STATUS.SUCCESS, {
|
return resResult(STATUS.SUCCESS, {
|
||||||
...await getLeagueFarmShowResult(myLeague.leagueCode, roleId, farmId),
|
...await getLeagueFarmShowResult(myLeague.leagueCode, roleId, farmId),
|
||||||
@@ -256,8 +267,6 @@ export class GVGProduceHandler {
|
|||||||
let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode);
|
let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode);
|
||||||
if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST);
|
if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST);
|
||||||
|
|
||||||
const leaguePrepare = await GVGLeaguePrepareModel.findByLeague(configId, myLeague.leagueCode);
|
|
||||||
|
|
||||||
const resultField = await GVGLeagueFarmModel.helpHarvest(configId, myLeague.leagueCode, farmId, fieldId); // 解锁
|
const resultField = await GVGLeagueFarmModel.helpHarvest(configId, myLeague.leagueCode, farmId, fieldId); // 解锁
|
||||||
if(!resultField) return resResult(STATUS.GVG_CANNOT_HARVEST);
|
if(!resultField) return resResult(STATUS.GVG_CANNOT_HARVEST);
|
||||||
|
|
||||||
@@ -265,7 +274,7 @@ export class GVGProduceHandler {
|
|||||||
let targetOnlineInfo = await getRoleOnlineInfo(targetRoleId);
|
let targetOnlineInfo = await getRoleOnlineInfo(targetRoleId);
|
||||||
|
|
||||||
// 计算产量
|
// 计算产量
|
||||||
const { foodSum, rewardSum, leagueRewardSum, activeSum } = await calFarmOutputs([resultField], myLeague, leaguePrepare);
|
const { foodSum, rewardSum, leagueRewardSum, activeSum } = await sumOutputByResults([resultField]);
|
||||||
// 资源
|
// 资源
|
||||||
await addResource(myLeague.leagueCode, targetRoleId, GVG_RESOURCE_TYPE.FOOD, foodSum)||{};
|
await addResource(myLeague.leagueCode, targetRoleId, GVG_RESOURCE_TYPE.FOOD, foodSum)||{};
|
||||||
await sendMailByContent(MAIL_TYPE.HELP_HARVEST, targetRoleId, { sendName: roleName, goods: rewardSum });
|
await sendMailByContent(MAIL_TYPE.HELP_HARVEST, targetRoleId, { sendName: roleName, goods: rewardSum });
|
||||||
@@ -279,6 +288,212 @@ export class GVGProduceHandler {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 进入矿山
|
||||||
|
async mineStart(msg: { farmId: number, itemId: number }, session: BackendSession) {
|
||||||
|
const roleId = session.get('roleId');
|
||||||
|
const guildCode = session.get('guildCode');
|
||||||
|
|
||||||
|
const { farmId, itemId } = msg;
|
||||||
|
if(!checkItemCanUserInFarm(farmId, itemId)) return resResult(STATUS.GVG_ITEM_CANNOT_USE);
|
||||||
|
|
||||||
|
let { configId, period } = getGVGPeriodData();
|
||||||
|
if(period != GVG_PERIOD.PREPARE) return resResult(STATUS.GVG_NOT_PREPARE_PERIOD);
|
||||||
|
|
||||||
|
let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode);
|
||||||
|
if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST);
|
||||||
|
|
||||||
|
const hasItem = await GVGUserItemModel.checkItemCnt(configId, myLeague.leagueCode, roleId, itemId, 1);
|
||||||
|
if(!hasItem) return resResult(STATUS.GVG_ITEMS_NOT_ENOUGH);
|
||||||
|
|
||||||
|
const lockResult = await lockMineOrForestry(myLeague.leagueCode, roleId, farmId, itemId);
|
||||||
|
if(!lockResult) return resResult(STATUS.GVG_MINE_HAS_LOCKED);
|
||||||
|
const myRank = await getmyDistributeRank(myLeague.leagueCode, myLeague.members, roleId);
|
||||||
|
|
||||||
|
return resResult(STATUS.SUCCESS, {
|
||||||
|
...await getLeagueFarmShowResult(myLeague.leagueCode, roleId, farmId, false),
|
||||||
|
myRank,
|
||||||
|
fieldId: lockResult.fieldId,
|
||||||
|
unlockTime: lockResult.unlockTime
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 结算矿场
|
||||||
|
async mineEnd(msg: { farmId: number, fieldId: number, result: [{ type: number, count: number }] }, session: BackendSession) {
|
||||||
|
const roleId = session.get('roleId');
|
||||||
|
const roleName = session.get('roleName');
|
||||||
|
const guildCode = session.get('guildCode');
|
||||||
|
const sid = session.get('sid');
|
||||||
|
|
||||||
|
const { farmId, fieldId, result } = msg;
|
||||||
|
let { configId, period } = getGVGPeriodData();
|
||||||
|
if(period != GVG_PERIOD.PREPARE) return resResult(STATUS.GVG_NOT_PREPARE_PERIOD);
|
||||||
|
|
||||||
|
let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode);
|
||||||
|
if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST);
|
||||||
|
|
||||||
|
// 检查数据是否上传争取
|
||||||
|
let dicMine = gameData.gvgResource.get(farmId);
|
||||||
|
if(!dicMine) return resResult(STATUS.DIC_DATA_NOT_FOUND);
|
||||||
|
let mineralSum = 0;
|
||||||
|
for(let { type, count } of result) {
|
||||||
|
let max = dicMine.mineralValue.find(cur => cur.type == type)?.count||0;
|
||||||
|
if(count > max) return resResult(STATUS.GVG_MINERAL_COUNT_OVER);
|
||||||
|
mineralSum += count;
|
||||||
|
}
|
||||||
|
|
||||||
|
const field = await GVGLeagueFarmModel.findByField(configId, myLeague.leagueCode, farmId, fieldId);
|
||||||
|
if(!field || field.lockRoleId != roleId) return resResult(STATUS.GVG_MINE_HAS_OVER);
|
||||||
|
if(!!field.harvestTime) return resResult(STATUS.GVG_MINE_HAS_HARVEST);
|
||||||
|
let dicGVGItem = gameData.gvgItem.get(field.itemId);
|
||||||
|
if(mineralSum > (dicGVGItem?.value||0)) return resResult(STATUS.GVG_MINE_SCOOP_OVER);
|
||||||
|
|
||||||
|
// 扣铲子
|
||||||
|
const costResult = await handleGVGCost(roleId, myLeague.leagueCode, sid, [{ id: field.itemId, count: 1 }], [], ITEM_CHANGE_REASON.MINE_END);
|
||||||
|
if(!costResult) return resResult(STATUS.GVG_ITEMS_NOT_ENOUGH);
|
||||||
|
|
||||||
|
// 计算资源
|
||||||
|
const cities = await getGVGCities(myLeague);
|
||||||
|
const leaguePrepare = await GVGLeaguePrepareModel.findByLeague(configId, myLeague.leagueCode);
|
||||||
|
const { output, outputStr } = calMineOutput(farmId, result, cities, leaguePrepare?.activeTech||[]);
|
||||||
|
// 挖完
|
||||||
|
await GVGLeagueFarmModel.mineOrForestryEnd(configId, myLeague.leagueCode, farmId, roleId, fieldId, output, outputStr);
|
||||||
|
// 计算产量
|
||||||
|
let { reward, leagueReward, leagueConsume } = dicGVGItem;
|
||||||
|
let produceCoin = getProduceCoinCnt(leagueConsume);
|
||||||
|
// 资源
|
||||||
|
let resourceResult = await addResource(myLeague.leagueCode, roleId, GVG_RESOURCE_TYPE.MINERAL, output)||{};
|
||||||
|
// 相关物品
|
||||||
|
let leagueGoods = await addGVGReward(roleId, roleName, myLeague.leagueCode, sid, leagueReward, reward, ITEM_CHANGE_REASON.HARVEST)
|
||||||
|
// 活跃
|
||||||
|
const active = await addGVGActive(myLeague.leagueCode, roleId, GVG_ACTIVE_TYPE.COST_PRODUCE_COIN, produceCoin);
|
||||||
|
|
||||||
|
return resResult(STATUS.SUCCESS, {
|
||||||
|
...await getLeagueFarmShowResult(myLeague.leagueCode, roleId, farmId, false),
|
||||||
|
...resourceResult,
|
||||||
|
leagueGoods,
|
||||||
|
active
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 不能进的矿山,获取其他人的状态
|
||||||
|
async getOtherMines(msg: { farmId: number }, session: BackendSession) {
|
||||||
|
const roleId = session.get('roleId');
|
||||||
|
const guildCode = session.get('guildCode');
|
||||||
|
const { farmId } = msg;
|
||||||
|
|
||||||
|
let { configId, period } = getGVGPeriodData();
|
||||||
|
if(period != GVG_PERIOD.PREPARE) return resResult(STATUS.GVG_NOT_PREPARE_PERIOD);
|
||||||
|
|
||||||
|
let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode);
|
||||||
|
if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST);
|
||||||
|
|
||||||
|
const fields = await GVGLeagueFarmModel.findLockedByFarmId(configId, myLeague.leagueCode, farmId);
|
||||||
|
const roleIds: string[] = [], fieldByRoleId = new Map<string, GVGLeagueFarmType[]>();
|
||||||
|
for(let field of fields) {
|
||||||
|
if(roleIds.indexOf(field.lockRoleId) == -1) {
|
||||||
|
roleIds.push(field.lockRoleId);
|
||||||
|
fieldByRoleId.set(field.lockRoleId, []);
|
||||||
|
}
|
||||||
|
fieldByRoleId.get(field.lockRoleId).push(field);
|
||||||
|
}
|
||||||
|
|
||||||
|
const serverNames = await getAllServerName();
|
||||||
|
const roles = await RoleModel.findByRoleIds(roleIds);
|
||||||
|
const result: LeagueFarmMember[] = [];
|
||||||
|
for(let role of roles) {
|
||||||
|
let obj = new LeagueFarmMember(role, serverNames);
|
||||||
|
let myFields = fieldByRoleId.get(role.roleId)||[]
|
||||||
|
obj.setByMines(myFields);
|
||||||
|
result.push(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
return resResult(STATUS.SUCCESS, {
|
||||||
|
...await getLeagueFarmShowResult(myLeague.leagueCode, roleId, farmId, false),
|
||||||
|
members: result
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 进入林场
|
||||||
|
async forestryStart(msg: { farmId: number, itemId: number }, session: BackendSession) {
|
||||||
|
const roleId = session.get('roleId');
|
||||||
|
const guildCode = session.get('guildCode');
|
||||||
|
|
||||||
|
const { farmId, itemId } = msg;
|
||||||
|
if(!checkItemCanUserInFarm(farmId, itemId)) return resResult(STATUS.GVG_ITEM_CANNOT_USE);
|
||||||
|
|
||||||
|
let { configId, period } = getGVGPeriodData();
|
||||||
|
if(period != GVG_PERIOD.PREPARE) return resResult(STATUS.GVG_NOT_PREPARE_PERIOD);
|
||||||
|
|
||||||
|
let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode);
|
||||||
|
if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST);
|
||||||
|
|
||||||
|
const hasItem = await GVGUserItemModel.checkItemCnt(configId, myLeague.leagueCode, roleId, itemId, 1);
|
||||||
|
if(!hasItem) return resResult(STATUS.GVG_ITEMS_NOT_ENOUGH);
|
||||||
|
|
||||||
|
const lockResult = await lockMineOrForestry(myLeague.leagueCode, roleId, farmId, itemId);
|
||||||
|
if(!lockResult) return resResult(STATUS.GVG_MINE_HAS_LOCKED);
|
||||||
|
const myRank = await getmyDistributeRank(myLeague.leagueCode, myLeague.members, roleId);
|
||||||
|
|
||||||
|
return resResult(STATUS.SUCCESS, {
|
||||||
|
...await getLeagueFarmShowResult(myLeague.leagueCode, roleId, farmId, false),
|
||||||
|
myRank,
|
||||||
|
fieldId: lockResult.fieldId,
|
||||||
|
unlockTime: lockResult.unlockTime
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 林场结算
|
||||||
|
async forestryEnd(msg: { farmId: number, fieldId: number, result: number }, session: BackendSession) {
|
||||||
|
const roleId = session.get('roleId');
|
||||||
|
const roleName = session.get('roleName');
|
||||||
|
const guildCode = session.get('guildCode');
|
||||||
|
const sid = session.get('sid');
|
||||||
|
|
||||||
|
const { farmId, fieldId, result } = msg;
|
||||||
|
let { configId, period } = getGVGPeriodData();
|
||||||
|
if(period != GVG_PERIOD.PREPARE) return resResult(STATUS.GVG_NOT_PREPARE_PERIOD);
|
||||||
|
|
||||||
|
let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode);
|
||||||
|
if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST);
|
||||||
|
|
||||||
|
// 检查数据是否上传争取
|
||||||
|
let dicForestry = gameData.gvgResource.get(farmId);
|
||||||
|
if(!dicForestry) return resResult(STATUS.DIC_DATA_NOT_FOUND);
|
||||||
|
|
||||||
|
const field = await GVGLeagueFarmModel.findByField(configId, myLeague.leagueCode, farmId, fieldId);
|
||||||
|
if(!field || field.lockRoleId != roleId) return resResult(STATUS.GVG_FORESTRY_HAS_OVER);
|
||||||
|
if(!!field.harvestTime) return resResult(STATUS.GVG_FORESTRY_HAS_HARVEST);
|
||||||
|
let dicGVGItem = gameData.gvgItem.get(field.itemId);
|
||||||
|
if(result > (dicGVGItem?.value||0)) return resResult(STATUS.GVG_MINE_SCOOP_OVER);
|
||||||
|
|
||||||
|
// 扣斧头
|
||||||
|
const costResult = await handleGVGCost(roleId, myLeague.leagueCode, sid, [{ id: field.itemId, count: 1 }], [], ITEM_CHANGE_REASON.MINE_END);
|
||||||
|
if(!costResult) return resResult(STATUS.GVG_ITEMS_NOT_ENOUGH);
|
||||||
|
|
||||||
|
// 计算资源
|
||||||
|
const cities = await getGVGCities(myLeague);
|
||||||
|
const leaguePrepare = await GVGLeaguePrepareModel.findByLeague(configId, myLeague.leagueCode);
|
||||||
|
const { output, outputStr } = calForestryOutput(farmId, result, cities, leaguePrepare?.activeTech||[]);
|
||||||
|
// 挖完
|
||||||
|
await GVGLeagueFarmModel.mineOrForestryEnd(configId, myLeague.leagueCode, farmId, roleId, fieldId, output, outputStr);
|
||||||
|
// 计算产量
|
||||||
|
let { reward, leagueReward, leagueConsume } = dicGVGItem;
|
||||||
|
let produceCoin = getProduceCoinCnt(leagueConsume);
|
||||||
|
// 资源
|
||||||
|
let resourceResult = await addResource(myLeague.leagueCode, roleId, GVG_RESOURCE_TYPE.WOOD, output)||{};
|
||||||
|
// 相关物品
|
||||||
|
let leagueGoods = await addGVGReward(roleId, roleName, myLeague.leagueCode, sid, leagueReward, reward, ITEM_CHANGE_REASON.HARVEST)
|
||||||
|
// 活跃
|
||||||
|
const active = await addGVGActive(myLeague.leagueCode, roleId, GVG_ACTIVE_TYPE.COST_PRODUCE_COIN, produceCoin);
|
||||||
|
|
||||||
|
return resResult(STATUS.SUCCESS, {
|
||||||
|
...await getLeagueFarmShowResult(myLeague.leagueCode, roleId, farmId, false),
|
||||||
|
...resourceResult,
|
||||||
|
leagueGoods,
|
||||||
|
active
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// 获取资源
|
// 获取资源
|
||||||
async debugAddResource(msg: { type: number, count: number }, session: BackendSession) {
|
async debugAddResource(msg: { type: number, count: number }, session: BackendSession) {
|
||||||
const roleId = session.get('roleId');
|
const roleId = session.get('roleId');
|
||||||
|
|||||||
@@ -10,13 +10,11 @@ import { calLeagueLv, gameData, getFieldMaxAddType } from "../../pubUtils/data";
|
|||||||
import { GVG } from "../../pubUtils/dicParam";
|
import { GVG } from "../../pubUtils/dicParam";
|
||||||
import { RewardInter } from "../../pubUtils/interface";
|
import { RewardInter } from "../../pubUtils/interface";
|
||||||
import { nowSeconds } from "../../pubUtils/timeUtil";
|
import { nowSeconds } from "../../pubUtils/timeUtil";
|
||||||
import { getArrayOfNumber, getRandEelm, getRandValueByMinMax, parseGoodStr, sortArrRandom } from "../../pubUtils/util";
|
import { arrToMap, getArrayOfNumber, getRandEelm, getRandValueByMinMax, parseGoodStr, sortArrRandom } from "../../pubUtils/util";
|
||||||
import { addGVGReward } from "./gvgItemService";
|
import { addGVGReward } from "./gvgItemService";
|
||||||
import { getGVGConfig } from "./gvgService";
|
import { getGVGConfig } from "./gvgService";
|
||||||
import { getProduceCoinCnt } from "./gvgItemService";
|
import { getProduceCoinCnt } from "./gvgItemService";
|
||||||
import { GVGLeagueType } from "../../db/GVGLeague";
|
import { GVGLeagueFarmRecModel } from "../../db/GVGLeagueFarmRec";
|
||||||
import { getCities } from "../guildActivity/guildActivityService";
|
|
||||||
import { getGVGCities } from "./gvgBattleService";
|
|
||||||
|
|
||||||
export function checkPreTech(techId: number, activeQueue: number[], techQueue: Tech[]) {
|
export function checkPreTech(techId: number, activeQueue: number[], techQueue: Tech[]) {
|
||||||
const dicTech = gameData.gvgTech.get(techId);
|
const dicTech = gameData.gvgTech.get(techId);
|
||||||
@@ -136,7 +134,7 @@ function getResourceCnt(resourceType: GVG_RESOURCE_TYPE, count: number) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function unlockField(leagueCode: string, roleId: string, farmId: number) {
|
export async function lockField(leagueCode: string, roleId: string, farmId: number) {
|
||||||
let { configId } = getGVGConfig();
|
let { configId } = getGVGConfig();
|
||||||
const produceCoinCnt = await getLockFieldCnt(leagueCode, roleId);
|
const produceCoinCnt = await getLockFieldCnt(leagueCode, roleId);
|
||||||
if(produceCoinCnt == 0) return
|
if(produceCoinCnt == 0) return
|
||||||
@@ -160,7 +158,7 @@ export async function unlockField(leagueCode: string, roleId: string, farmId: nu
|
|||||||
lands.push({ fieldId, addType });
|
lands.push({ fieldId, addType });
|
||||||
}
|
}
|
||||||
// 更新田
|
// 更新田
|
||||||
let result = await GVGLeagueFarmModel.lockFields(configId, leagueCode, farmId, roleId, lands);
|
await GVGLeagueFarmModel.lockFields(configId, leagueCode, farmId, roleId, lands);
|
||||||
return await GVGLeagueFarmModel.findByFarmIdAndRoleId(configId, leagueCode, farmId, roleId);
|
return await GVGLeagueFarmModel.findByFarmIdAndRoleId(configId, leagueCode, farmId, roleId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -242,13 +240,11 @@ export async function rollbackUnPlantFields(cost: RewardInter[], plantResult: GV
|
|||||||
for(let { id, count } of cost) add.push({ id, count });
|
for(let { id, count } of cost) add.push({ id, count });
|
||||||
for(let { seedType } of plantResult) {
|
for(let { seedType } of plantResult) {
|
||||||
let index = add.findIndex(({ id }) => id == getItemIdOfSeedType(seedType));
|
let index = add.findIndex(({ id }) => id == getItemIdOfSeedType(seedType));
|
||||||
console.log('#### index', index);
|
|
||||||
if(index != -1) {
|
if(index != -1) {
|
||||||
add[index].count --;
|
add[index].count --;
|
||||||
if(add[index].count <= 0) add.splice(index);
|
if(add[index].count <= 0) add.splice(index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
console.log('rollbackUnPlantFields', add, 'plantResult', plantResult)
|
|
||||||
await addGVGReward(roleId, roleName, leagueCode, sid, add, [], ITEM_CHANGE_REASON.PLANT_ROLLBACK);
|
await addGVGReward(roleId, roleName, leagueCode, sid, add, [], ITEM_CHANGE_REASON.PLANT_ROLLBACK);
|
||||||
return add;
|
return add;
|
||||||
}
|
}
|
||||||
@@ -312,11 +308,32 @@ export async function getLeagueFarmShowResult(leagueCode: string, roleId: string
|
|||||||
return { farmId, count: leagueFarms.length, fields: result }
|
return { farmId, count: leagueFarms.length, fields: result }
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function calFarmOutputs(myResultFields: GVGLeagueFarmType[], league: GVGLeagueType, leaguePrepare: GVGLeaguePrepareType) {
|
export function calFarmOutput(seedType: number, addType: number, farmId: number, cities: number[], activeTech: number[]) {
|
||||||
let cities = await getGVGCities(league);
|
// 种子基础产量 * ( 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: 0;
|
||||||
|
let farmRatio = dicFarm.fieldAdd;
|
||||||
|
let cityRatio = getCitiesAdd(cities);
|
||||||
|
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] = [];
|
let [foodSum = 0, rewardSum = new Array<RewardInter>(), leagueRewardSum = new Array<RewardInter>(), activeSum = 0] = [];
|
||||||
for(let { seedType, addType, farmId } of myResultFields) {
|
for(let { seedType, output: food } of myResultFields) {
|
||||||
let { food, reward, leagueReward, active } = calResourceResult(seedType, addType, farmId, cities||[], leaguePrepare?.activeTech||[]);
|
let itemId = getItemIdOfSeedType(seedType);
|
||||||
|
let dicGVGItem = gameData.gvgItem.get(itemId);
|
||||||
|
if(!dicGVGItem) continue;
|
||||||
|
let { reward, leagueReward, leagueConsume } = dicGVGItem;
|
||||||
|
let produceCoin = getProduceCoinCnt(leagueConsume);
|
||||||
foodSum += food;
|
foodSum += food;
|
||||||
for(let { id, count } of reward) {
|
for(let { id, count } of reward) {
|
||||||
let rewardObj = rewardSum.find(cur => cur.id == id);
|
let rewardObj = rewardSum.find(cur => cur.id == id);
|
||||||
@@ -326,31 +343,60 @@ export async function calFarmOutputs(myResultFields: GVGLeagueFarmType[], league
|
|||||||
let rewardObj = leagueRewardSum.find(cur => cur.id == id);
|
let rewardObj = leagueRewardSum.find(cur => cur.id == id);
|
||||||
rewardObj? rewardObj.count += count: leagueRewardSum.push({id, count});
|
rewardObj? rewardObj.count += count: leagueRewardSum.push({id, count});
|
||||||
}
|
}
|
||||||
activeSum += active;
|
activeSum += produceCoin;
|
||||||
}
|
}
|
||||||
return { foodSum, rewardSum, leagueRewardSum, activeSum }
|
return { foodSum, rewardSum, leagueRewardSum, activeSum }
|
||||||
}
|
}
|
||||||
|
|
||||||
function calResourceResult(seedType: number, addType: number, farmId: number, cities: number[], activeTech: number[]) {
|
/**
|
||||||
// 种子基础产量 * ( 1 + 格子加成 + 农庄等级加成 + 战力城池加成 + 科技树加成)
|
* 计算挖矿产量
|
||||||
let itemId = getItemIdOfSeedType(seedType);
|
* @param farmId 矿场id
|
||||||
let dicGVGItem = gameData.gvgItem.get(itemId);
|
* @param result 小游戏的结果
|
||||||
let dicFarm = gameData.gvgResource.get(farmId);
|
* @param cities 上周占领城镇加成
|
||||||
if(!dicGVGItem || !dicFarm) return {};
|
* @param activeTech 千机阁加成
|
||||||
let { value: foodBase, reward, leagueReward, leagueConsume } = dicGVGItem;
|
* @returns
|
||||||
let addRatio = seedType == addType? GVG.GVG_SP_FIELD_ADD: 0;
|
*/
|
||||||
let farmRatio = dicFarm.fieldAdd;
|
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);
|
let cityRatio = getCitiesAdd(cities);
|
||||||
let techRatio = getTechAdd(activeTech);
|
let techRatio = getTechAdd(activeTech);
|
||||||
let produceCoin = getProduceCoinCnt(leagueConsume);
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
food: Math.floor(foodBase * (1 + (addRatio + farmRatio + cityRatio + techRatio)/100)),
|
output: Math.floor(output * (1 + (cityRatio + techRatio)/100)),
|
||||||
reward, leagueReward,
|
outputStr: `Math.floor(${addStrArr.join('+')} * (1 + (${cityRatio} + ${techRatio})/100))`
|
||||||
active: produceCoin
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 计算木块产量
|
||||||
|
* @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);
|
||||||
|
let techRatio = getTechAdd(activeTech);
|
||||||
|
return {
|
||||||
|
output: Math.floor( base * (1 + (cityRatio + techRatio)/100) * result),
|
||||||
|
outputStr: `Math.floor(${base} * (1 + (${cityRatio} + ${techRatio})/100) * ${result})`
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// TODO 城池加成,多城池取最大加成
|
// TODO 城池加成,多城池取最大加成
|
||||||
function getCitiesAdd(cities: number[]) {
|
function getCitiesAdd(cities: number[]) {
|
||||||
return 0
|
return 0
|
||||||
@@ -366,4 +412,39 @@ function getTechAdd(activeTech: number[]) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ratio;
|
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;
|
||||||
}
|
}
|
||||||
@@ -1077,6 +1077,7 @@ export enum ITEM_CHANGE_REASON {
|
|||||||
PLANT = 164, // 种田
|
PLANT = 164, // 种田
|
||||||
PLANT_ROLLBACK = 165, // 种田的时候田已经被抢了回滚
|
PLANT_ROLLBACK = 165, // 种田的时候田已经被抢了回滚
|
||||||
HARVEST = 166, // 收获
|
HARVEST = 166, // 收获
|
||||||
|
MINE_END = 165, // 挖矿
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum TA_EVENT {
|
export enum TA_EVENT {
|
||||||
|
|||||||
@@ -317,6 +317,16 @@ export const STATUS = {
|
|||||||
GVG_TECH_NOT_QUEUE: { code: 21311, simStr: '该科技不在解锁队列中' },
|
GVG_TECH_NOT_QUEUE: { code: 21311, simStr: '该科技不在解锁队列中' },
|
||||||
GVG_BATTLE_FEAT_NOT_ENOUGH: { code: 21312, simStr: '战功不足' },
|
GVG_BATTLE_FEAT_NOT_ENOUGH: { code: 21312, simStr: '战功不足' },
|
||||||
GVG_CANNOT_HARVEST: { code: 21313, simStr: '暂不可收获' },
|
GVG_CANNOT_HARVEST: { code: 21313, simStr: '暂不可收获' },
|
||||||
|
GVG_FIELD_NOT_FOUND: { code: 21314, simStr: '未找到该田' },
|
||||||
|
GVG_FIELD_HAS_LOCKED: { code: 21315, simStr: '该田已被其他人锁定' },
|
||||||
|
GVG_MINE_HAS_LOCKED: { code: 21316, simStr: '全联军挖矿次数达上限或挖矿位置被他人抢先' },
|
||||||
|
GVG_MINERAL_COUNT_OVER: { code: 21317, simStr: '上传铁矿含量超过配置上限' },
|
||||||
|
GVG_MINE_HAS_OVER: { code: 21318, simStr: '挖矿超时,已被他人抢先' },
|
||||||
|
GVG_MINE_SCOOP_OVER: { code: 21319, simStr: '挖矿量超过道具耐久' },
|
||||||
|
GVG_FORESTRY_HAS_OVER: { code: 21320, simStr: '伐木超时,已被他人抢先' },
|
||||||
|
GVG_ITEM_CANNOT_USE: { code: 21321, simStr: '此处不可使用这个道具' },
|
||||||
|
GVG_FORESTRY_HAS_HARVEST: { code: 21322, simStr: '本次伐木已结算过' },
|
||||||
|
GVG_MINE_HAS_HARVEST: { code: 21323, simStr: '本次挖矿已结算过' },
|
||||||
|
|
||||||
// 通用 30000 - 30099
|
// 通用 30000 - 30099
|
||||||
DIC_DATA_NOT_FOUND: { code: 30000, simStr: '数据表未找到' },
|
DIC_DATA_NOT_FOUND: { code: 30000, simStr: '数据表未找到' },
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
// 每个农庄/每个田一条记录,这个田被其他人用了之后会覆盖
|
||||||
|
|
||||||
import BaseModel from './BaseModel';
|
import BaseModel from './BaseModel';
|
||||||
import { index, getModelForClass, prop, DocumentType, } from '@typegoose/typegoose';
|
import { index, getModelForClass, prop, DocumentType, } from '@typegoose/typegoose';
|
||||||
import { getFutureTime, nowSeconds } from '../pubUtils/timeUtil';
|
import { getFutureTime, nowSeconds } from '../pubUtils/timeUtil';
|
||||||
@@ -25,23 +27,32 @@ export default class GVGLeagueFarm extends BaseModel {
|
|||||||
fieldId: number; // 农庄id
|
fieldId: number; // 农庄id
|
||||||
|
|
||||||
@prop({ required: true })
|
@prop({ required: true })
|
||||||
unlockTime: number; // 解锁时间,打开界面时预锁定一批填,种下去之后锁定时间延长到收获时间
|
unlockTime: number; // 解锁时间,农场:打开界面时预锁定一批填,种下去之后锁定时间延长到收获时间,林场&矿场:开始小游戏时锁定时间
|
||||||
|
|
||||||
@prop({ required: true })
|
@prop({ required: true })
|
||||||
lockRoleId: string; // 锁定的人
|
lockRoleId: string; // 锁定的人
|
||||||
|
|
||||||
@prop({ required: true })
|
@prop({ required: true })
|
||||||
harvestTime: number; // 收获时间,种植下去后将时间更新,收获之后设为0
|
harvestTime: number; // 收获时间,农庄:种植下去后将时间更新,收获之后设为0,林场&矿场:小游戏结束时更新
|
||||||
|
|
||||||
@prop({ required: true })
|
@prop({ required: true })
|
||||||
seedType: number; // 实际种的种子类型
|
seedType: number; // 仅农庄使用,实际种的种子类型
|
||||||
|
|
||||||
@prop({ required: true })
|
@prop({ required: true })
|
||||||
addType: number; // 种子加成
|
addType: number; // 仅农庄使用,种子加成
|
||||||
|
|
||||||
@prop({ required: true })
|
@prop({ required: true })
|
||||||
batchCode: string; // 批量号
|
batchCode: string; // 批量号
|
||||||
|
|
||||||
|
@prop({ required: true })
|
||||||
|
itemId: number; // 仅矿山使用,使用的铲子id
|
||||||
|
|
||||||
|
@prop({ required: true })
|
||||||
|
output: number; // 产量,农庄:种下去时可以预估产量,林场&矿场:小游戏结束时根据结果更新
|
||||||
|
|
||||||
|
@prop({ required: true })
|
||||||
|
outputStr: string; // 产量计算公式
|
||||||
|
|
||||||
public static async findByType(configId: number, leagueCode: string, type: number) {
|
public static async findByType(configId: number, leagueCode: string, type: number) {
|
||||||
const result: GVGLeagueFarmType[] = await GVGLeagueFarmModel.find({ configId, leagueCode, type }).select('-_id').lean();
|
const result: GVGLeagueFarmType[] = await GVGLeagueFarmModel.find({ configId, leagueCode, type }).select('-_id').lean();
|
||||||
return result;
|
return result;
|
||||||
@@ -57,12 +68,16 @@ export default class GVGLeagueFarm extends BaseModel {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static async findPlantedByFarmId(configId: number, leagueCode: string, farmId: number) {
|
public static async findPlantedByFarmId(configId: number, leagueCode: string, farmId: number) {
|
||||||
const result: GVGLeagueFarmType[] = await GVGLeagueFarmModel.find({ configId, leagueCode, farmId, unlockTime: { $gte: nowSeconds() }, harvestTime: { $gte: nowSeconds() }}).select('-_id').lean();
|
const result: GVGLeagueFarmType[] = await GVGLeagueFarmModel.find({ configId, leagueCode, farmId, unlockTime: { $gte: nowSeconds() }, harvestTime: { $gte: nowSeconds() }}).select('-_id').lean();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static async findByFieldIds(configId: number, leagueCode: string, farmId: number, fieldIds: number[]) {
|
||||||
|
const result: GVGLeagueFarmType[] = await GVGLeagueFarmModel.find({ configId, leagueCode, farmId, fieldId: { $in: fieldIds } }).select('-_id').lean();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 首次打开页面时锁定田
|
* 首次打开页面时锁定田
|
||||||
* @param configId
|
* @param configId
|
||||||
@@ -76,7 +91,7 @@ export default class GVGLeagueFarm extends BaseModel {
|
|||||||
return { updateOne: { filter: { configId, leagueCode, farmId, fieldId }, update: { $setOnInsert: { unlockTime: 0, harvestTime: 0, seedType: 0, addType: 0 } }, upsert: true} }
|
return { updateOne: { filter: { configId, leagueCode, farmId, fieldId }, update: { $setOnInsert: { unlockTime: 0, harvestTime: 0, seedType: 0, addType: 0 } }, upsert: true} }
|
||||||
}));
|
}));
|
||||||
const result = await GVGLeagueFarmModel.bulkWrite(lands.map(({ fieldId, addType }) => {
|
const result = await GVGLeagueFarmModel.bulkWrite(lands.map(({ fieldId, addType }) => {
|
||||||
return { updateOne: { filter: { configId, leagueCode, farmId, fieldId, unlockTime: { $lt: nowSeconds() } }, update: { $set: { addType, unlockTime: nowSeconds() + GVG.GVG_FARM_LOCK_TIME, lockRoleId: roleId } } } }
|
return { updateOne: { filter: { configId, leagueCode, farmId, fieldId, $or:[{ unlockTime: { $lt: nowSeconds() }}, {lockRoleId: roleId} ] }, update: { $set: { addType, unlockTime: nowSeconds() + GVG.GVG_FARM_LOCK_TIME, lockRoleId: roleId } } } }
|
||||||
}));
|
}));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -86,10 +101,10 @@ export default class GVGLeagueFarm extends BaseModel {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async plant(configId: number, leagueCode: string, farmId: number, fields: { fieldId: number, seedType: number, time: number }[], roleId: string) {
|
public static async plant(configId: number, leagueCode: string, farmId: number, fields: { fieldId: number, seedType: number, time: number, output: number, outputStr: string }[], roleId: string) {
|
||||||
const batchCode = genCode(10);
|
const batchCode = genCode(10);
|
||||||
const result = await GVGLeagueFarmModel.bulkWrite(fields.map(({ fieldId, seedType, time }) => {
|
const result = await GVGLeagueFarmModel.bulkWrite(fields.map(({ fieldId, seedType, time, output, outputStr }) => {
|
||||||
return { updateOne: { filter: { configId, leagueCode, farmId, fieldId, lockRoleId: roleId }, update: { $set: { seedType, unlockTime: getFutureTime(), harvestTime: nowSeconds() + time, batchCode }} } }
|
return { updateOne: { filter: { configId, leagueCode, farmId, fieldId, lockRoleId: roleId }, update: { $set: { seedType, unlockTime: getFutureTime(), harvestTime: nowSeconds() + time, batchCode, output, outputStr }} } }
|
||||||
}));
|
}));
|
||||||
if(result.modifiedCount == 0) return [];
|
if(result.modifiedCount == 0) return [];
|
||||||
const fieldResult: GVGLeagueFarmType[] = await GVGLeagueFarmModel.find({ batchCode }).sort({ fieldId: 1 }).select('-_id -createdAt -updatedAt -__v -configId -leagueCode').lean();
|
const fieldResult: GVGLeagueFarmType[] = await GVGLeagueFarmModel.find({ batchCode }).sort({ fieldId: 1 }).select('-_id -createdAt -updatedAt -__v -configId -leagueCode').lean();
|
||||||
@@ -116,6 +131,29 @@ export default class GVGLeagueFarm extends BaseModel {
|
|||||||
public static async releaseLock(configId: number, leagueCode: string, farmId: number, roleId: string) {
|
public static async releaseLock(configId: number, leagueCode: string, farmId: number, roleId: string) {
|
||||||
await GVGLeagueFarmModel.updateMany({ configId, leagueCode, farmId, lockRoleId: roleId }, { $set: { unlockTime: 0, lockRoleId: '' } });
|
await GVGLeagueFarmModel.updateMany({ configId, leagueCode, farmId, lockRoleId: roleId }, { $set: { unlockTime: 0, lockRoleId: '' } });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static async lockMineOrForestry(configId: number, leagueCode: string, farmId: number, type: number, roleId: string, fieldId: number, itemId: number) {
|
||||||
|
// 先创建
|
||||||
|
await GVGLeagueFarmModel.findOneAndUpdate({ configId, leagueCode, farmId, fieldId }, { $setOnInsert: { unlockTime: 0, itemId: 0, type } }, { upsert: true });
|
||||||
|
const result: GVGLeagueFarmType = await GVGLeagueFarmModel.findOneAndUpdate(
|
||||||
|
{ configId, leagueCode, farmId, fieldId, $or:[{ unlockTime: { $lt: nowSeconds() } }, {lockRoleId: roleId}] },
|
||||||
|
{ $set: { unlockTime: nowSeconds() + GVG.GVG_FARM_LOCK_TIME, lockRoleId: roleId, itemId } },
|
||||||
|
{ new: true }).lean();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async findByField(configId: number, leagueCode: string, farmId: number, fieldId: number) {
|
||||||
|
const result: GVGLeagueFarmType = await GVGLeagueFarmModel.findOne({ configId, leagueCode, farmId, fieldId }).lean();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async mineOrForestryEnd(configId: number, leagueCode: string, farmId: number, roleId: string, fieldId: number, output: number, outputStr: string) {
|
||||||
|
const result: GVGLeagueFarmType = await GVGLeagueFarmModel.findOneAndUpdate(
|
||||||
|
{ configId, leagueCode, farmId, fieldId, lockRoleId: roleId,unlockTime: { $gte: nowSeconds() } },
|
||||||
|
{ $set: { output, outputStr, unlockTime: getFutureTime(), harvestTime: nowSeconds() } },
|
||||||
|
{ new: true }).lean();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const GVGLeagueFarmModel = getModelForClass(GVGLeagueFarm);
|
export const GVGLeagueFarmModel = getModelForClass(GVGLeagueFarm);
|
||||||
|
|||||||
@@ -0,0 +1,72 @@
|
|||||||
|
// 仅记录农场农田的记录,因为一块田可以反复被不同人种植、收获,不像矿场林场就是固定次数
|
||||||
|
|
||||||
|
import BaseModel from './BaseModel';
|
||||||
|
import { index, getModelForClass, prop, DocumentType, } from '@typegoose/typegoose';
|
||||||
|
import { GVGLeagueFarmType } from './GVGLeagueFarm';
|
||||||
|
|
||||||
|
@index({ leagueCode: 1, configId: 1, farmId: 1, fieldId: 1 })
|
||||||
|
export default class GVGLeagueFarmRec extends BaseModel {
|
||||||
|
|
||||||
|
@prop({ required: true })
|
||||||
|
leagueCode: string; // 联军唯一code
|
||||||
|
|
||||||
|
@prop({ required: true })
|
||||||
|
configId: number;
|
||||||
|
|
||||||
|
@prop({ required: true })
|
||||||
|
farmId: number; // 农庄id
|
||||||
|
|
||||||
|
@prop({ required: true })
|
||||||
|
type: number; // 农庄类型
|
||||||
|
|
||||||
|
@prop({ required: true })
|
||||||
|
fieldId: number; // 农庄id
|
||||||
|
|
||||||
|
@prop({ required: true })
|
||||||
|
startRoleId: string; // 种田玩家/开始游戏玩家
|
||||||
|
|
||||||
|
@prop({ required: true })
|
||||||
|
startTime: Date; // 种值时间/开始时间
|
||||||
|
|
||||||
|
@prop({ required: false })
|
||||||
|
addType: number; // 种子加成
|
||||||
|
|
||||||
|
@prop({ required: false })
|
||||||
|
seedType: number; // 实际种的种子类型
|
||||||
|
|
||||||
|
@prop({ required: false })
|
||||||
|
itemId: number; // 实际种的种子类型
|
||||||
|
|
||||||
|
@prop({ required: false })
|
||||||
|
endRoleId: string; // 收获玩家/结束游戏玩家
|
||||||
|
|
||||||
|
@prop({ required: false })
|
||||||
|
endTime: Date; // 收获时间/结束时间
|
||||||
|
|
||||||
|
@prop({ required: false })
|
||||||
|
output: number; // 产量
|
||||||
|
|
||||||
|
@prop({ required: false })
|
||||||
|
outputStr: number; // 产量计算公式
|
||||||
|
|
||||||
|
public static async insertRecs(params: GVGLeagueFarmType[]) {
|
||||||
|
let insertParams = params.map(field => {
|
||||||
|
return { ...field, startRoleId: field.lockRoleId, startTime: new Date() }
|
||||||
|
})
|
||||||
|
await GVGLeagueFarmRecModel.insertMany(insertParams);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async updateRecs(params: GVGLeagueFarmType[], roleId: string) {
|
||||||
|
if(params.length == 0) return;
|
||||||
|
let { configId, leagueCode, farmId } = params[0];
|
||||||
|
let fieldIds = params.map(cur => cur.fieldId);
|
||||||
|
await GVGLeagueFarmRecModel.updateMany({ configId, leagueCode, farmId, fieldId: { $in: fieldIds } }, { $set: { endRoleId: roleId, endTime: new Date() } });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const GVGLeagueFarmRecModel = getModelForClass(GVGLeagueFarmRec);
|
||||||
|
|
||||||
|
export interface GVGLeagueFarmRecType extends Pick<DocumentType<GVGLeagueFarmRec>, keyof GVGLeagueFarmRec> {
|
||||||
|
id: number;
|
||||||
|
};
|
||||||
|
export type GVGLeagueFarmRecUpdate = Partial<GVGLeagueFarmRecType>; // 将所有字段变成可选项
|
||||||
@@ -42,16 +42,14 @@ export default class GVGUserItem extends BaseModel {
|
|||||||
public static async decreaseItem(configId: number, leagueCode: string, roleId: string, items: RewardInter[]) {
|
public static async decreaseItem(configId: number, leagueCode: string, roleId: string, items: RewardInter[]) {
|
||||||
const result = await GVGUserItemModel.bulkWrite(items.map(({ id, count }) => {
|
const result = await GVGUserItemModel.bulkWrite(items.map(({ id, count }) => {
|
||||||
let filter = { configId, leagueCode, roleId, id, count: { $gte: count }, expireTime: { $gte: nowSeconds() } }
|
let filter = { configId, leagueCode, roleId, id, count: { $gte: count }, expireTime: { $gte: nowSeconds() } }
|
||||||
console.log('#### filter', filter, )
|
|
||||||
return { updateOne: { filter, update: { $inc: { count: -1 * count } } } }
|
return { updateOne: { filter, update: { $inc: { count: -1 * count } } } }
|
||||||
}));
|
}));
|
||||||
console.log(result.matchedCount, items.length)
|
console.log(result.matchedCount, items.length)
|
||||||
return result.matchedCount == items.length;
|
return result.matchedCount == items.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async findByItem(configId: number, leagueCode: string, roleId: string, id: number) {
|
public static async checkItemCnt(configId: number, leagueCode: string, roleId: string, id: number, count: number) {
|
||||||
const result: GVGUserItemType = await GVGUserItemModel.findOne({ configId, leagueCode, roleId, id }).select('count').lean();
|
return await GVGUserItemModel.exists({ configId, leagueCode, roleId, id, count: { $gte: count } });
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -90,6 +90,7 @@ export class GVGMainData {
|
|||||||
setLeague(league: GVGLeagueType, serverNames: any) {
|
setLeague(league: GVGLeagueType, serverNames: any) {
|
||||||
if(!league) return;
|
if(!league) return;
|
||||||
this.hasLeague = true;
|
this.hasLeague = true;
|
||||||
|
this.leagueCode = league.leagueCode;
|
||||||
let leader = <RoleType>league.leader;
|
let leader = <RoleType>league.leader;
|
||||||
this.leader = new LeagueLeaderInfo(leader, serverNames);
|
this.leader = new LeagueLeaderInfo(leader, serverNames);
|
||||||
this.name = league.name;
|
this.name = league.name;
|
||||||
@@ -338,9 +339,11 @@ export class LeagueFarmMember {
|
|||||||
this.count = fields.length;
|
this.count = fields.length;
|
||||||
this.harvestTime = Math.min(...fields.map(cur => cur.harvestTime))||0;
|
this.harvestTime = Math.min(...fields.map(cur => cur.harvestTime))||0;
|
||||||
this.canHelp = !!fields.find(cur => cur.harvestTime < nowSeconds());
|
this.canHelp = !!fields.find(cur => cur.harvestTime < nowSeconds());
|
||||||
|
this.output = fields.reduce((pre, cur) => (pre + cur.output||0), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
setOutput(output: number) {
|
setByMines(mines: GVGLeagueFarmType[]) {
|
||||||
this.output = output;
|
this.count = mines.length;
|
||||||
|
this.output = mines.reduce((pre, cur) => (pre + cur.output||0), 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -385,7 +385,8 @@ export const GVG = {
|
|||||||
GVG_ARMY_LEAGUE_TIME: 3, // GVG开启军团等级开启限制
|
GVG_ARMY_LEAGUE_TIME: 3, // GVG开启军团等级开启限制
|
||||||
GVG_ROLE_TYPE: '1&贤臣|2&猛将', // GVG中职能选择
|
GVG_ROLE_TYPE: '1&贤臣|2&猛将', // GVG中职能选择
|
||||||
GVG_SP_FIELD_ADD: 0.2,
|
GVG_SP_FIELD_ADD: 0.2,
|
||||||
GVG_FARM_LOCK_TIME: 180,
|
|
||||||
GVG_FIELD_TYPE_RATIO: '1&10|2&20|3&10',
|
GVG_FIELD_TYPE_RATIO: '1&10|2&20|3&10',
|
||||||
GVG_SP_FIELD_RATIO: '30&60',
|
GVG_SP_FIELD_RATIO: '30&60',
|
||||||
|
GVG_FARM_LOCK_TIME: 180,
|
||||||
|
GVG_MINE_LOCK_TIME: 180,
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user