297 lines
8.9 KiB
Go
297 lines
8.9 KiB
Go
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"
|
|
)
|
|
|
|
type TmPlayer struct {
|
|
SnId int32
|
|
seq int // 报名序号(第几个报名的)
|
|
}
|
|
type TmMatch struct {
|
|
SortId int32 // 比赛开始时间戳,纳秒
|
|
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 // 最近一轮的机器人积分备份
|
|
tmpUseRobot int32 // 是否使用机器人
|
|
}
|
|
|
|
type TmGradeInfo struct {
|
|
grade int32
|
|
copySnid int32
|
|
copyLv int32
|
|
copyRoleId int32
|
|
}
|
|
|
|
func (tm *TmMatch) Start() {
|
|
logger.Logger.Trace("(this *TmMatch) Start()")
|
|
//通知客户端比赛开始
|
|
pack := &tournament.SCTMStart{
|
|
MatchId: proto.Int32(tm.TMId),
|
|
}
|
|
proto.SetDefaults(pack)
|
|
logger.Logger.Trace("SCTMStart:", pack)
|
|
tm.BroadcastMessage(int(tournament.TOURNAMENTID_PACKET_TM_SCTMStart), pack)
|
|
|
|
//创建房间
|
|
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) 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 := MulticastMaker.CreateMulticastPacket(packetId, rawPack, v...)
|
|
if err == nil {
|
|
proto.SetDefaults(pack)
|
|
gateSess.Send(int(srvproto.SrvlibPacketID_PACKET_SS_MULTICAST), pack)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func (tm *TmMatch) CopyMap(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.Trace("机器人数量: ", lastPromotionNum)
|
|
|
|
// 第初始轮数据
|
|
if tm.robotGrades == nil || tm.robotGrades[round-1] == nil { //初始化数据
|
|
tm.robotGrades[round-1] = []*TmGradeInfo{}
|
|
snids := []int32{}
|
|
lvs := []int32{}
|
|
roleIds := []int32{}
|
|
for _, player := range PlayerMgrSington.snidMap {
|
|
if len(snids) > int(lastPromotionNum) {
|
|
break
|
|
}
|
|
if player != nil && player.IsRob {
|
|
snids = append(snids, player.SnId)
|
|
ms := MatchSeasonMgrSington.GetMatchSeason(player.SnId)
|
|
lv := MatchSeasonRankMgrSington.CreateRobotLv()
|
|
if ms != nil {
|
|
lv = ms.Lv
|
|
}
|
|
lvs = append(lvs, lv)
|
|
roleId := int32(2000001)
|
|
if player.Roles != nil && player.Roles.ModId != 0 {
|
|
roleId = player.Roles.ModId
|
|
}
|
|
roleIds = append(roleIds, roleId)
|
|
}
|
|
}
|
|
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)
|
|
lv := MatchSeasonRankMgrSington.CreateRobotLv()
|
|
lvs = append(lvs, lv)
|
|
roleIds = append(roleIds, int32(2000001))
|
|
}
|
|
}
|
|
for i := 0; i < int(lastPromotionNum); i++ {
|
|
gradeInfo := &TmGradeInfo{
|
|
grade: 1000, // 初始都是1000积分
|
|
copySnid: snids[i],
|
|
copyLv: lvs[i],
|
|
copyRoleId: roleIds[i],
|
|
}
|
|
tm.robotGrades[round-1] = append(tm.robotGrades[round-1], gradeInfo)
|
|
}
|
|
}
|
|
sort.Slice(tm.robotGrades[round-1], func(i, j int) bool {
|
|
return tm.robotGrades[round-1][i].grade > tm.robotGrades[round-1][j].grade
|
|
})
|
|
|
|
// 当前轮数据
|
|
tm.robotGrades[round] = []*TmGradeInfo{}
|
|
upNum := int32(math.Floor(float64(lastPromotionNum*tm.gml.RobotUpRatio) / 100.0))
|
|
indexs := []int32{}
|
|
for i := 0; i < int(lastPromotionNum); i++ {
|
|
indexs = append(indexs, int32(i))
|
|
}
|
|
upIndexs := []int32{} // 积分上升的机器人
|
|
for i := 0; i < int(upNum); i++ {
|
|
randIndex := rand.Intn(len(indexs))
|
|
upIndexs = append(upIndexs, indexs[randIndex])
|
|
indexs = append(indexs[:randIndex], indexs[randIndex+1:]...)
|
|
}
|
|
downNum := lastPromotionNum - upNum
|
|
downIndexs := []int32{} // 积分下降的机器人
|
|
for i := 0; i < int(downNum); i++ {
|
|
randIndex := rand.Intn(len(indexs))
|
|
downIndexs = append(downIndexs, indexs[randIndex])
|
|
indexs = append(indexs[:randIndex], indexs[randIndex+1:]...)
|
|
}
|
|
// 上升
|
|
var n int32
|
|
for _, v := range tm.gml.UpGradeOdds {
|
|
n += v
|
|
}
|
|
for _, index := range upIndexs {
|
|
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,
|
|
}
|
|
tm.robotGrades[round] = append(tm.robotGrades[round], gradeInfo)
|
|
}
|
|
// 下降
|
|
n = 0
|
|
for _, v := range tm.gml.DownGradeOdds {
|
|
n += v
|
|
}
|
|
for _, index := range downIndexs {
|
|
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,
|
|
}
|
|
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,
|
|
}
|
|
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)
|
|
}
|
|
}
|
|
}
|