2025-04-23 09:34:08 +08:00

922 lines
30 KiB
TypeScript
Raw Permalink 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 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)
}
}
}
}
}
}