import PlayerMgr from "../object/PlayerMgr"; import PaiHangMgr from "../core/PaiHangMgr"; import { BattleType, EEventType, ERaceType, MsgCode } from "../role/EEnum"; import DB from "../utils/DB"; import * as schedule from "node-schedule"; import SKLogger from "../gear/SKLogger"; import Player from "../object/Player"; import SKDataUtil from "../gear/SKDataUtil"; import ActivityDefine from "./ActivityDefine"; import GTimer from "../common/GTimer"; import TeamMgr from "../core/TeamMgr"; import Currency from "../activity/Currency"; import NoticeMgr from "../core/NoticeMgr"; import SpecialEffect from "../object/SpecialEffect"; export default class TianTi { static shared = new TianTi(); schedule: any;// 定时器:每天更新排行榜 schedule2: any;// 定时器:每月结算奖励 reportlist: any[]; // 奖励列表 JiangLiList: any[]; /**限制击杀表 */ limtlist: any[]; /**定时时间(毫秒单位) */ state_time: any = { sign_time: 1000, // 通知完2分钟后开始报名 sat_time: 60 * 60 * 1000 *5 // 巅峰对决(35分钟) } /**比赛阶段 */ match_state: any = { /** 备战-巅峰对决*/ beizhantianti: 1, // /** 巅峰对决*/ tiantizhan: 2 // } /**战斗状态 */ FightState: any = { Wait: 1, // 等待 FightEnd: 2, // 结束战斗 Fighting: 3, // 等待状态 } /**赛季 */ season: number; /**参战队伍 报名加入 */ match_team: any[]; name: any; player_list: any; /** 天梯状态 */ activity_state: any; /**通知时间 */ inform_time: any; /**比赛阶段 */ game_state: any; /**奖励 */ goods_award: any[]; /**定时匹配队伍 */ matching_cancel: any; /**定时调整队伍 */ adjust_cancel: any; constructor() { this.JiangLiList = [];//奖励列表 this.reportlist = [];//天梯排行数据 // this.goods_award = [50014, 50015, 10406, 10110, 10609, 10604, 50016, 95142, 50033];//奖励列表 this.goods_award =[]; this.limtlist = []; this.name = '天梯巅峰战'; /**赛季 */ this.season = 1; /**参数队伍 */ this.match_team = []; this.player_list = {}; this.game_state = 0; } OnNewDay() { this.limtlist = []; } init() { this.activity_state = ActivityDefine.activityState.Close;//天梯状态 schedule.scheduleJob("0 0 12 ? * *", () => { //先更新排行数据 this.reportlist = []; //先清空 //在读取 let sql = `SELECT * FROM qy_tianti;`; DB.query(sql, (error: any, rows: any) => { if (error) { return; } for (let i = 0; i < rows.length; i++) { SKLogger.debug('开始读取天梯数据') this.reportlist.push({ roleid: rows[i].roleid, resid: rows[i].resid, jifen: rows[i].jifen, name: rows[i].name, baichang: rows[i].baichang, shengchang: rows[i].shengchang, wingId: Number(rows[i].wingId), effid: rows[i].effid, }) } }) // 修改状态为准备报名 this.open(); }) this.schedule2 = schedule.scheduleJob("50 59 23 L * ?", () => { // var date = new Date(2022,2,15,19,0,0); // this.schedule2 =schedule.scheduleJob(date, () => { this.reportlist = []; //先清空 //在读取 let sql = `SELECT * FROM qy_tianti;`; // let sql = `DELETE FROM qy_tianti;`; DB.query(sql, (error: any, rows: any) => { if (error) { return; } for (let i = 0; i < rows.length; i++) { SKLogger.debug('开始发放天梯奖励') PlayerMgr.shared.getPlayerByRoleId(rows[i].roleid).addItem(70004, 1200 - (i * 200),true); let notice:any; notice.interval=5; notice.isgm = true notice.times=3; notice.type = 3; NoticeMgr.shared.addNewNotice(notice); } }); sql = `DELETE FROM qy_tianti;`; DB.query(sql, (error: any, rows: any) => { if (error) { return; } }); }) this.reportlist = []; //先清空 //在读取 let sql = `SELECT * FROM qy_tianti;`; DB.query(sql, (error: any, rows: any) => { if (error) { return; } for (let i = 0; i < rows.length; i++) { this.reportlist.push({ roleid: rows[i].roleid, resid: rows[i].resid, jifen: rows[i].jifen, name: rows[i].name, baichang: rows[i].baichang, shengchang: rows[i].shengchang, wingId: rows[i].wingId, effid: rows[i].effid, }) } SKLogger.debug('读取天梯数据成功!!') }) //读取兑换奖励 this.JiangLiList = []; //先清空 //在读取 sql = `SELECT * FROM prop_tiantijiangli;`; DB.query(sql, (error: any, rows: any) => { if (error) { SKLogger.debug('读取天梯奖励奖励失败') return; } for (let i = 0; i < rows.length; i++) { this.JiangLiList.push({ id: rows[i].id, itemid: rows[i].itemid, price: rows[i].price, name: rows[i].name, des: rows[i].des, }) } SKLogger.debug('读取天梯奖励数据成功!!===================================') }) //读取掉落奖励 this.goods_award = []; //先清空 //在读取 sql = `SELECT * FROM qy_tianti_diaoluo;`; DB.query(sql, (error: any, rows: any) => { if (error) { SKLogger.debug('读取掉落奖励失败') return; } for (let i = 0; i < rows.length; i++) { this.goods_award.push( rows[i].itemid); } }) // this.open();//测试直接开启 } /** * 活动开始-报名 */ open() { this.player_list = {}; this.match_team = []; this.activity_state = ActivityDefine.activityState.Opening;//报名状态 let msg = `${this.name}开启,请打开界面天梯巅峰战,进入决战地图匹配!`; PlayerMgr.shared.broadcast('s2c_notice', { strRichText: msg }); PlayerMgr.shared.broadcast('s2c_game_chat', { scale: 3, msg: msg, name: '', resid: 0, teamid: 0, }); this.inform_time = GTimer.getTime(); // 开始巅峰对决 setTimeout(() => { this.inform_time = GTimer.getTime(); this.SatPk(); }, 5 * 1000); SKLogger.info(`活动(${this.name})已经开启!${this.name}状态改变 当前状态:开始报名`); } /** * 进入-巅峰对决 */ SatPk() { // 即将关闭活动定时 setTimeout(() => { this.inform_time = GTimer.getTime(); // 即将关闭(活动结束前两分钟通知) this.readyClose(); }, this.state_time.sat_time - (2 * 60 * 1000)); // 关闭活动定时 setTimeout(() => { this.inform_time = GTimer.getTime(); // 活动结束-关闭 this.close(); }, this.state_time.sat_time); // 通知队伍中玩家比赛状态-巅峰对决 // for (const teamId in this.player_list) { // if (this.player_list.hasOwnProperty(teamId)) { // this.sayStage(TeamMgr.shared.getTeamInfo(teamId), this.match_state.sat, this.state_time.sat_time); // } // } // 开始比赛 this.matching(); } /** * 开始比赛 */ matching() { SKLogger.info(`天梯状态改变 当前状态:开始比赛`); this.checkMatch(this.match_team); //'*'表示通配符,匹配任意,当秒是'*'时,表示任意秒数都触发,其它类推 // 6个占位符从左到右分别代表:秒、分、时、日、月、周几 this.matching_cancel = schedule.scheduleJob("0/10 * * * * ? ", () => { this.checkMatch(this.match_team); }) this.adjust_cancel = schedule.scheduleJob("0/10 * * * * ? ", () => { this.checkFightTime(); }) } /** * 战斗休息10秒 */ checkFightTime() { let nowtime = Date.now(); for (const teaminfo of this.match_team) { if (teaminfo.fight_state == this.FightState.FightEnd) { if (nowtime - teaminfo.fight_end_time > 10 * 1000) { teaminfo.fight_end_time = 0; teaminfo.fight_state = this.FightState.Wait; } } } } /** * 匹配队伍进行战斗 */ checkMatch(match: any) { SKLogger.debug('匹配队伍进行战斗:' + match.length); if (match.length <= 1) { // this.close(); return; } else { let peak_team_all: any = []; let peak_team: any = []; let num = Math.floor(match.length / 2);//判断队伍是否对战数量 let flag = true; for (let i = 0; i < num; i++) { let count = 0; while (flag) { if (peak_team.length < 2) { if (count >= 5) { flag = false; continue; } count++; let ran = Math.floor(Math.random() * match.length); if (peak_team_all.indexOf(match[ran]) != -1 || match[ran].fight_state != this.FightState.Wait) { continue; } peak_team.push(match[ran]); peak_team_all.push(match[ran]); } else { flag = false; } } if (peak_team.length >= 2) { if (peak_team[0].teamid != peak_team[1].teamid) { this.beforeFight(peak_team[0], peak_team[1]); } } peak_team = []; flag = true; } } } // 战斗开始之前的 10秒 beforeFight(t1: any, t2: any) { let team = TeamMgr.shared.getTeamInfo(t1.teamid); let eteam = TeamMgr.shared.getTeamInfo(t2.teamid); if (team && eteam) { let selfTeam = []; for (let index = 0; index < team.playerlist.length; index++) { let member = team.playerlist[index]; let satRole: any = {}; satRole.onlyid = member.onlyid; satRole.roleid = member.roleid; satRole.resid = member.resid; satRole.level = member.level; satRole.name = member.name; selfTeam.push(satRole); if (this.hasLimt(satRole.onlyid)) {//存在记录 for (let index = 0; index < this.limtlist.length; index++) { const lim = this.limtlist[index]; //限制 if (lim.roleid == satRole.onlyid) { if (lim.num >= 10) { member.send('s2c_notice', { strRichText: '已达到最大匹配次数!' }) // return; } else { lim.num++; } } } } else {//没有记录 let info: any = {}; info.roleid = satRole.onlyid; info.num = 0; this.limtlist.push(info) } } let enemyTeam = []; for (let index = 0; index < eteam.playerlist.length; index++) { let member = eteam.playerlist[index]; let satRole: any = {}; satRole.onlyid = member.onlyid; satRole.roleid = member.roleid; satRole.resid = member.resid; satRole.level = member.level; satRole.name = member.name; enemyTeam.push(satRole); if (this.hasLimt(satRole.onlyid)) {//存在记录 for (let index = 0; index < this.limtlist.length; index++) { const lim = this.limtlist[index]; //限制 if (lim.roleid == satRole.onlyid) { if (lim.num >= 10) { member.send('s2c_notice', { strRichText: '已达到最大匹配次数!' }) // return; } else { lim.num++; } } } } else {//没有记录 let info: any = {}; info.roleid = satRole.onlyid; info.num = 0; this.limtlist.push(info) } } TeamMgr.shared.broadcast(t1.teamid, 's2c_tiantisat_match', { teamS: selfTeam, teamE: enemyTeam, }); TeamMgr.shared.broadcast(t2.teamid, 's2c_tiantisat_match', { teamS: enemyTeam, teamE: selfTeam, }); t1.fight_state = this.FightState.Fighting; t2.fight_state = this.FightState.Fighting; setTimeout(() => { this.startFight(t1, t2); }, 9 * 1000); } } hasLimt(roleid: any): boolean { for (let rid of this.limtlist) { if (rid.roleid == roleid) { return true; } } return false; } /** * 进入战斗 * @param t1 * @param t2 */ startFight(t1: any, t2: any) { let team = TeamMgr.shared.getTeamInfo(t1.teamid); let eteam = TeamMgr.shared.getTeamInfo(t2.teamid); delete this.player_list[t1.teamid]; delete this.player_list[t2.teamid]; for (let i = 0; i < this.match_team.length; i++) { let info: any = this.match_team[i]; if (info.teamid != t1.teamid) { continue; } this.match_team.splice(i, 1); break; } for (let i = 0; i < this.match_team.length; i++) { let info: any = this.match_team[i]; if (info.teamid != t2.teamid) { continue; } this.match_team.splice(i, 1); break; } if (team && eteam) { let eonlyid = eteam.leader.onlyid; team.leader.playerBattle(eonlyid, BattleType.TianTIFight); } } /** * 通知队伍中玩家比赛状态 * @param team */ sayStage(team: any, type: number, countDown: number) { if (team != null) { countDown = countDown - (GTimer.getTime() - this.inform_time); for (let i = 0; i < team.playerlist.length; i++) { const mem = team.playerlist[i]; // 通知前端改为巅峰 if (type == this.match_state.prepare_sat) { let teamInfo = this.player_list[team.teamid]; if (teamInfo) { mem.send('s2c_update_say_peak', { score: teamInfo.peak }) } } // 通知前端更改比赛状态 mem.send('s2c_say_stage', { type: type, countDown: countDown, }); } } } /** * 即将关闭活动进行通知 */ readyClose() { this.activity_state = ActivityDefine.activityState.ReadyClose; // 关闭定时调整队伍 this.adjust_cancel.cancel(); // 关闭定时匹配队伍 this.matching_cancel.cancel(); let msg = `${this.name} 即将关闭,大家抓紧时间!`; PlayerMgr.shared.broadcast('s2c_notice', { strRichText: msg }); PlayerMgr.shared.broadcast('s2c_game_chat', { scale: 3, msg: msg, name: '', resid: 0, teamid: 0, }); } /** * 关闭活动 */ close() { if (this.activity_state == ActivityDefine.activityState.Close) { return; } // 关闭定时调整队伍 if (this.adjust_cancel != undefined && this.adjust_cancel != null) { this.adjust_cancel.cancel(); } // 关闭定时匹配队伍 if (this.matching_cancel != undefined && this.matching_cancel != null) { this.matching_cancel.cancel(); } // 活动状态 this.activity_state = ActivityDefine.activityState.Close; // 清理在场队伍跳转长安 for (const teamId in this.player_list) { if (this.player_list.hasOwnProperty(teamId)) { let team = this.player_list[teamId]; this.leaveSat(PlayerMgr.shared.getPlayerByRoleId(team.pid), teamId); } } // 清理数据 this.match_team = []; this.player_list = {}; } /** * 请求离开天梯 */ leaveSat(player: any, teamId: any) { if (player) { let team = this.player_list[teamId]; if (team != null && team != undefined) { if (team.pid == player.roleid) { delete this.player_list[teamId]; } else { player.send_notice("您不是队长不可以次操作!"); player.send('s2c_leave_sat', { code: MsgCode.FAILED }); return; } } for (let i = 0; i < this.match_team.length; i++) { let info: any = this.match_team[i]; if (info.teamid != teamId) { continue; } this.match_team.splice(i, 1); break; } // 通知当前队伍成员将证道大会标题取消显示 // let team_list = TeamMgr.shared.getTeamInfo(teamId); // if (team_list) { // for (const member of team_list.playerlist) { // member.send('s2c_leave_sat', { // code: MsgCode.SUCCESS // }); // } // } } } /** * 获得匹配队伍 * @param teamid */ getMatchTeamInfo(teamid: any): any { for (let teaminfo of this.match_team) { if (teaminfo.teamid == teamid) { return teaminfo; } } return null; } /** * 奖励 * @param playid * @param isWin 1 胜利 0 失败 */ sendReward(playid: any, isWin: any) { let play = PlayerMgr.shared.getPlayerByOnlyId(playid); if (play) { // 获取队伍战斗分数(胜利 人数 * 10,失败 人数 * 5) let score = isWin == 1 ? 100 : 50; play.tianti_integral+=score; // 更新参数队伍的积分 // let dataScore = this.updateMatchScore(isWin, score, teamId, type, team, teamInfo); // 获取随机道具 let item = this.goods_award[Math.floor((Math.random() * this.goods_award.length))]; let exp = play.level * 6000 + play.relive * 50000; let pExp = Math.floor(exp * 1.2); play.addExp(exp); // 随机发送几个道具 play.addItem(item, Math.floor(Math.random() * 3) + 1, false, "天梯奖励!") play.curPet && (play.curPet.addExp(pExp)); // 天梯积分积分 play.tianti_integral += score; let baichang = isWin == 1 ? 0 : 1;; let shengchang = isWin == 1 ? 1 : 0; for (const key in this.reportlist) { if (Object.prototype.hasOwnProperty.call(this.reportlist, key)) { const element = this.reportlist[key]; if (element.roleid == play.roleid) { let effid = SpecialEffect.shared.getSuiEffect(play.roleid); element.jifen += score; baichang = element.baichang += baichang; element.baichang = baichang; shengchang = element.shengchang += shengchang; element.shengchang = shengchang; element.wingId = play.wingId, element.effid = effid } } } //更新数据库 let effid = SpecialEffect.shared.getSuiEffect(play.roleid); DB.tiantidata(play, play.tianti_integral, baichang, shengchang, effid, () => { }); // 通知前端更新积分信息 play.send('s2c_match_battles', { type: 3, // 1 元魔 0 证道 isWin: isWin, // 1 胜利 0 失败 icon: item, // 图标 exp: exp, // 人物经验 petExp: pExp, // 宠物经验 score: score, // 当前获得分数 peak: 0, // 当前巅峰积分 satScore: 0, // 队伍证道积分 matchScore: 0 // 队伍元魔积分 }); } // 巅峰对决(巅峰积分小于等于0清理出场) // if (type == 0 && isWin == 0) { // let info = this.player_list[teamId]; // if (info.peak <= 0) { // for (const member of team.playerlist) { // member.send_notice("由于你所在队伍的巅峰积分不足,失去继续比赛资格!") // } // this.leaveSat(PlayerMgr.shared.getPlayerByRoleId(info.pid), teamId); // // 当前队伍小于2个队伍直接结束活动 // let count_player: number = Object.keys(this.player_list).length // if (count_player <= 1) { // this.close(); // } // } // } } /** * 更新参数队伍的积分 * @param isWin 1 胜利 0 失败 * @param score 分数 * @param teamId 队伍ID * @param type 1:元魔 0:证道 */ updateMatchScore(isWin: number, score: number, teamId: any, type: number, team: any, player_team: any): any { let data: any = {}; if (type == 1) { player_team.magic_score += score; } else { player_team.sat_score += score; if (isWin == 1) { player_team.peak += 50; } else { player_team.peak -= 50; } } // 巅峰积分 data.peak = player_team.peak; // 元魔积分 data.satScore = player_team.sat_score; // 证道积分 data.matchScore = player_team.magic_score; // 更新 队伍积分状态集合 this.player_list[teamId] = { name: team.leader.name + '的队伍', pid: team.leader.roleid, // 队长角色编号 teamid: teamId, // 队伍编号 magic_score: data.matchScore, // 元魔积分 sat_score: data.satScore, // 证道积分 peak: data.peak, // 队伍巅峰积分 num: team.playerlist.length, // 队伍人数 } return data; } //获取天梯数据 getTianTidata(player: any, type: any) { let report = []; let selfjifen = 0; let selfpaiming = 0; let shengchang = 0; let baichang = 0; for (let i = 0; i < this.reportlist.length; i++) { let items = this.reportlist[i]; report.push({ roleid: items.roleid, resid: items.resid, jifen: items.jifen, name: items.name, baichang: items.baichang, shengchang: items.shengchang, wingId: Number(items.wingId), effid: items.effid }) } report.sort((a, b) => { return b.jifen - a.jifen });//排序 for (const key in report) { if (Object.prototype.hasOwnProperty.call(report, key)) { const element = report[key]; if (element.roleid == player.roleid) { selfjifen = element.jifen; selfpaiming = Number(key) + 1; shengchang = element.shengchang; baichang = element.baichang; break; } } } report.sort((a, b) => { return a.jifen < b.jifen ? 1 : -1; }); let frist = report.splice(0, 6); // 数据发送前端 player.send('s2c_TianTi_info', { selfjifen: selfjifen, selfpaiming: selfpaiming, shengchang: shengchang, baichang: baichang, tiantijizhenshifen:player.tianti_integral, list: SKDataUtil.toJson(frist, "{}") }); } //获取天梯奖励数据 getJiangLidata(player: any) { SKLogger.debug('获取天梯奖励数据') // 数据发送前端 let report = []; for (let i = 0; i < this.JiangLiList.length; i++) { let items = this.JiangLiList[i]; report.push({ id: items.id, itemid: items.itemid, price: items.price, name: items.name, des: items.des, }) } // 数据发送前端 player.send('s2c_TianTijiangli_info', { jiangli: SKDataUtil.toJson(this.JiangLiList, "{}"), }); } report() { let callback = (ret: any, rows: any) => { if (ret == MsgCode.SUCCESS) { for (let i = 0; i < rows.length; i++) { this.reportlist.push({ sroleid: rows[i].sroleid, eresid: rows[i].eresid, eroleid: rows[i].eroleid, erolename: rows[i].erolename, iswin: rows[i].iswin, ranking: rows[i].ranking, cdate: rows[i].cdate }) } } } DB.selectReport(callback); } /** * 天梯巅峰战:玩家报名 */ playerSign(player: any) { // 天梯没有开启 if (this.activity_state == ActivityDefine.activityState.Close) { return MsgCode.TIANTI_NOT_OPEN; } // // 不在天梯报名时间 // if (this.activity_state != ActivityDefine.activityState.ReadyOpen) { // return MsgCode.TIANTI_NOT_SIGN_TIME; // } let team = TeamMgr.shared.getTeamInfo(player.teamid); // // 天梯必须3人以上组队参加 // if (team == null || team.playerlist.length < 3) { // return MsgCode.TIANTI_SIGN_TEAM; // } // // 天梯必须3人以上组队参加 // for (let i = 0; i < team.playerlist.length; i++) { // const mem = team.playerlist[i]; // if (mem.level < 80) { // return MsgCode.TIANTI_SIGN_LEVEL_80; // } // } // 只能队长报名 if (team.leader.roleid != player.roleid) { return MsgCode.SIGN_TEAM_LEADER; } if (this.player_list[player.teamid] != null) { return MsgCode.SIGN_ALREADY; } SKLogger.debug('天梯报名成功') this.player_list[player.teamid] = { name: player.name + '的队伍', pid: player.roleid, // 队长角色编号 teamid: player.teamid, // 队伍编号 peak: 0, // 队伍巅峰积分\ num: team.playerlist.length,// 队伍人数 } // this.sayStage(team, this.match_state.beizhantianti, this.state_time.sign_time) this.matchTeam(team); return MsgCode.SUCCESS; } matchTeam(team: any) { let team_data: any = {}; team_data.teamid = team.teamid; // 队伍编号 team_data.wtime = 0; team_data.ltime = 0; team_data.fight_state = this.FightState.Wait; team_data.fight_end_time = 0; team_data.battle_index = 0; this.match_team.push(team_data); } /**现金奖励 */ starCurrency(battle: any, task_name: string) { if (battle != null && battle.campA != undefined) { for (let role of battle.campA.broles) { // 如果是玩家 if (role.living_type == 1) { let player = PlayerMgr.shared.getPlayerByOnlyId(role.onlyid) if (player) { Currency.shared.obtain_currency(player, task_name) } } } } } }