活动:弹窗活动新类型

This commit is contained in:
luying
2022-04-20 21:37:51 +08:00
parent 7b3b826167
commit 1913a4a2b9
13 changed files with 128 additions and 43 deletions

View File

@@ -276,7 +276,7 @@ export class PvpHandler {
let myRank = await r.getMyRank({ roleId });
result.setMyRank(myRank);
await checkTaskInPvpEnd(serverId, roleId, sid, isSuccess, pvpDefense.heroScores);
await checkTaskInPvpEnd(serverId, roleId, sid, isSuccess, pvpDefense.heroScores, myRank);
if(hisWinStreakNum < pvpDefense.hisWinStreakNum) {
await unlockFigure(sid, roleId, [{ type: FIGURE_UNLOCK_CONDITION.PVP_WIN_SERIES, paramWinStreakNum: pvpDefense.hisWinStreakNum }]);
}

View File

@@ -20,11 +20,6 @@ import Counter from '../../../db/Counter';
import { getExpByLv } from '../../../pubUtils/data';
import { reportTAUserSet } from '../../../services/sdkService';
import { saveLoginAndOutLog } from '../../../pubUtils/logUtil';
import { JewelModel } from '../../../db/Jewel';
import { ItemModel } from '../../../db/Item';
import { SkinModel } from '../../../db/Skin';
import { HeroParam } from '../../../domain/roleField/hero';
import { getAp } from '../../../services/actionPointService';
import { sendMessageToAllWithSuc } from '../../../services/pushService';
export default function (app: Application) {
@@ -68,7 +63,7 @@ export class EntryHandler {
}
}
let serverName = this.app.getServerId();
await roleLogin(role.roleId, user.userCode, serverName, user.pkgName, role.createTime); // 保存在线用户
await roleLogin(role.roleId, user.userCode, serverName, user.pkgName, role.createTime, role.serverId); // 保存在线用户
await this.addSession(user, role, session);
saveLoginAndOutLog(LOG_TYPE.LOGIN, session);

View File

@@ -18,6 +18,7 @@ export class GuildActivityRemote {
private currentTime: number = Date.now();
private setTime: number = Date.now();
private isAuctionPopUp: boolean = false;
/**
* 从systimer服分发到guild各个服发送排行榜数据
@@ -36,6 +37,10 @@ export class GuildActivityRemote {
public async guildActivityEnd(aid: number) {
try {
await settleGuildActivityReward(aid);
this.isAuctionPopUp = true;
setTimeout(() => { // 军团活动结束的15分钟内就不会再弹出了
this.isAuctionPopUp = false;
}, 15 * 60 * 1000);
} catch(e) {
errlogger.error(`remote ${__filename} \n ${e.stack}`);
}
@@ -147,4 +152,12 @@ export class GuildActivityRemote {
errlogger.error(`remote ${__filename} \n ${e.stack}`);
}
}
public getAuctionPopUpShow() {
try {
return this.isAuctionPopUp;
} catch(e) {
errlogger.error(`remote ${__filename} \n ${e.stack}`);
}
}
}

View File

@@ -250,7 +250,7 @@ export class EquipHandler {
let oldEplace = hero.ePlace||[];
let curEquip = oldEplace.find(cur => cur.id == ePlaceId);
if(!curEquip) return resResult(STATUS.EQUIP_NOT_FIND);
let incEquipStarSum = 0;
let equipUpdate = {
star: curEquip.star,
starStage: curEquip.starStage,
@@ -275,6 +275,7 @@ export class EquipHandler {
if(isEnough) {
equipUpdate.star = nextEquipStar.star;
equipUpdate.starStage = 0;
incEquipStarSum += equipUpdate.star - curEquip.star;
}
}
} else { // 升小点,包括一键升到满小点和升一个小点
@@ -298,9 +299,11 @@ export class EquipHandler {
ePlace: newEplace,
consumes: addConsumeToHero(hero.consumes, consumes)
}
await calculateCeWithHero(HERO_SYSTEM_TYPE.EQUIP_STAR, roleId, serverId, sid, hid, update, { ePlaceId });
await checkTaskInEquipStarUp(serverId, roleId, sid, oldEplace, newEplace, ePlaceId, hid, isUpStar);
console.log('### incEquipStarSum', incEquipStarSum)
let { curRole } = await calculateCeWithHero(HERO_SYSTEM_TYPE.EQUIP_STAR, roleId, serverId, sid, hid, update, { ePlaceId, roleIncUpdate: { equipStarSum: incEquipStarSum } });
await checkTaskInEquipStarUp(serverId, roleId, sid, oldEplace, newEplace, ePlaceId, hid, isUpStar, curRole.equipStarSum);
pushEquipStarMax(roleId, roleName, serverId, hid, newEquip, isUpStar);
const curHero = {

View File

@@ -1,4 +1,4 @@
import { ACTIVITY_TYPE, ITEM_CHANGE_REASON, POP_UP_SHOP_CONDITION_TYPE, STATUS } from '../../consts';
import { ACTIVITY_TYPE, ITEM_CHANGE_REASON, POP_UP_SHOP_CONDITION_TYPE, PUSH_BATCH, PUSH_INTERVAL, STATUS } from '../../consts';
import { ActivityModel, ActivityModelType } from '../../db/Activity';
import { PopShopItem, PopUpConditionParamInter, PopUpShopData, PopUpShopPackage, PopUpShopItemShow, } from '../../domain/activityField/popUpShopField';
import { RewardParam } from '../../domain/activityField/rewardField';
@@ -9,6 +9,9 @@ import moment = require('moment');
import { getActivitiesByType, getActivityById, pushActivities, pushActivityInter, pushSingleActivity } from './activityService';
import { RoleModel, RoleType } from '../../db/Role';
import { HeroType } from '../../db/Hero';
import { pinus } from 'pinus';
import { getRandEelm, getRandSingleEelm } from '../../pubUtils/util';
import { getAllOnlineRoles } from '../redisService';
/**
* 玩家活动数据
@@ -44,12 +47,40 @@ export async function checkPopUpConditionInCreateHero(serverId: number, roleId:
return await checkPopUpConditions(serverId, roleId, conditions);
}
export async function checkPopUpCondition(serverId: number, roleId: string, conditionType: POP_UP_SHOP_CONDITION_TYPE, param: PopUpConditionParamInter) {
return await checkPopUpConditions(serverId, roleId, [{ conditionType, param }]);
export async function checkPopUpCondition(serverId: number, roleId: string, conditionType: POP_UP_SHOP_CONDITION_TYPE, param: PopUpConditionParamInter, sid?: string) {
return await checkPopUpConditions(serverId, roleId, [{ conditionType, param }], sid);
}
export async function checkPopUpConditionInEntry(serverId: number, roleId: string, sid: string) {
let guilds = pinus.app.getServersByType('guild');
let guild = getRandSingleEelm(guilds);
let isAuctionPopUpShow = await pinus.app.rpc.guild.guildActivityRemote.getAuctionPopUpShow.toServer(guild.id);
if(isAuctionPopUpShow) {
await checkPopUpCondition(serverId, roleId, POP_UP_SHOP_CONDITION_TYPE.AUCTION, {}, sid);
}
}
export async function checkPopUpConditionWhenGuildActivityEnd() {
let allOnlineUsers = await getAllOnlineRoles();
let n = Math.ceil(allOnlineUsers.length / PUSH_BATCH); // 一共多少批
let i = -1;
let interval = setInterval(async () => {
if (++i < n) {
console.log('****', i)
let users = allOnlineUsers.slice(i * PUSH_BATCH, (i + 1) * PUSH_BATCH - 1);
console.log('****', users)
for(let { serverId, roleId, sid } of users) {
await checkPopUpCondition(serverId, roleId, POP_UP_SHOP_CONDITION_TYPE.AUCTION, {}, sid);
}
} else {
clearInterval(interval);
}
}, PUSH_INTERVAL);
}
// 弹出礼包任务
export async function checkPopUpConditions(serverId: number, roleId: string, conditions: { conditionType: POP_UP_SHOP_CONDITION_TYPE, param: PopUpConditionParamInter }[]) {
export async function checkPopUpConditions(serverId: number, roleId: string, conditions: { conditionType: POP_UP_SHOP_CONDITION_TYPE, param: PopUpConditionParamInter }[], sid?: string) {
let activities = await getActivitiesByType(serverId, ACTIVITY_TYPE.POP_UP_SHOP);
let pushData: pushActivityInter[] = [];
for(let { activityId, type: activityType } of activities) {
@@ -63,15 +94,23 @@ export async function checkPopUpConditions(serverId: number, roleId: string, con
continue;
}
let items = pkg.getItemsByCondition(param);
console.log('##### 4', items, items.length)
if(items.length > 0) {
let popUpShopRec = await ActivityPopUpShopModel.createRecord({
serverId, activityId, roleId, id: pkg.id,
...pkg.getEffectTime(),
items: items.map(item => new PopUpShopItem(item))
});
let result = pkg.pushPackage(popUpShopRec);
pushItems.push(...result);
let map = new Map<string, PopShopItem[]>();
for(let item of items) {
if(!map.has(item.param)) {
map.set(item.param, []);
}
map.get(item.param).push(item);
}
for(let [_, items] of map) {
let popUpShopRec = await ActivityPopUpShopModel.createRecord({
serverId, activityId, roleId, id: pkg.id,
...pkg.getEffectTime(),
items: items.map(item => new PopUpShopItem(item))
});
let result = pkg.pushPackage(popUpShopRec);
pushItems.push(...result);
}
}
}
}
@@ -81,7 +120,7 @@ export async function checkPopUpConditions(serverId: number, roleId: string, con
}
}
console.log('##### 6', pushData.length)
return await pushActivities(pushData, roleId);
return await pushActivities(pushData, roleId, sid);
}

View File

@@ -38,12 +38,14 @@ interface Param {
schoolHid?: number,
preSchoolHid?: number,
skinId?: number,
roleUpdate?: RoleUpdate,
roleIncUpdate?: RoleUpdate
}
export async function calculateCeWithHero(type: HERO_SYSTEM_TYPE, roleId: string, serverId: number, sid: string, hid: number, heroUpdate: HeroUpdate, param: Param = {}) {
let heroUpdates = new Map<number, HeroUpdate>();
heroUpdates.set(hid, heroUpdate);
let { heroes, curRole } = await calculateCes(type, roleId, serverId, sid, heroUpdates, {}, {}, param);
let { heroes, curRole } = await calculateCes(type, roleId, serverId, sid, heroUpdates, param.roleUpdate||{}, param.roleIncUpdate||{}, param);
let curHero = heroes.find(cur => cur.hid == hid);
return { heroes, curHero, curRole }
}

View File

@@ -311,9 +311,8 @@ export async function clearChannelServers() {
* @param userCode user表唯一字符串标识
* @param sid connector服的那个sid
*/
export async function roleLogin(roleId: string, userCode: string, sid: string, pkgName: string, createTime: number) {
let param = { userCode, sid, pkgName, createTime };
return await redisClient().hsetAsync(REDIS_KEY.ONLINE_USERS, roleId, JSON.stringify(param));
export async function roleLogin(roleId: string, userCode: string, sid: string, pkgName: string, createTime: number, serverId: number) {
return await redisClient().hsetAsync(REDIS_KEY.ONLINE_USERS, roleId, `${userCode}|${sid}|${pkgName}|${createTime}|${serverId}`);
}
/**
@@ -343,13 +342,12 @@ export async function getRoleOnlineInfo(roleId: string) {
let str = await redisClient().hgetAsync(REDIS_KEY.ONLINE_USERS, roleId);
if(str) {
try {
let result = JSON.parse(str);
let result = str.split('|');
let [userCode, sid, pkgName, createTime, serverId] = result;
return {
isOnline: true,
userCode: result.userCode,
sid: result.sid,
pkgName: result.pkgName,
createtime: result.createTime
isOnline: true, userCode, sid, pkgName,
createtime: parseInt(createTime),
serverId: parseInt(serverId)
}
} catch(e) {
return { isOnline: false }
@@ -375,15 +373,15 @@ export async function getRoleCreateTime(roleId: string, role?: RoleType) {
* 获得所有在线的玩家
*/
export async function getAllOnlineRoles() {
const client: Redis.RedisClient = pinus.app.get('redis');
let allRoles = await redisClient().hgetallAsync(REDIS_KEY.ONLINE_USERS);
let result = new Array<{roleId: string, userCode: string, sid: string, pkgName: string}>();
let result = new Array<{roleId: string, userCode: string, sid: string, pkgName: string, serverId: number}>();
for(let roleId in allRoles) {
try{
let param = JSON.parse(allRoles[roleId]);
if(param) {
result.push({ roleId, userCode: param.userCode, sid: param.sid, pkgName: param.pkgName });
}
let param = allRoles[roleId].split('|');
let [userCode, sid, pkgName, _createTime, serverId] = param;
result.push({ roleId, userCode, sid, pkgName, serverId: parseInt(serverId) });
} catch(e) {
continue;
}

View File

@@ -1,7 +1,7 @@
import { RoleModel, RoleType } from '../../db/Role';
import { pinus, FrontendOrBackendSession } from 'pinus';
import { resResult, shouldRefresh } from '../../pubUtils/util';
import { STATUS, TASK_TYPE, TASK_FUN_TYPE, SHOP_REFRESH_TYPE, WAR_TYPE, PUSH_ROUTE } from '../../consts';
import { STATUS, TASK_TYPE, TASK_FUN_TYPE, SHOP_REFRESH_TYPE, WAR_TYPE, PUSH_ROUTE, POP_UP_SHOP_CONDITION_TYPE } from '../../consts';
import { TaskParamInter, TaskListReturn } from '../../domain/roleField/task';
import { EPlace, HeroType } from '../../db/Hero';
import { HeroScores } from '../../db/PvpHistoryOpp';
@@ -16,7 +16,7 @@ import { getActivities } from '../activity/activityService';
import { CheckTask } from './taskObj';
import { getEquipById } from '../equipService';
import { JewelType } from '../../db/Jewel';
import { checkPopUpConditionInCreateHero } from '../activity/popUpShopService';
import { checkPopUpCondition, checkPopUpConditionInCreateHero, checkPopUpConditionInEntry } from '../activity/popUpShopService';
import { sendMessageToUserWithSuc } from '../pushService';
export async function checkTaskWithRoles(serverId: number, roleId: string, sid: string, taskType: TASK_TYPE, roles: RoleType[]) {
@@ -46,6 +46,7 @@ export async function checkTaskInEntry(serverId: number, roleId: string, sid: st
task.setParam(TASK_TYPE.LOGIN_SUM, {});
task.setParam(TASK_TYPE.LOGIN_SERIES, {});
await task.saveAndPush(sid);
checkPopUpConditionInEntry(serverId, roleId, sid);
}
export async function checkTaskInCreateHero(serverId: number, roleId: string, sid: string, heroNum: number, heroes: HeroType[]) {
@@ -122,6 +123,10 @@ export async function checkTaskInGuildTrain(serverId: number, roleId: string, si
task.setParam(TASK_TYPE.BATTLE_EXPEDITION, { warId, count: 1 });
task.setParam(TASK_TYPE.BATTLE_MAIN_ELITE, { warId, count: 1 });
await task.saveAndPush(sid);
let dicWar = gameData.war.get(warId);
if(dicWar && dicWar.warType == WAR_TYPE.NORMAL) {
checkPopUpCondition(serverId, roleId, POP_UP_SHOP_CONDITION_TYPE.MAIN_BATTLE, { warId }, sid);
}
}
@@ -157,12 +162,15 @@ export async function checkTaskInComBattleStart(roleStatus: RoleStatus[], capId:
}
}
export async function checkTaskInPvpEnd(serverId: number, roleId: string, sid: string, isSuccess: boolean, heroScores: HeroScores[]) {
export async function checkTaskInPvpEnd(serverId: number, roleId: string, sid: string, isSuccess: boolean, heroScores: HeroScores[], myRank: number) {
let task = new CheckTask(serverId, roleId);
task.setParam(TASK_TYPE.PVP_WIN, { isSuccess });
task.setParam(TASK_TYPE.PVP_WIN_SERIES, { isSuccess });
task.setParam(TASK_TYPE.PVP_HERO_SCORE, { heroScores });
await task.saveAndPush(sid);
if(myRank) {
checkPopUpCondition(serverId, roleId, POP_UP_SHOP_CONDITION_TYPE.PVP, { rank: myRank }, sid);
}
}
export async function checkTaskInGacha(serverId: number, roleId: string, sid: string, count: number, heroes: HeroType[]) {
@@ -207,7 +215,7 @@ export async function checkTaskInPutStone(serverId: number, roleId: string, sid:
await task.saveAndPush(sid);
}
export async function checkTaskInEquipStarUp(serverId: number, roleId: string, sid: string, oldEplace: EPlace[], newEplace: EPlace[], ePlaceId: number, hid: number, isUpStar: boolean) {
export async function checkTaskInEquipStarUp(serverId: number, roleId: string, sid: string, oldEplace: EPlace[], newEplace: EPlace[], ePlaceId: number, hid: number, isUpStar: boolean, equipStarSum: number) {
let task = new CheckTask(serverId, roleId);
if(isUpStar) {
let { oldEquip, newEquip } = getEquipById(oldEplace, newEplace, ePlaceId);
@@ -216,6 +224,9 @@ export async function checkTaskInEquipStarUp(serverId: number, roleId: string, s
}
task.setParam(TASK_TYPE.EQUIP_STAR_UP_CNT, { hid, ePlaceId });
await task.saveAndPush(sid);
if(isUpStar) {
checkPopUpCondition(serverId, roleId, POP_UP_SHOP_CONDITION_TYPE.EQUIP_STAR, { equipStar: equipStarSum }, sid);
}
}
export async function checkTaskInEquipQualityUp(serverId: number, roleId: string, sid: string, oldEplace: EPlace[], newEplace: EPlace[], ePlaceId: number, hid: number, isUpQuality: boolean) {

View File

@@ -37,6 +37,7 @@ import { getActivitiesByType } from './activity/activityService';
import { ActivityGroupModel } from '../db/ActivityGroup';
import { sendMessageToServer } from './pushService';
import { resResult } from '../pubUtils/util';
import { checkPopUpConditionWhenGuildActivityEnd } from './activity/popUpShopService';
const PER_SECOND = 1 * 1000;
const PER_DAY = 24 * 60 * 60;
@@ -297,6 +298,7 @@ export async function gateActivityEnd() {
guildActEndJobId.cancel();
guildActEndJobId = undefined;
}
checkPopUpConditionWhenGuildActivityEnd();
}
// 每10秒下发一次的任务
@@ -325,6 +327,7 @@ export async function cityActivityEnd() {
guildActEndJobId.cancel();
guildActEndJobId = undefined;
}
checkPopUpConditionWhenGuildActivityEnd();
}
// 每10秒下发一次的任务
@@ -348,6 +351,7 @@ export async function raceActivityEnd() {
guildActEndJobId.cancel();
guildActEndJobId = undefined;
}
checkPopUpConditionWhenGuildActivityEnd();
}
// 每10秒下发一次的任务

View File

@@ -178,6 +178,10 @@ export enum POP_UP_SHOP_CONDITION_TYPE {
GET_HERO_BY_QUALITY = 2, // 获得某种品质的武将
GACHA_RES_NOT_ENOUGH = 3, // 点击抽卡资源不足
TERAPH_RES_NOT_ENOUGH = 4, // 神兽强化材料不足
MAIN_BATTLE = 5, // 通关主线
PVP = 6, // pvp
EQUIP_STAR = 7, // 装备精炼
AUCTION = 8, // 拍卖行
}
export enum POP_UP_SHOP_REFRESH_TIME_TYPE {

View File

@@ -25,6 +25,7 @@ export const REF_CIRCLE_MAIL_TIME = 6; // 统一一天刷新定期邮件时间
export const PUSH_BATCH = 100; // 推送分批人数
export const PUSH_INTERVAL = 5 * 1000; // 分批时间5秒一批
export enum TIME_OUTPUT_TYPE {
DATE = 1,
STAMP_10 = 2,

View File

@@ -180,6 +180,8 @@ export default class Role extends BaseModel {
payRecord: PayRecord[]; // 支付记录
@prop({ required: true, default: 0 })
jewelCount: number; // 装备数量
@prop({ required: true })
equipStarSum: number; // 装备上的星级的数量
@prop({ required: true, default: 0 })
coin: number; // 总铜钱

View File

@@ -307,6 +307,7 @@ export class PopUpShopPackage {
// 礼包,购买以此为单位
export class PopShopItem {
id: number; // 档位唯一id升降档的时候按照id顺序排升档id+降档id-
param: string;
conditionParam: number[]; // 条件类型的参数填法根据conditionType表判断
price: number; // 商品价格
productID: string; // 商品id支付时使用
@@ -325,6 +326,7 @@ export class PopShopItem {
constructor(data: PopUpShopItemInDb, parent: PopUpShopPackage) {
this.id = data.id;
this.param = data.conditionParam;
this.conditionParam = parseNumberList(data.conditionParam);
this.price = data.price;
this.productID = data.productID;
@@ -361,6 +363,14 @@ export class PopShopItem {
case POP_UP_SHOP_CONDITION_TYPE.GACHA_RES_NOT_ENOUGH:
case POP_UP_SHOP_CONDITION_TYPE.TERAPH_RES_NOT_ENOUGH:
return true;
case POP_UP_SHOP_CONDITION_TYPE.MAIN_BATTLE:
return param.warId == this.conditionParam[0];
case POP_UP_SHOP_CONDITION_TYPE.PVP:
return param.rank <= this.conditionParam[0];
case POP_UP_SHOP_CONDITION_TYPE.EQUIP_STAR:
return param.equipStar >= this.conditionParam[0];
case POP_UP_SHOP_CONDITION_TYPE.AUCTION:
return true;
default:
return false;
}
@@ -425,6 +435,9 @@ export interface PopUpConditionParamInter {
oldLv?: number;
newLv?: number;
quality?: number;
warId?: number;
rank?: number;
equipStar?: number;
}