Files
ZYZ/game-server/app/services/actionPointService.ts
2021-12-26 15:45:02 +08:00

128 lines
5.4 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 { ActionPointModel, ActionPointType } from '../db/ActionPoint';
import { TASK_TYPE, STATUS, TA_EVENT, ITEM_CHANGE_REASON } from '../consts';
import { checkActivityTask, checkTask } from './taskService';
import { getDicApByLv } from '../pubUtils/data';
import { pinus } from 'pinus';
import { resResult, shouldRefresh } from '../pubUtils/util';
import { RoleModel } from '../db/Role';
import { pick } from 'underscore';
import { AP } from '../pubUtils/dicParam';
import { reportTAEvent } from './sdkService';
/**
* 获取当前体力
* @param roleId 玩家id
* @param lv 玩家等级
*/
export async function getAp(roleId: string, ip: string, lv: number, fromGetAp = false) {
let dataAp = await ActionPointModel.getAp(roleId);
return getApWithDataAp(roleId, ip, lv, dataAp, fromGetAp);
}
function getApWithDataAp(roleId: string, ip: string, lv: number, dataAp: ActionPointType, fromGetAp = false) {
const now = Date.now();
const dicAp = getDicApByLv(lv);
const maxAp = dicAp.maxAp; // 最大体力值
const per = AP.PERAPRESTORETIME * 1000; // 恢复时间ms)
let { ap, refTime, buyRefTime = 0, buyTimes = 0, apBefore } = dataAp;
let oldAp = ap;
if(shouldRefresh(new Date(buyRefTime), new Date())) {
buyTimes = 0;
}
let result;
if (ap >= maxAp) {
// 体力溢出不需要做时间的处理
result = { ap, maxAp, refTime: now, apRemainTime: 0, apMaxRemainTime: 0, isOver: true, buyTimes, buyRefTime, apBefore };
} else {
if (refTime > now) refTime = now; // refTime每次记录时候最近的一个整的时间点绝对不会大于now
let n = Math.floor((now - refTime) / per); // 上次记录到现在可以增长多少体力
ap += n; // 增加上
if (ap >= maxAp) { // 加上后溢出了
ap = maxAp;
result = { ap, maxAp, refTime: now, apRemainTime: 0, apMaxRemainTime: 0, isOver: true, buyTimes, buyRefTime, apBefore };
} else {
refTime += n * per; // 更新refTime到离现在最近的一个整的时间点
let apRemainTime = Math.floor((refTime + per - now) / 1000); // 恢复下一点需要多少时间
let apMaxRemainTime = (maxAp - ap - 1) * AP.PERAPRESTORETIME + apRemainTime;
result = { ap, maxAp, refTime, apRemainTime, apMaxRemainTime, isOver: false, buyTimes, buyRefTime, apBefore };
}
}
if(result.ap > oldAp) {
reportTAEvent(roleId, TA_EVENT.AP_GET, { change_count: oldAp - result.ap, change_after: result.ap, change_reason: ITEM_CHANGE_REASON.AP_RECOVERY })
}
return fromGetAp?result: pick(result, ['ap', 'maxAp', 'apRemainTime', 'apMaxRemainTime', 'buyTimes', 'apBefore']);
}
/**
* 增加或减少体力
* @param roleId 玩家id
* @param lv 玩家等级
* @param changeAp 体力变化,正是加,负是减
* @param sid
*/
export async function setAp(roleId: string, ip: string, lv: number, changeAp: number, sid: string, reason: ITEM_CHANGE_REASON) {
console.log('***** setAp', roleId, ip, lv, changeAp)
const now = Date.now();
const dicAp = getDicApByLv(lv);
let ApResult = await getAp(roleId, ip, lv, true);
let { ap: apBefore, maxAp, refTime, apRemainTime, apMaxRemainTime, isOver, buyTimes } = ApResult; // 更新ap
let ap = apBefore + changeAp;
if (ap >= maxAp) { // 溢出
refTime = now;
apRemainTime = 0;
apMaxRemainTime = 0;
}
if (ap < 0) return null // 体力不足
let dataAp = await ActionPointModel.saveAp(roleId, ap, apBefore, refTime);
if (isOver && ap < maxAp) { // 特殊处理,溢出之后做减少体力的操作时
apRemainTime = AP.PERAPRESTORETIME;
apMaxRemainTime = (maxAp - ap) * AP.PERAPRESTORETIME;
}
if (changeAp < 0) {
await checkTask(roleId, sid, TASK_TYPE.BATTLE_COST_AP, -1 * changeAp, true, {});
let { serverId } = await RoleModel.findByRoleId(roleId);
await checkActivityTask(serverId, sid, roleId, TASK_TYPE.BATTLE_COST_AP, -1 * changeAp,);
// reportTAEvent(roleId, TA_EVENT.AP_CONSUME, { change_count: -1 * changeAp, change_after: ap, change_reason: reason }, ip)
} else {
reportTAEvent(roleId, TA_EVENT.AP_GET, { change_count: changeAp, change_after: ap, change_reason: reason }, ip)
}
let apJson = await getApWithDataAp(roleId, ip, lv, dataAp);
if (changeAp != 0) {
let uids = [{ uid: roleId, sid }];
pinus.app.get('channelService').pushMessageByUids('onApUpdate', resResult(STATUS.SUCCESS, { apJson: { ...apJson, apBefore } }), uids);
}
return apJson
}
export async function setApBuyTimes(roleId: string, ip: string, lv: number, sid: string, incTimes: number) {
if(incTimes <= 0) return false;
let ApResult = await getAp(roleId, ip, lv, true);
let { ap, maxAp, refTime, apRemainTime, apMaxRemainTime, buyTimes, buyRefTime } = ApResult; // 更新ap
if(shouldRefresh(new Date(buyRefTime), new Date())) {
buyTimes = 0;
buyRefTime = new Date();
}
buyTimes += incTimes;
await ActionPointModel.saveBuyTimes(roleId, buyTimes, buyRefTime);
let apJson = { ap, maxAp, refTime, apMaxRemainTime, apRemainTime, buyTimes };
if(incTimes != 0) {
let uids = [{ uid: roleId, sid }];
pinus.app.get('channelService').pushMessageByUids('onApUpdate', resResult(STATUS.SUCCESS, { apJson }), uids);
}
return apJson;
}