128 lines
5.4 KiB
TypeScript
128 lines
5.4 KiB
TypeScript
/**
|
||
* 体力系统
|
||
*/
|
||
|
||
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;
|
||
} |