package tamquoc import ( "encoding/json" "math" "math/rand" "time" "mongo.games.com/goserver/core/basic" "mongo.games.com/goserver/core/logger" "mongo.games.com/goserver/core/task" "mongo.games.com/game/common" rule "mongo.games.com/game/gamerule/tamquoc" "mongo.games.com/game/gamesrv/base" "mongo.games.com/game/model" "mongo.games.com/game/proto" "mongo.games.com/game/protocol/gamehall" "mongo.games.com/game/protocol/tamquoc" ) type TamQuocSceneData struct { *base.Scene //房间信息 players map[int32]*TamQuocPlayerData //玩家信息 rooms map[int][]*TamQuocPlayerData //房间 jackpot *base.SlotJackpotPool //奖池 lastJackpotValue int64 //上一次奖池变化时的值 lastJackPot time.Time //增加奖池时间 lastBurstJackPot map[int32]time.Time //爆池时间 } func NewTamQuocSceneData(s *base.Scene) *TamQuocSceneData { return &TamQuocSceneData{ Scene: s, players: make(map[int32]*TamQuocPlayerData), rooms: make(map[int][]*TamQuocPlayerData), } } func (this *TamQuocSceneData) SaveData(force bool) { } func (this *TamQuocSceneData) OnPlayerLeave(p *base.Player, reason int) { if p, exist := this.players[p.SnId]; exist { delete(this.players, p.SnId) } } func (this *TamQuocSceneData) SceneDestroy(force bool) { //销毁房间 this.Scene.Destroy(force) } func (this *TamQuocSceneData) init() bool { if this.DbGameFree == nil { return false } params := this.DbGameFree.GetJackpot() this.jackpot = &base.SlotJackpotPool{} if this.jackpot.Small <= 0 { this.jackpot.Small = 0 this.jackpot.VirtualJK = int64(params[rule.TAMQUOC_JACKPOT_InitJackpot]) * int64(this.DbGameFree.GetBaseScore()) } str := base.SlotsPoolMgr.GetPool(this.GetGameFreeId(), this.Platform) if str != "" { jackpot := &base.SlotJackpotPool{} err := json.Unmarshal([]byte(str), jackpot) if err == nil { this.jackpot = jackpot } } if this.jackpot != nil { base.SlotsPoolMgr.SetPool(this.GetGameFreeId(), this.Platform, this.jackpot) } this.lastJackPot = time.Now() this.lastBurstJackPot = make(map[int32]time.Time) this.SetLastBurstJackPot() return true } type TamQuocSpinResult struct { LinesInfo []*tamquoc.TamQuocLinesInfo SlotsData []int32 TotalPrizeLine int64 // 线条总金额 TotalPrizeJackpot int64 // 爆奖总金额 JackpotCnt int // 爆奖的次数 AddFreeTimes int32 // 新增免费次数 IsJackpot bool // 是否爆奖 BonusGame tamquoc.TamQuocBonusGameInfo TotalWinRate int32 // 中奖总倍率 TotalTaxScore int64 // 税收 IsBonusGame bool // 是否进小游戏标志 WinLines []int // 赢分的线 } func (this *TamQuocSceneData) CalcLinePrize(cards []int, betLines []int64, betValue int64) (spinRes TamQuocSpinResult) { taxRate := this.DbGameFree.GetTaxRate() calcTaxScore := func(score int64, taxScore *int64) int64 { newScore := int64(float64(score) * float64(10000-taxRate) / 10000.0) if taxScore != nil { *taxScore += score - newScore } return newScore } var startBonus int lines := rule.CalcLine(cards, betLines) for _, line := range lines { if line.Element == rule.Element_JACKPOT && line.Count == rule.LINE_CELL { spinRes.IsJackpot = true spinRes.JackpotCnt++ var prizeJackpot int64 if spinRes.TotalPrizeJackpot == 0 { // 第一个爆奖 获取当前奖池所有 prizeJackpot = this.jackpot.VirtualJK } else { // 之后的爆奖 奖励为奖池初值 prizeJackpot = int64(this.DbGameFree.GetJackpot()[rule.TAMQUOC_JACKPOT_InitJackpot]) * int64(this.DbGameFree.GetBaseScore()) } prizeJackpot = calcTaxScore(prizeJackpot, &spinRes.TotalTaxScore) spinRes.TotalPrizeJackpot += prizeJackpot } curScore := betValue * int64(line.Score) curScore = calcTaxScore(curScore, &spinRes.TotalTaxScore) spinRes.TotalPrizeLine += curScore spinRes.TotalWinRate += int32(line.Score) lineInfo := &tamquoc.TamQuocLinesInfo{ LineId: proto.Int32(int32(line.Index)), Position: line.Position, PrizeValue: proto.Int64(curScore), } spinRes.LinesInfo = append(spinRes.LinesInfo, lineInfo) spinRes.WinLines = append(spinRes.WinLines, int(lineInfo.GetLineId())) // bonus game if line.BonusElementCnt == 3 || line.BonusElementCnt == 4 { startBonus += rule.LineScore[rule.Element_BONUS][line.BonusElementCnt-1] spinRes.IsBonusGame = true } // add free if line.FreeElementCnt >= 3 { spinRes.AddFreeTimes += int32(rule.FreeSpinTimesRate[line.FreeElementCnt-1]) } } if spinRes.IsBonusGame && startBonus > 0 { bonusGame := rule.GenerateBonusGame(int(betValue), startBonus) var totalBonusValue int64 bonusData := make([]int64, 0) for _, value := range bonusGame.BonusData { value = calcTaxScore(value, nil) totalBonusValue += value bonusData = append(bonusData, value) } spinRes.BonusGame = tamquoc.TamQuocBonusGameInfo{ TotalPrizeValue: proto.Int64(totalBonusValue * int64(bonusGame.Mutiplier)), Mutiplier: proto.Int32(int32(bonusGame.Mutiplier)), DataMultiplier: proto.Int64(totalBonusValue), BonusData: bonusData, } // 小游戏税收 bonusTax := (bonusGame.DataMultiplier - totalBonusValue) * int64(bonusGame.Mutiplier) spinRes.TotalTaxScore += bonusTax } for _, card := range cards { spinRes.SlotsData = append(spinRes.SlotsData, int32(card)) } return } func (this *TamQuocSceneData) BroadcastJackpot(sync bool) { if this.lastJackpotValue != this.jackpot.VirtualJK || sync { this.lastJackpotValue = this.jackpot.VirtualJK pack := &gamehall.SCHundredSceneGetGameJackpot{} jpfi := &gamehall.GameJackpotFundInfo{ GameFreeId: proto.Int32(this.DbGameFree.Id), JackPotFund: proto.Int64(this.jackpot.VirtualJK), } pack.GameJackpotFund = append(pack.GameJackpotFund, jpfi) proto.SetDefaults(pack) //以平台为标识向该平台内所有玩家广播奖池变动消息,游戏内外的玩家可监听该消息,减少由gamesrv向worldsrv转发这一步 tags := []string{this.Platform} logger.Logger.Trace("jackpot tamquoc", pack) base.PlayerMgrSington.BroadcastMessageToGroup(int(gamehall.HundredScenePacketID_PACKET_SC_GAMEJACKPOT), pack, tags) } } func (this *TamQuocSceneData) PushCoinPool(prizeFundAdd int64, IsNovice bool) { if IsNovice { base.CoinPoolMgr.PushCoinNovice(this.GetGameFreeId(), this.GroupId, this.Platform, prizeFundAdd) } else { base.CoinPoolMgr.PushCoin(this.GetGameFreeId(), this.GroupId, this.Platform, prizeFundAdd) } } func (this *TamQuocSceneData) PopCoinPool(winCoin int64, IsNovice bool) { if IsNovice { base.CoinPoolMgr.PopCoinNovice(this.GetGameFreeId(), this.GroupId, this.Platform, winCoin) } else { base.CoinPoolMgr.PopCoin(this.GetGameFreeId(), this.GroupId, this.Platform, winCoin) } } func (this *TamQuocSceneData) RecordBurstLog(name string, wincoin, totalbet int64) { log := model.NewBurstJackpotLog(this.Platform, this.DbGameFree.GameId, this.GetGameFreeId(), name, wincoin, totalbet) task.New(nil, task.CallableWrapper(func(o *basic.Object) interface{} { return model.InsertBurstJackpotLogs(log) }), nil, "InsertBurstJackpotLogs").Start() } func (this *TamQuocSceneData) BurstHistory(player *TamQuocPlayerData) { task.New(nil, task.CallableWrapper(func(o *basic.Object) interface{} { return model.GetBurstJackpotLog(this.Platform, this.DbGameFree.GameId) }), task.CompleteNotifyWrapper(func(data interface{}, t task.Task) { var logsp []*tamquoc.TamQuocBurstHistoryInfo if data != nil { logs := data.([]model.BurstJackpotLog) if len(logs) > 0 { for _, log := range logs { logsp = append(logsp, &tamquoc.TamQuocBurstHistoryInfo{ UserName: log.Name, PriceValue: log.WinCoin, TotalBet: log.TotalBet, Ts: log.Ts, }) } } } pack := &tamquoc.SCTamQuocBurstHistory{ BurstLog: logsp, } logger.Logger.Trace("SCTamQuocBurstHistory:", pack) player.SendToClient(int(tamquoc.TamQuocPacketID_PACKET_SC_TAMQUOC_BURSTHISTORY), pack) }), "BurstHistory").Start() } func (this *TamQuocSceneData) GetLastBurstJackPot() time.Time { return this.lastBurstJackPot[this.GetGameFreeId()] } func (this *TamQuocSceneData) SetLastBurstJackPot() { var randT = rand.Intn(25200-7200+1) + 7200 switch this.DbGameFree.SceneType { case 1: randT = rand.Intn(25200-7200+1) + 7200 case 2: randT = rand.Intn(108000-72000+1) + 72000 case 3: randT = rand.Intn(180000-108000+1) + 108000 } this.lastBurstJackPot[this.GetGameFreeId()] = time.Now().Add(time.Second * time.Duration(randT)) } func (this *TamQuocSceneData) AIAddJackPot() { if time.Now().Sub(this.lastJackPot) > 0 { var randT = rand.Intn(3) + 1 switch this.DbGameFree.SceneType { case 1: randT = rand.Intn(3) + 1 case 2: randT = rand.Intn(12-5) + 6 case 3: randT = rand.Intn(20-9) + 10 default: randT = rand.Intn(3) + 1 } this.lastJackPot = time.Now().Add(time.Second * time.Duration(randT)) val := int64(math.Floor(float64(this.DbGameFree.GetBaseScore()) * float64(rule.LINENUM) * float64(500) / 10000)) this.jackpot.VirtualJK += val } } func (this *TamQuocSceneData) AIBurstJackPot() { if time.Now().Sub(this.GetLastBurstJackPot()) > 0 { this.SetLastBurstJackPot() jackpotParams := this.DbGameFree.GetJackpot() var jackpotInit = int64(jackpotParams[rule.TAMQUOC_JACKPOT_InitJackpot]) * int64(this.DbGameFree.GetBaseScore()) //奖池初始值 //AI机器人爆奖 val := this.jackpot.VirtualJK this.jackpot.VirtualJK = jackpotInit bet := int64(this.DbGameFree.GetBaseScore()) * int64(rule.LINENUM) this.RecordBurstLog(this.RandNickName(), val, int64(bet)) } } func (this *TamQuocSceneData) KickPlayerByTime() { if time.Now().Sub(this.GameStartTime) > time.Second*3 { this.GameStartTime = time.Now() for _, p := range this.players { if p.IsOnLine() { p.leavetime = 0 continue } p.leavetime++ if p.leavetime < 60 { continue } //踢出玩家 this.PlayerLeave(p.Player, common.PlayerLeaveReason_LongTimeNoOp, true) } //for _, p := range this.players { // //游戏次数达到目标值 // todayGamefreeIDSceneData, _ := p.GetDaliyGameData(int(this.DbGameFree.GetId())) // if !p.IsRob && // todayGamefreeIDSceneData != nil && // this.DbGameFree.GetPlayNumLimit() != 0 && // todayGamefreeIDSceneData.GameTimes >= int64(this.DbGameFree.GetPlayNumLimit()) { // this.PlayerLeave(p.Player, common.PlayerLeaveReason_GameTimes, true) // } //} if this.CheckNeedDestroy() { for _, player := range this.players { if !player.IsRob { if time.Now().Sub(player.LastOPTimer) > 10*time.Second { //离开有统计 this.PlayerLeave(player.Player, common.PlayerLeaveReason_OnDestroy, true) } } } if this.GetRealPlayerCnt() == 0 { this.SceneDestroy(true) } } } }