Files
ZYZ/game-server/app/services/battleService.ts

654 lines
24 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { HeroModel } from './../db/Hero';
import { HangUpRecordModel } from './../db/HangUpRecord';
import { HANG_UP_CONSTS, REDIS_KEY, TASK_TYPE, TOWER_FORBIDDEN_CHARA_TYPE, TOWER_TASK_STATUS, MAIL_TYPE } from './../consts';
import { BattleRecordModel } from './../db/BattleRecord';
import { TowerRecordModel } from './../db/TowerRecord';
import { RoleModel, RoleType } from './../db/Role';
import { shouldRefresh, resResult, cal, getRandEelmWithWeight, genCode, } from '../pubUtils/util';
import { STATUS } from '../consts/statusCode';
import { HangUpSpdUpRecModel } from '../db/HangUpSpdUpRec';
import { TaskHero, TowerTaskRecModel, TowerTaskRecType } from '../db/TowerTaskRec';
import { cloneDeep } from 'lodash';
import { Rank } from './rankService';
import { checkActivityTask, checkTask } from './taskService';
import { getRandExpedition, gameData } from '../pubUtils/data';
import { ItemInter, RewardInter } from '../pubUtils/interface';
import { getTimeFunM } from '../pubUtils/timeUtil';
import { ComRoleStatusHero } from '../db/ComBattleTeam';
import { sendMailByContent } from './mailService';
import { DicTowerTask } from '../pubUtils/dictionary/DicTowerTask';
import * as dicParam from '../pubUtils/dicParam';
/**
* 获取当前镇念塔状态
* @param role
*/
export async function getTowerStatus(role: RoleType) {
let { towerLv, roleId, serverId } = role;
if (!towerLv) {
let role = await RoleModel.towerLvUp(roleId);
towerLv = role.towerLv;
}
let towerRec = await TowerRecordModel.getRecordByLv(roleId, towerLv);
if (!towerRec) {
const towerInfo = gameData.tower.get(towerLv);
const { warArray } = towerInfo;
const sts = warArray.map(id => {
return {warId: id, status: false};
});
towerRec = await TowerRecordModel.createRecord({roleId, lv: towerLv, warStatus: sts});
// return { code: 201, data: '天梯记录异常' };
}
return {
canHungUp: towerLv - 1 >= dicParam.TOWER_HANG_UP.TOWER_HANG_UP_ENABLE_LV,
hungUpEnableLv: dicParam.TOWER_HANG_UP.TOWER_HANG_UP_ENABLE_LV,
canSendTask: towerLv - 1 >= dicParam.TOWER_SEARCH.TOWER_SEARCH_STARTLIMITED,
sendTaskEnableLv: dicParam.TOWER_SEARCH.TOWER_SEARCH_STARTLIMITED,
curLv: towerLv,
usedHeroes: towerRec.heroes,
progress: towerRec.warStatus
};
}
/**
* 获取镇念塔挂机收益
* @param roleId
*/
export async function getHungupRewards(roleId: string) {
const result = await calcuHangUpReward(roleId);
if(result.status == -1) {
return result;
}
let {timeReward, startTime, deltaTime} = result.data;
let {hangUpSpdUpCnt = 0, lastSpdUpTime} = await RoleModel.findByRoleId(roleId);
let curTime = new Date();
if (shouldRefresh(lastSpdUpTime, curTime)) {
hangUpSpdUpCnt = 0;
}
let nextCostGold = getManyHangSpdUpCostGold(hangUpSpdUpCnt, 1);
return {
status: 0,
resResult: null,
data: {
startTime, hangUpPassTime: Math.floor(deltaTime/1000), hangUpSpdUpCnt: dicParam.TOWER_BOOST.TOWER_BOOSTTIME - hangUpSpdUpCnt, nextCostGold, rewards: timeReward
}
}
}
/**
* 获取派遣任务列表
* @param role
*/
export async function getTasks(role: RoleType) {
let { roleId, roleName, towerLv, towerTaskRefTime, towerTaskReCnt = 0 } = role;
// towerLv从1开始下次打得层数dicParam内的从0开始打过的层数
if(towerLv - 1 < dicParam.TOWER_SEARCH.TOWER_SEARCH_STARTLIMITED) {
return {curTasks: [], refRemainTime: 0, nextCostGold: 0}
}
let curTime = new Date();
let curTasks = await TowerTaskRecModel.getCurTasks(roleId); // 当前显示中的任务
const needRefresh = shouldRefresh(towerTaskRefTime, curTime);
if(needRefresh) {
const batchCode = genCode(8);
let preTasks = await TowerTaskRecModel.getPreTasks(roleId);
if(preTasks && preTasks.length) {
let checkResult = checkTaskRewards(preTasks[0].batchCode, preTasks );
if(!checkResult) return false;
await sendMailByContent(MAIL_TYPE.TOWER_TASK_REWARD, roleId, { goods: checkResult.rewards });
await TowerTaskRecModel.finishTask(preTasks[0].batchCode, preTasks.map(cur => cur.taskCode));
}
curTasks = await refreshTasks(towerLv, batchCode, roleId, roleName, []); // 新建任务
// 重置派遣次数
role = await RoleModel.resetTowerCnt(roleId, curTime);
towerTaskReCnt = role.towerTaskReCnt;
}
let refRemainTime = getRemainTime(curTime);
let nextCostGold = getTowerTaskCostGold(role.towerTaskReCnt, role.towerTaskRefTime);
return {curTasks: treatTask(curTasks, curTime), refRemainTime, nextCostGold}
}
export function checkTaskRewards(batchCode: string, tasks: TowerTaskRecType[]) {
const curTime = new Date();
let compTasks: string[] = [];
let rewards: RewardInter[] = [];
for (let task of tasks) {
if(task.batchCode != batchCode) return false;
if ( task.status === TOWER_TASK_STATUS.DOINING) {
let {completeTime, reward, termsForAdd, additionalReward} = gameData.towerTask.get(task.taskId);
if (task.sendTime && task.sendTime.getTime() + completeTime * 1000 < curTime.getTime()) {
compTasks.push(task.taskCode);
rewards.push(...reward);
if(termsForAdd) {
const result = checkTaskConditions(task.heroes, termsForAdd);
if(result) {
rewards.push(...additionalReward);
}
}
}
}
}
return { compTasks, rewards };
}
export async function checkTowerWar(roleId: string, battleId: number, seqIds: number[], heroes: Array<number>) {
let { towerLv } = await RoleModel.findByRoleId(roleId);
const towerInfo = gameData.tower.get(towerLv);
if (!towerInfo) {
console.error(`天梯层数异常lv ${towerLv} by ${roleId}`);
return { status: -1, resResult: resResult(STATUS.TOWER_INFO_NOT_FOUND) };
}
const warIds = towerInfo.warArray;
if (warIds.indexOf(battleId) === -1) {
return { status: -1, resResult: resResult(STATUS.TOWER_WRONG_BATTLE_ID) };
}
const tower = await TowerRecordModel.getRecordByLv(roleId, towerLv);
if (!tower) {
return { status: -1, resResult: resResult(STATUS.TOWER_NOT_FOUND) };
}
let { heroes: recHeroes = [], warStatus = [] } = tower;
let dicWar = gameData.war.get(battleId);
let { fobiddenCharactor } = dicWar;
for (let hid of seqIds) {
if (recHeroes.indexOf(hid) !== -1) {
return { status: -1, resResult: resResult(STATUS.TOWER_DUPLICATE_HERO) };
}
}
for(let hid of heroes) {
if(checkForbiddenChar(hid, fobiddenCharactor)) {
return { status: -1, resResult: resResult(STATUS.TOWER_HERO_FORBIDDEN) };
}
}
const curWarStatus = warStatus.find(elem => elem.warId == battleId);
if (curWarStatus && curWarStatus.status) {
return { status: -1, resResult: resResult(STATUS.TOWER_DUPLICATE_CHALLENGE) };
}
return {
status: 0, data: {
heroes: recHeroes, warStatus: curWarStatus
}
};
}
function checkForbiddenChar(hid: number, fobiddenCharactor: {type: number, id: number}[]) {
let dicHero = gameData.hero.get(hid);
let dicJob = gameData.job.get(dicHero.jobid);
let flag = false;
for(let { type, id } of fobiddenCharactor) {
switch(type) {
case TOWER_FORBIDDEN_CHARA_TYPE.CHAR:
if(id == hid) flag = true;
break;
case TOWER_FORBIDDEN_CHARA_TYPE.JOB:
if(id == dicJob.job_class) flag = true;
break;
case TOWER_FORBIDDEN_CHARA_TYPE.CAMP:
if(id == dicHero.camp) flag = true;
break;
}
if(flag) break;
}
return flag;
}
export async function towerBattleEnd(sid: string, roleId: string, serverId: number, battleCode: string, battleId: number, succeed: boolean, heroes: Array<number>) {
if (succeed) {
let battleRec = await BattleRecordModel.getBattleRecordByCode(battleCode);
if (battleRec.battleId != battleId) {
return { status: -1, resResult: resResult(STATUS.BATTLE_ID_NOT_MATCH) };
}
let { towerLv, roleName } = await RoleModel.findByRoleId(roleId);
let { warStatus, heroes: recHeroes } = await TowerRecordModel.getRecordByLv(roleId, towerLv);
// console.log('*******', towerLv, heroes.join(), recHeroes.join())
for (let hid of heroes) {
if (recHeroes.indexOf(hid) !== -1) {
return { status: -1, resResult: resResult(STATUS.TOWER_DUPLICATE_HERO) };
}
}
let inc = 1;
warStatus.forEach(st => {
if (st.warId !== battleId && st.status === false) {
inc = 0;
}
})
let newRec = await TowerRecordModel.updateRecord(roleId, towerLv, battleCode, battleId, heroes, inc);
let towerReward: RewardInter[] = null;
if (inc === 1) {
let role = await RoleModel.towerLvUp(roleId);
// 更新redis
let r = new Rank(REDIS_KEY.TOWER_RANK, { serverId });
await r.setRankWithRoleInfo(roleId, role.towerLv - 1, role.towerUpTime.getTime(), role);
const nextTowerInfo = gameData.tower.get(role.towerLv);
if (nextTowerInfo) {
const { warArray } = nextTowerInfo;
const sts = warArray.map(id => {
return { warId: id, status: false };
});
await TowerRecordModel.createRecord({ roleId, lv: role.towerLv, warStatus: sts });
}
const { reward } = gameData.tower.get(role.towerLv - 1);
if (reward) towerReward = reward;
if (role.towerLv == dicParam.TOWER_HANG_UP.TOWER_HANG_UP_ENABLE_LV + 1) {
await startHangUp(roleId, roleName);
}
// 任务
await checkTask(roleId, sid, TASK_TYPE.BATTLE_TOWER_LV, role.towerLv - 1, false, {});
await checkActivityTask(serverId, sid, roleId, TASK_TYPE.BATTLE_TOWER_LV, 1, { towerLv: role.towerLv - 1 });
}
return {
status: 0,
data: {
newRec,
towerReward,
towerStatus: !!inc
}
};
}
}
async function startHangUp(roleId: string, roleName: string) {
await HangUpRecordModel.initRecord(roleId, roleName);
}
export async function checkHangUpSpdUpCnt(roleId: string, cnt: number, curTime: Date) {
const role = await RoleModel.findByRoleId(roleId);
let { hangUpSpdUpCnt, gold, lastSpdUpTime } = role;
if (shouldRefresh(lastSpdUpTime, curTime)) {
hangUpSpdUpCnt = 0;
}
if (cnt + hangUpSpdUpCnt > dicParam.TOWER_BOOST.TOWER_BOOSTTIME) {
return { status: -1, resResult: resResult(STATUS.TOWER_NOT_ENOUGH_HANG_UP_TIME) }
}
return { status: 0, data: { hangUpSpdUpCnt, gold, lastSpdUpTime } }
}
export async function calcuHangUpReward(roleId: string, speedUp = false, speedUpCnt = 1, curTime = new Date()) {
let { towerLv = 1, hangUpSpdUpCnt = 0, lastSpdUpTime } = await RoleModel.findByRoleId(roleId);
if (towerLv - 1 < dicParam.TOWER_HANG_UP.TOWER_HANG_UP_ENABLE_LV) {
return { status: -1, resResult: resResult(STATUS.TOWER_HANG_UP_NOT_START) }
}
let towerInfo = gameData.tower.get(towerLv - 1); // towerLv 是当前层,奖励计算按照已经通过的层,即上一层
let timeReward = []; // 奖励
let needReceiveGoods = []; // 由于小数,未能领取的奖励
let baseReward = towerInfo.rewardOfcollect;
let { startTime } = await HangUpRecordModel.getCurRec(roleId);
let endTime = curTime; // 挂机结束时间现在到开始时间经历了10的倍数的时间
let deltaTime = curTime.getTime() - startTime.getTime(); // 累计的挂机时间,受最大时间限制
if (deltaTime > HANG_UP_CONSTS.MAX_TIME) {
deltaTime = HANG_UP_CONSTS.MAX_TIME;
endTime = curTime; // 累积到超过24小时那么结束时间和下一次开启时间就取整了
} else {
let multiReal = Math.floor(deltaTime / HANG_UP_CONSTS.UNIT_TIME);// 距开始挂机实际过去的时间单位
endTime = new Date(startTime.getTime() + multiReal * HANG_UP_CONSTS.UNIT_TIME)
}
if (speedUp) { // 加速直接收取6小时收益小数的累积和普通收取独立
if (hangUpSpdUpCnt + speedUpCnt <= dicParam.TOWER_BOOST.TOWER_BOOSTTIME || !lastSpdUpTime || shouldRefresh(lastSpdUpTime, new Date)) { // 可加速
let multi = Math.floor(HANG_UP_CONSTS.SPD_UP_REC_TIME / HANG_UP_CONSTS.UNIT_TIME);
let spdUpRec = await HangUpSpdUpRecModel.getSpdUpRec(roleId, towerLv - 1);
let goods = [];
if (spdUpRec) {
let { notReceivedGoodsList = [], cnt } = spdUpRec;
let notReceivedGoods = notReceivedGoodsList.find(cur => cur.cnt == cnt);
goods = notReceivedGoods ? notReceivedGoods.goods : [];
}
for (let { id, count } of baseReward) {
let newCount = cal.mul(count, multi);
let oldGoods = goods.find(cur => cur.gid == id);
if (oldGoods) newCount = cal.add(newCount, oldGoods.count);
let roundCount = Math.floor(newCount);
if (newCount > roundCount) {
needReceiveGoods.push({ gid: id, count: cal.sub(newCount, roundCount) });
}
if (roundCount > 0) {
timeReward.push({ id, count: roundCount })
}
}
}
} else {
let lastRec = await HangUpRecordModel.getLastRec(roleId);
let notReceivedGoods = lastRec ? lastRec.notReceivedGoods : [];
let multi = Math.floor(deltaTime / HANG_UP_CONSTS.UNIT_TIME); // 结算奖励的倍数,受最大时间限制
// console.log(deltaTime, multi, baseReward);
for (let { id, count } of baseReward) {
let newCount = cal.mul(count, multi);
let oldGoods = notReceivedGoods.find(cur => cur.gid == id);
if (oldGoods) newCount = cal.add(newCount, oldGoods.count);
let roundCount = Math.floor(newCount);
if (newCount > roundCount) {
needReceiveGoods.push({ gid: id, count: cal.sub(newCount, roundCount) });
}
if (roundCount > 0) {
timeReward.push({ id, count: roundCount })
}
}
}
return {
status: 0,
data: {
endLv: towerLv - 1,
startTime,
deltaTime,
endTime,
timeReward,
needReceiveGoods
}
};
}
function checkCond(heroes: TaskHero[], type: number, param: number, cnt: number) {
let heroCnt = 0;
switch (type) {
case 1:
for (let { star, colorStar } of heroes) {
if (star + colorStar >= param) {
heroCnt++;
}
}
break;
case 2:
for (let { camp } of heroes) {
if (camp === param) {
heroCnt++;
}
}
break;
case 3:
for (let { jobClass } of heroes) {
if (jobClass === param) {
heroCnt++;
}
}
break;
default:
break;
}
if (heroCnt >= cnt) {
return true;
}
return false;
}
export function checkTaskConditions(heroes: TaskHero[], condition: { type: number, param: number, count: number }[]) {
let res = true;
for (let { type, param, count } of condition) {
const checkRes = checkCond(heroes, type, param, count);
if (!checkRes) {
res = false;
break;
}
}
return res;
}
export async function refreshTasks(towerLv: number, batchCode: string, roleId: string, roleName: string, oldTasks:TowerTaskRecType[]) {
let needFloor = !oldTasks || oldTasks.length <= 0; // 首次刷新需要一个保底
let ridTaskIds: number[] = [];
let positions = new Map<number, TowerTaskRecType> (); // 需要创建或更新
for(let i = 1; i <= dicParam.TOWER_SEARCH.TOWER_SEARCH_LIMITED; i++) {
positions.set(i, null);
}
let tasks: TowerTaskRecType[] = [];
for(let task of oldTasks) {
if( task.status == TOWER_TASK_STATUS.WAITING ) {
positions.set(task.position, task);
} else {
positions.delete(task.position);
ridTaskIds.push(task.taskId);
tasks.push(task);
}
}
for(let [ position, task ] of positions) {
let dicOldTask = task? gameData.towerTask.get(task.taskId): null;
let dicTask = randomTask(towerLv, dicOldTask?dicOldTask.quality: 0, ridTaskIds);
if(!dicTask) break; // 任务池没有可刷新了
let { taskId, quality } = dicTask;
if(quality == 4 || quality == 5) needFloor = false;
if(task) { // 更新
tasks.push(await TowerTaskRecModel.updateTask(roleId, batchCode, position, taskId));
} else {
tasks.push(await TowerTaskRecModel.createTask(roleId, roleName, batchCode, taskId, position));
}
ridTaskIds.push(taskId);
}
if(needFloor) { // 塞一个保底
let dicTask = randomTask(towerLv, 3, ridTaskIds);
if(dicTask) {
let index = Math.floor(Math.random() * tasks.length);
tasks[index] = await TowerTaskRecModel.updateTask(roleId, batchCode, tasks[index].position, dicTask.taskId);
}
}
return tasks
}
function randomTask(towerLv: number, oldQuality: number, rids: number[]) {
let qualityRange = oldQuality + 1;
let randomList: DicTowerTask[] = [];
while(randomList.length <= 0) { // 如果这个品质范围里面没有,就降一品质再找
for (let [_id, task] of gameData.towerTask) {
if(task.quality >= qualityRange && !rids.includes(task.taskId)) {
let { suitFloor: { min, max } } = task;
let flag = max ? (towerLv >= min && towerLv <= max) : (towerLv >= min);
if (flag) {
randomList.push(task);
}
}
}
if(randomList.length <= 0) qualityRange--;
if(qualityRange == 0) return null;
}
let { dic } = getRandEelmWithWeight(randomList);
return dic;
}
// /**
// * 创建新的派遣任务
// * @param towerLv 玩家层数
// * @param roleId 玩家id
// * @param roleName 玩家名
// * @param hideNum 隐藏的任务数量
// */
// export async function createCurTasks(towerLv: number, batchCode: string, roleId: string, roleName: string, hideNum: number, showNum: number, rids: Array<number>) {
// let returnTasks = new Array();
// const arr = [{ refreshStatus: 0, num: hideNum }, { refreshStatus: 1, num: showNum }];
// for (let { refreshStatus, num } of arr) {
// let taskIds = [];
// for (let i = 0; i < num; i++) {
// }
// const curTasks = await TowerTaskRecModel.createTasks(roleId, roleName, batchCode, taskIds, refreshStatus);
// if (refreshStatus == 1) {
// returnTasks = curTasks;
// }
// }
// return returnTasks;
// }
export function getRemainTime(curTime: Date) {
let nextTime = <number>getTimeFunM(curTime).getAfterDayWithHour(1);
return Math.floor((nextTime - curTime.getTime()) / 1000);
}
export function treatTask(recs: Array<TowerTaskRecType>, curTime: Date) {
return recs.map(cur => {
let { heroes, batchCode, taskId, taskCode, status, completeTime, position } = cur;
let getStatusResult = getTaskStatus(status, completeTime, curTime);
return { position, heroes, batchCode, taskId, taskCode, completeTime, ...getStatusResult }
}).sort((a, b) => {
return a.position - b.position;
});
}
// 刷新任务,正在进行中的部分保留,没有进行中的刷掉
export function getDoingOrWaitingTasks(taskList: Array<any>, curTime: Date) {
let doingTaskCode = new Array<string>(), waitingTaskCode = new Array<string>(), doingIds = new Array<number>();
for (let task of taskList) {
let { status } = getTaskStatus(task.status, task.completeTime, curTime);
if (status == 1 || status == 2) {
doingTaskCode.push(task.taskCode);
doingIds.push(task.taskId);
} else if (status == 0 || status == 3) {
waitingTaskCode.push(task.taskCode);
}
}
return { doingTaskCode, waitingTaskCode, doingIds }
}
export function getTaskStatus(status: number, completeTime: Date, curTime: Date) {
let remainTime = 0;
if (status == 1) {
// console.log(curTime.getTime(), completeTime.getTime())
remainTime = Math.floor((completeTime.getTime() - curTime.getTime()) / 1000);
if (remainTime < 0) {
status = 2; remainTime = 0;
}
}
return { status, remainTime }
}
export async function getTasksReward(roleId: string, curTime: Date) {
let oldTasks = await TowerTaskRecModel.getCurTasks(roleId);
let goods: ItemInter[] = [];
for (let task of oldTasks) {
let { completeTime, reward, termsForAdd, additionalReward } = gameData.towerTask.get(task.taskId);
if (task.sendTime && task.sendTime.getTime() + completeTime * 1000 < curTime.getTime()) {
goods = goods.concat(reward);
if (termsForAdd) {
const result = checkTaskConditions(task.heroes, termsForAdd);
if (result) {
goods.push(...additionalReward);
}
}
}
}
return goods
}
/**
* 获取随机机器人数据
* @param cnt 机器人数量
* @param withAttr 是否返回属性false: 仅返回阵容
*/
export function getRandRobot(cnt = 1, withAttr = false) {
let setInfo = getRandExpedition(cnt);
if (!setInfo || setInfo.length !== cnt) return null;
let robots = [];
for (let info of setInfo) {
if (!info || !info.warId) continue;
const warInfo = gameData.warJson.get(info.warId);
if (!warInfo || !warInfo.length) continue;
let heroes: ComRoleStatusHero[] = [];
for (let hero of warInfo) {
if (hero && hero.relation === 2 && hero.actorId) {
let dicHero = gameData.hero.get(hero.actorId);
heroes.push({
id: hero.actorId,
skinId: hero.actorId,
star: hero.star||dicHero.initialStars,
colorStar: 0,
lv: hero.lv,
quality: dicHero.quality
});
}
}
robots.push(heroes);
}
return robots;
}
/**
* 拷贝敌军数组并添加当前血量字段
* @param source 原敌军数组,不包含当前血量字段
*/
export function transBossHpArr(source: Array<{ dataId: number, hp: number, actorId: number }>): Array<{ dataId: number, hp: number, curHp: number, actorId: number }> {
let desArr = [];
source.forEach(elem => {
let { hp } = elem;
desArr.push(Object.assign(elem, { curHp: hp }));
});
return cloneDeep(desArr);
}
/**
* 获得下一次刷新派遣的花费
* @param times 玩家表上的次数
* @param refTime 玩家表上的刷新时间
* @returns
*/
export function getTowerTaskCostGold(times: number, refTime: Date) {
if(shouldRefresh(refTime, new Date())) {
times = 0;
}
let cost = (times + 1) * dicParam.TOWER_SEARCH.TOWER_SEARCH_REFRESHRULE_FEE;
if(cost > dicParam.TOWER_SEARCH.TOWER_SEARCH_REFRESHRULE_MAX) cost = dicParam.TOWER_SEARCH.TOWER_SEARCH_REFRESHRULE_MAX;
return cost;
}
/**
* 多次加速挂机消耗的元宝
* @param originCnt 玩家表里原来的次数
* @param count 这次加速几次
* @returns
*/
export function getManyHangSpdUpCostGold(originCnt: number, count: number) {
let gold = 0;
for(let i = 1; i <= count; i++) {
let num = originCnt + i;
gold += getHangSpdUpCostGold(num);
}
return gold
}
/**
* 计算加速挂机消耗的元宝
* @param times 第几次如果你没有加速过这里给1
* @returns
*/
export function getHangSpdUpCostGold(times:number) {
if(times <= dicParam.TOWER_BOOST.TOWER_BOOSTFREETIME) {
return 0
} else {
let cost = (times - dicParam.TOWER_BOOST.TOWER_BOOSTFREETIME) * dicParam.TOWER_BOOST.TOWER_BOOSTCAST;
if(cost > dicParam.TOWER_BOOST.TOWER_BOOSTCASTMAX) cost = dicParam.TOWER_BOOST.TOWER_BOOSTCASTMAX;
return cost;
}
}