package main import ( "math" "math/rand" "sort" "time" "mongo.games.com/goserver/core/logger" "mongo.games.com/goserver/core/netlib" "mongo.games.com/goserver/core/timer" srvproto "mongo.games.com/goserver/srvlib/protocol" "mongo.games.com/game/common" "mongo.games.com/game/proto" "mongo.games.com/game/protocol/server" "mongo.games.com/game/protocol/tournament" webapi_proto "mongo.games.com/game/protocol/webapi" "mongo.games.com/game/srvdata" ) func getSortId() int64 { return time.Now().UnixMilli() } type TmPlayer struct { SnId int32 seq int // 报名序号(第几个报名的) } type TmGradeInfo struct { grade int32 copySnid int32 copyLv int32 copyRoleId int32 CopySkinId int32 rank int32 } type TmMatch struct { SortId int64 // 比赛开始时间戳,纳秒 TMId int32 // 比赛配置Id TmPlayer map[int32]*TmPlayer // 比赛玩家 Platform string // 平台 gmd *webapi_proto.GameMatchDate // 比赛配置 gml *server.DB_GameMatchLevel // 难度配置 dbGameFree *server.DB_GameFree // 游戏配置 robotGrades map[int][]*TmGradeInfo // 第几轮:玩家积分 copyRobotGrades []*TmGradeInfo // 最近一轮的机器人积分备份 useRobot int32 // 是否使用机器人 StartTime int64 // 本场比赛开始时间 } func NewTmMatch(platform string, match *webapi_proto.GameMatchDate, players map[int32]*TmPlayer) *TmMatch { ret := &TmMatch{ SortId: getSortId(), TMId: match.Id, TmPlayer: make(map[int32]*TmPlayer), Platform: platform, gmd: match, gml: srvdata.MatchLevelMgr.Get(match.GameFreeId, match.MatchLevel), dbGameFree: srvdata.PBDB_GameFreeMgr.GetData(match.GameFreeId), robotGrades: make(map[int][]*TmGradeInfo), useRobot: match.UseRobot, StartTime: time.Now().Unix(), } ret.copyPlayers(players) return ret } func (tm *TmMatch) Start() { logger.Logger.Trace("TmMatch Start") //通知客户端比赛开始 pack := &tournament.SCTMStart{ MatchId: proto.Int32(tm.TMId), } tm.BroadcastMessage(int(tournament.TOURNAMENTID_PACKET_TM_SCTMStart), pack) logger.Logger.Trace("SCTMStart ", pack) tm.RobotGradesDecline(1) //创建房间 timer.StartTimer(timer.TimerActionWrapper(func(h timer.TimerHandle, ud interface{}) bool { MatchSceneMgrSingleton.MatchStart(tm) return true }), nil, time.Millisecond*3500, 1) } func (tm *TmMatch) Stop() { // 销毁房间 MatchSceneMgrSingleton.MatchStop(tm) logger.Logger.Trace("(this *TmMatch) Stop()") } func (tm *TmMatch) GetTotalRound() int32 { return int32(len(tm.gmd.GetMatchPromotion()) - 1) } func (tm *TmMatch) BroadcastMessage(packetId int, rawPack interface{}) { mgs := make(map[*netlib.Session][]*srvproto.MCSessionUnion) for _, tmp := range tm.TmPlayer { p := PlayerMgrSington.GetPlayerBySnId(tmp.SnId) if p != nil && p.gateSess != nil && p.IsOnLine() && p.scene == nil { mgs[p.gateSess] = append(mgs[p.gateSess], &srvproto.MCSessionUnion{ Mccs: &srvproto.MCClientSession{ SId: proto.Int64(p.sid), }, }) } } for gateSess, v := range mgs { if gateSess != nil && len(v) != 0 { pack, err := common.CreateMulticastPacket(packetId, rawPack, v...) if err == nil { proto.SetDefaults(pack) gateSess.Send(int(srvproto.SrvlibPacketID_PACKET_SS_MULTICAST), pack) } } } } func (tm *TmMatch) copyPlayers(b map[int32]*TmPlayer) { tm.TmPlayer = make(map[int32]*TmPlayer) for _, v := range b { var tmp TmPlayer tmp = *v tm.TmPlayer[v.SnId] = &tmp } } // CreateRobotGrades 生成假积分 // 完成机器人积分上升或下降 func (tm *TmMatch) CreateRobotGrades(round int) { logger.Logger.Tracef("======创建假积分======当前第 %v 轮============", round) if tm.robotGrades == nil { tm.robotGrades = make(map[int][]*TmGradeInfo) } if tm.robotGrades[round] == nil { //生成假数据 gmd := tm.gmd lastPromotionNum := gmd.MatchPromotion[round-1] - 1 // 当前轮机器人数量 logger.Logger.Tracef("CreateRobotGrades round:%v 机器人数量:%v", round, lastPromotionNum) // 上一轮数据,用在线玩家数据填充包含机器人,如果不够填充假数据 if tm.robotGrades[round-1] == nil { //初始化数据 tm.robotGrades[round-1] = []*TmGradeInfo{} var snids []int32 var lvs []int32 var roleIds, skinIds []int32 for _, player := range PlayerMgrSington.snidMap { if len(snids) > int(lastPromotionNum) { break } if player != nil && player.IsRob { snids = append(snids, player.SnId) lvs = append(lvs, 1) roleId := int32(2000001) if player.Roles != nil && player.Roles.ModId != 0 { roleId = player.Roles.ModId } roleIds = append(roleIds, roleId) if player.Skin != nil && player.Skin.ModId != 0 { skinIds = append(skinIds, player.Skin.ModId) } } } if len(snids) <= int(lastPromotionNum) { // 机器人不够了 logger.Logger.Warn("robot num not enough to match, must fixed robot num") max := int32(99999999) min := int32(10000000) old := len(snids) for i := 0; i < int(lastPromotionNum)-old; i++ { tmpSnid := rand.Int31n(max-min) + min if common.InSliceInt32(snids, tmpSnid) { tmpSnid = rand.Int31n(max-min) + min } snids = append(snids, tmpSnid) lvs = append(lvs, 1) roleIds = append(roleIds, int32(2000001)) skinIds = append(skinIds, 300001) } } for i := 0; i < int(lastPromotionNum); i++ { gradeInfo := &TmGradeInfo{ grade: 1000, // 初始都是1000积分 copySnid: snids[i], copyLv: lvs[i], copyRoleId: roleIds[i], CopySkinId: skinIds[i], } tm.robotGrades[round-1] = append(tm.robotGrades[round-1], gradeInfo) } } sort.Slice(tm.robotGrades[round-1], func(i, j int) bool { if tm.robotGrades[round-1][i].copySnid > 0 && tm.robotGrades[round-1][j].copySnid == 0 { return true } if tm.robotGrades[round-1][i].copySnid > 0 && tm.robotGrades[round-1][j].copySnid > 0 { return tm.robotGrades[round-1][i].grade > tm.robotGrades[round-1][j].grade } if tm.robotGrades[round-1][i].copySnid == 0 && tm.robotGrades[round-1][j].copySnid > 0 { return false } return false }) // 当前轮数据 tm.robotGrades[round] = []*TmGradeInfo{} upNum := int32(math.Floor(float64(lastPromotionNum*tm.gml.RobotUpRatio) / 100.0)) indexes := rand.Perm(int(lastPromotionNum)) upIndexes := indexes[:upNum] // 积分上升的机器人 downIndexes := indexes[upNum:] // 积分下降的机器人 // 上升 var n int32 for _, v := range tm.gml.UpGradeOdds { n += v } for _, index := range upIndexes { grade := tm.robotGrades[round-1][index].grade r := rand.Int31n(n) t := int32(0) findI := 0 for i, odd := range tm.gml.UpGradeOdds { t += odd if r < t { findI = i break } } grade += tm.gml.UpGrade[findI] gradeInfo := &TmGradeInfo{ grade: grade, copySnid: tm.robotGrades[round-1][index].copySnid, copyLv: tm.robotGrades[round-1][index].copyLv, copyRoleId: tm.robotGrades[round-1][index].copyRoleId, CopySkinId: tm.robotGrades[round-1][index].CopySkinId, } tm.robotGrades[round] = append(tm.robotGrades[round], gradeInfo) } // 下降 n = 0 for _, v := range tm.gml.DownGradeOdds { n += v } for _, index := range downIndexes { grade := tm.robotGrades[round-1][index].grade r := rand.Int31n(n) //0-999 t := int32(0) findI := 0 for i, odd := range tm.gml.DownGradeOdds { t += odd if r < t { findI = i break } } grade -= tm.gml.DownGrade[findI] gradeInfo := &TmGradeInfo{ grade: grade, copySnid: tm.robotGrades[round-1][index].copySnid, copyLv: tm.robotGrades[round-1][index].copyLv, copyRoleId: tm.robotGrades[round-1][index].copyRoleId, CopySkinId: tm.robotGrades[round-1][index].CopySkinId, } tm.robotGrades[round] = append(tm.robotGrades[round], gradeInfo) } } sort.Slice(tm.robotGrades[round], func(i, j int) bool { return tm.robotGrades[round][i].grade > tm.robotGrades[round][j].grade }) // 清除上上一轮数据 if tm.robotGrades[round-2] != nil { delete(tm.robotGrades, round-2) } //for i, infos := range tm.robotGrades { // logger.Logger.Tracef(">>>积分历史>>> 第 %v 轮", i) // for _, info := range infos { // logger.Logger.Trace("Snid: ", info.copySnid, " grade: ", info.grade, " copyLv: ", info.copyLv, " copyRoleId: ", info.copyRoleId) // } //} } // RobotGradesDecline 假积分衰减 func (tm *TmMatch) RobotGradesDecline(round int) { //衰减上一轮的积分 lastRound := round - 1 tm.copyRobotGrades = []*TmGradeInfo{} if tm.robotGrades == nil { tm.robotGrades = make(map[int][]*TmGradeInfo) } // 初始化第一轮积分 if round == 1 { tm.CreateRobotGrades(1) } // 生成当前轮积分 if tm.robotGrades[lastRound] == nil { tm.CreateRobotGrades(lastRound) } // 按规则积分衰减 if tm.robotGrades[lastRound] != nil { for i, info := range tm.robotGrades[lastRound] { declineGrade := info.grade if round != 1 { declineGrade = info.grade * 75 / 100 } gradeInfo := &TmGradeInfo{ grade: declineGrade, copySnid: info.copySnid, copyLv: info.copyLv, copyRoleId: info.copyRoleId, CopySkinId: info.CopySkinId, rank: info.rank, } tm.robotGrades[lastRound][i] = gradeInfo if info.copySnid != 0 { // 备份机器人积分,机器人入场时从备份数据中获取一个 tm.copyRobotGrades = append(tm.copyRobotGrades, gradeInfo) } } } //logger.Logger.Tracef("======积分衰减======当前第 %v 轮============", round) //for i, infos := range tm.robotGrades { // logger.Logger.Tracef(">>>积分历史>>> 第 %v 轮", i) // for _, info := range infos { // logger.Logger.Trace("Snid: ", info.copySnid, " grade: ", info.grade, " copyLv: ", info.copyLv, " copyRoleId: ", info.copyRoleId) // } //} }