game_sync/worldsrv/tmmatch.go

320 lines
9.8 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"
"mongo.games.com/game/srvdata"
)
type TmPlayer struct {
SnId int32
seq int // 报名序号(第几个报名的)
}
type TmGradeInfo struct {
grade int32
copySnid int32
copyLv int32
copyRoleId int32
CopySkinId 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: time.Now().UnixNano(),
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)
//创建房间
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) 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,
}
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)
// }
//}
}