package smallrocket import ( "mongo.games.com/game/model" "mongo.games.com/game/protocol/smallrocket" "time" "mongo.games.com/goserver/core" "mongo.games.com/goserver/core/logger" "mongo.games.com/game/common" rule "mongo.games.com/game/gamerule/smallrocket" "mongo.games.com/game/gamesrv/base" "mongo.games.com/game/proto" ) var PolicySmallRocketSingleton = &PolicySmallRocket{} type PolicySmallRocket struct { base.BaseScenePolicy states [rule.SmallRocketSceneStateMax]base.SceneState } func (this *PolicySmallRocket) CreateSceneExData(s *base.Scene) interface{} { sceneEx := NewSmallRocketSceneData(s) if sceneEx != nil { if sceneEx.init() { s.ExtraData = sceneEx } } return sceneEx } func (this *PolicySmallRocket) CreatePlayerExData(s *base.Scene, p *base.Player) interface{} { playerEx := &PlayerEx{Player: p} if playerEx != nil { p.ExtraData = playerEx } return playerEx } func (this *PolicySmallRocket) OnStart(s *base.Scene) { logger.Logger.Trace("(this *PolicySmallRocket) OnStart, sceneId=", s.GetSceneId()) sceneEx := NewSmallRocketSceneData(s) if sceneEx != nil { if sceneEx.init() { s.ExtraData = sceneEx s.ChangeSceneState(rule.SmallRocketSceneStateWait) } } } func (this *PolicySmallRocket) OnStop(s *base.Scene) { logger.Logger.Trace("(this *PolicyThirteen) OnStop , sceneId=", s.GetSceneId()) } func (this *PolicySmallRocket) OnTick(s *base.Scene) { if s == nil { return } if s.SceneState != nil { s.SceneState.OnTick(s) } } func (this *PolicySmallRocket) OnPlayerEnter(s *base.Scene, p *base.Player) { if s == nil || p == nil { return } logger.Logger.Trace("(this *PolicySmallRocket) OnPlayerEnter, sceneId=", s.GetSceneId(), " player=", p.SnId) if sceneEx, ok := s.ExtraData.(*SceneEx); ok { pos := -1 for i := 0; i < sceneEx.GetPlayerNum(); i++ { if sceneEx.seats[i] == nil { pos = i break } } if pos != -1 { playerEx := &PlayerEx{Player: p} sceneEx.seats[pos] = playerEx sceneEx.players[p.SnId] = playerEx baseScore := sceneEx.GetBaseScore() p.Pos = pos p.ExtraData = playerEx playerEx.Clear(baseScore) if sceneEx.Gaming { p.MarkFlag(base.PlayerState_WaitNext) p.UnmarkFlag(base.PlayerState_Ready) } //给自己发送房间信息 this.SendRoomInfo(s, p, sceneEx) s.FirePlayerEvent(p, base.PlayerEventEnter, nil) } } } func (this *PolicySmallRocket) OnPlayerLeave(s *base.Scene, p *base.Player, reason int) { logger.Logger.Trace("(this *PolicyThirteen) OnPlayerLeave, sceneId=", s.GetSceneId(), " player=", p.SnId) if s == nil || p == nil { return } if !this.CanChangeCoinScene(s, p) { return } sceneEx, ok := s.ExtraData.(*SceneEx) if !ok { return } playerEx, ok := p.ExtraData.(*PlayerEx) if !ok { return } isBilled := false // 游戏已开始,玩家离开,备份玩家数据 if sceneEx.Gaming { isBilled = playerEx.IsFinishTakeBet(sceneEx.GetSceneState().GetState()) sceneEx.BackupPlayer(playerEx, isBilled) } // 清理玩家数据 sceneEx.OnPlayerLeave(p, reason) s.FirePlayerEvent(p, base.PlayerEventLeave, nil) } func (this *PolicySmallRocket) OnPlayerDropLine(s *base.Scene, p *base.Player) { if s == nil || p == nil { return } logger.Logger.Trace("(this *PolicySmallRocket) OnPlayerDropLine, sceneId=", s.GetSceneId(), " player=", p.SnId) s.FirePlayerEvent(p, base.PlayerEventDropLine, nil) } func (this *PolicySmallRocket) OnPlayerRehold(s *base.Scene, p *base.Player) { if s == nil || p == nil { return } logger.Logger.Trace("(this *PolicySmallRocket) OnPlayerRehold, sceneId=", s.GetSceneId(), " player=", p.SnId) if sceneEx, ok := s.ExtraData.(*SceneEx); ok { if _, ok := p.ExtraData.(*PlayerEx); ok { //发送房间信息给自己 if p.IsGameing() { p.MarkFlag(base.PlayerState_Ready) } this.SendRoomInfo(s, p, sceneEx) s.FirePlayerEvent(p, base.PlayerEventRehold, nil) } } } func (this *PolicySmallRocket) OnPlayerReturn(s *base.Scene, p *base.Player) { if s == nil || p == nil { return } logger.Logger.Trace("(this *PolicySmallRocket) OnPlayerRehold, sceneId=", s.GetSceneId(), " player=", p.SnId) if sceneEx, ok := s.ExtraData.(*SceneEx); ok { if _, ok := p.ExtraData.(*PlayerEx); ok { //发送房间信息给自己 if p.IsGameing() { p.MarkFlag(base.PlayerState_Ready) } this.SendRoomInfo(s, p, sceneEx) s.FirePlayerEvent(p, base.PlayerEventReturn, nil) } } } func (this *PolicySmallRocket) OnPlayerOp(s *base.Scene, p *base.Player, opcode int, params []int64) bool { if s == nil || p == nil { return false } logger.Logger.Trace("(this *PolicySmallRocket) OnPlayerOp, sceneId=", s.GetSceneId(), " player=", p.SnId, " opcode=", opcode, " params=", params) if s.SceneState != nil { p.LastOPTimer = time.Now() p.Trusteeship = 0 return s.SceneState.OnPlayerOp(s, p, opcode, params) } return true } func (this *PolicySmallRocket) OnPlayerEvent(s *base.Scene, p *base.Player, evtcode int, params []int64) { if s == nil || p == nil { return } logger.Logger.Trace("(this *PolicySmallRocket) OnPlayerEvent, sceneId=", s.GetSceneId(), " player=", p.SnId, " eventcode=", evtcode, " params=", params) if s.SceneState != nil { s.SceneState.OnPlayerEvent(s, p, evtcode, params) } } func (this *PolicySmallRocket) IsCompleted(s *base.Scene) bool { if s == nil { return false } if sceneEx, ok := s.ExtraData.(*SceneEx); ok { return !sceneEx.Gaming } return false } func (this *PolicySmallRocket) IsCanForceStart(s *base.Scene) bool { if sceneEx, ok := s.ExtraData.(*SceneEx); ok { return len(s.Players) >= 2 && !sceneEx.Gaming } return false } func (this *PolicySmallRocket) ForceStart(s *base.Scene) { if sceneEx, ok := s.ExtraData.(*SceneEx); ok { if sceneEx.SceneState.GetState() == rule.SmallRocketSceneStateWait { s.ChangeSceneState(rule.SmallRocketSceneStateStart) } } } // 当前状态能否退出游戏 func (this *PolicySmallRocket) CanChangeCoinScene(s *base.Scene, p *base.Player) bool { if s == nil || p == nil { return false } if s.GetSceneState() != nil { return s.GetSceneState().CanChangeCoinScene(s, p) } return true } func (this *PolicySmallRocket) SendRoomInfo(s *base.Scene, p *base.Player, sceneEx *SceneEx) { pack := sceneEx.SamllRocketCreateRoomInfoPacket(s, p) p.SendToClient(int(smallrocket.SmallRocketPacketID_PACKET_SC_SMALLROCKET_ROOMINFO), pack) } // 广播房间状态 params[0]: bombMul params[1]: bombRandomVal func SmallRocketBroadcastRoomState(s *base.Scene, params ...float32) { pack := &smallrocket.SCSmallRocketRoomState{ State: proto.Int(s.SceneState.GetState()), Params: params, } s.Broadcast(int(smallrocket.SmallRocketPacketID_PACKET_SC_SMALLROCKET_ROOMSTATE), pack, 0) } // 广播下注人数 func SmallRocketBroadcastRoomBetPlayerNum(s *base.Scene, params ...int32) { if sceneEx, ok := s.ExtraData.(*SceneEx); ok { logger.Logger.Trace("SmallRocketBroadcastRoomBetPlayerNum, sceneId=", s.GetSceneId(), " | sceneEx.TotalBetPlayer=", sceneEx.TotalBetPlayer) if sceneEx.TotalBetPlayer < 0 { sceneEx.TotalBetPlayer = 0 } pack := &smallrocket.SCSmallRocketBetPlayerChange{ TotalBetPlayerCnt: proto.Int(sceneEx.TotalBetPlayer), } s.Broadcast(int(smallrocket.SmallRocketPacketID_PACKET_SC_SMALLROCKET_ROOMPLAYERBETNUM), pack, 0) } } // 广播有玩家领取收益跳伞 func SmallRocketBroadcastRoomPlayerTakeGain(s *base.Scene, snId int32, LeaveTime float64) { if _, ok := s.ExtraData.(*SceneEx); ok { pack := &smallrocket.SCSmallRocketPlayerTakeGain{ SnId: proto.Int32(snId), LeaveTime: proto.Float32(float32(LeaveTime)), } s.Broadcast(int(smallrocket.SmallRocketPacketID_PACKET_SC_SMALLROCKET_PLAYERTAKEGAIN), pack, 0) } } // 玩家信息变化 func SmallRocketSendPlayerInfo(s *base.Scene, p *PlayerEx, betDataInfo []*rule.BetDataEx, GainCoinBet1 int64, GainCoinBet2 int64) { if _, ok := s.ExtraData.(*SceneEx); ok { pack := &smallrocket.SCSmallRocketPlayerInfo{ SnId: proto.Int32(p.SnId), Coin: proto.Int64(p.Coin), GainCoin: proto.Int64(p.gainCoin), GainCoinBet1: GainCoinBet1, GainCoinBet2: GainCoinBet2, } if betDataInfo != nil { for i := 0; i < len(betDataInfo); i++ { tempBetEml := &smallrocket.BetDataInfo{ BetVal: proto.Int64(betDataInfo[i].BetVal), TakeMul: proto.Float32(float32(betDataInfo[i].TakeMul)), IsCurBet: proto.Bool(betDataInfo[i].IsCurBet), IsNextBet: proto.Bool(betDataInfo[i].IsNextBet), IsTakeGain: proto.Bool(betDataInfo[i].IsTakeGain), IsAutoBetAndTake: proto.Bool(betDataInfo[i].IsAutoBetAndTake), } pack.BetDataArr = append(pack.BetDataArr, tempBetEml) } } p.SendToClient(int(smallrocket.SmallRocketPacketID_PACKET_SC_SMALLROCKET_PLAYERINFO), pack) } } //===================================== // BaseState 状态基类 //===================================== type BaseState struct { } func (this *BaseState) GetTimeout(s *base.Scene) int { if sceneEx, ok := s.ExtraData.(*SceneEx); ok { return int(time.Now().Sub(sceneEx.StateStartTime) / time.Second) } return 0 } func (this *BaseState) CanChangeTo(s base.SceneState) bool { return true } func (this *BaseState) CanChangeCoinScene(s *base.Scene, p *base.Player) bool { //playerEx, ok := p.ExtraData.(*PlayerEx) //if !ok { // return false //} // //if !playerEx.CanLeaveScene(s.GetSceneState().GetState()) { // return false //} return true } func (this *BaseState) OnEnter(s *base.Scene) { if sceneEx, ok := s.ExtraData.(*SceneEx); ok { sceneEx.StateStartTime = time.Now() } } func (this *BaseState) OnLeave(s *base.Scene) {} func (this *BaseState) OnTick(s *base.Scene) { } func (this *BaseState) OnPlayerOp(s *base.Scene, p *base.Player, opcode int, params []int64) bool { sceneEx, ok := s.ExtraData.(*SceneEx) if !ok { return false } playerEx, ok := p.ExtraData.(*PlayerEx) if !ok { return false } switch opcode { case rule.SmallRocketPlayerOpSResumeGetPlayerInfo: // if len(params) >= 1 { params = append(params, playerEx.Coin) params = append(params, int64(this.GetTimeout(s))) sceneEx.OnPlayerSCOp(p, opcode, smallrocket.OpResultCode_OPRC_Success, params, playerEx.betData) } } return false } func (this *BaseState) OnPlayerEvent(s *base.Scene, p *base.Player, evtcode int, params []int64) { } //===================================== // StateWait 等待中 //===================================== type StateWait struct { BaseState } func (this *StateWait) GetState() int { return rule.SmallRocketSceneStateWait } func (this *StateWait) CanChangeTo(s base.SceneState) bool { if s.GetState() == rule.SmallRocketSceneStateStart { return true } return false } func (this *StateWait) GetTimeout(s *base.Scene) int { return this.BaseState.GetTimeout(s) } func (this *StateWait) OnEnter(s *base.Scene) { this.BaseState.OnEnter(s) if sceneEx, ok := s.ExtraData.(*SceneEx); ok { if s.Gaming { s.NotifySceneRoundPause() } s.Gaming = false sceneEx.logic.LoadCrashSearchData() SmallRocketBroadcastRoomState(s, float32(0), float32(0)) if sceneEx.CanStart() { s.ChangeSceneState(rule.SmallRocketSceneStateStart) } } } // 玩家事件 func (this *StateWait) OnPlayerEvent(s *base.Scene, p *base.Player, evtcode int, params []int64) { logger.Logger.Trace("(this *StateWait) OnPlayerEvent, sceneId=", s.GetSceneId(), " player=", p.SnId, " evtcode=", evtcode) this.BaseState.OnPlayerEvent(s, p, evtcode, params) if _, ok := s.ExtraData.(*SceneEx); ok { switch evtcode { case base.PlayerEventLeave: case base.PlayerEventEnter: if !p.IsReady() { p.MarkFlag(base.PlayerState_Ready) p.SyncFlag() } } } } func (this *StateWait) OnTick(s *base.Scene) { this.BaseState.OnTick(s) if sceneEx, ok := s.ExtraData.(*SceneEx); ok { if s.CheckNeedDestroy() { sceneEx.SceneDestroy(true) return } if time.Now().Sub(sceneEx.StateStartTime) > rule.SmallRocketSceneWaitTimeout { //切换到准备开局状态 if sceneEx.CanStart() { s.ChangeSceneState(rule.SmallRocketSceneStateStart) } } } } //===================================== // StateStart 开始倒计时 //===================================== type StateStart struct { BaseState } func (this *StateStart) GetState() int { return rule.SmallRocketSceneStateStart } func (this *StateStart) CanChangeTo(s base.SceneState) bool { switch s.GetState() { case rule.SmallRocketSceneStatePlayGame: return true } return false } func (this *StateStart) OnEnter(s *base.Scene) { this.BaseState.OnEnter(s) if sceneEx, ok := s.ExtraData.(*SceneEx); ok { SmallRocketBroadcastRoomState(s, float32(0), float32(0)) s.Gaming = false sceneEx.GameNowTime = time.Now() sceneEx.NumOfGames++ sceneEx.TotalBetPlayer = 0 sceneEx.BoomMul, sceneEx.BombRandomNum = sceneEx.logic.CalBoomMul(int(rule.SmallRocketBombRandomMulMaxE)) sceneEx.logid, _ = model.AutoIncGameLogId() if sceneEx.BoomMul >= rule.SmallRocketBombRoomMulMaxE { sceneEx.BoomMul = rule.SmallRocketBombRoomMulMaxE } BoomTime := sceneEx.logic.GetBombTimeByBombMul(int32(sceneEx.BoomMul * rule.SmallRocketPlayerTransDataMul)) if BoomTime < rule.SmallRocketPlayerTransDataMul { BoomTime = rule.SmallRocketPlayerTransDataMul } sceneEx.bombTime = time.Duration(float64(BoomTime) * float64(time.Second) / rule.SmallRocketPlayerTransDataMul) logger.Logger.Trace("StateStart------OnEnter: sceneEx.BombRandomNum: ", sceneEx.BombRandomNum, " | sceneEx.BoomMul: ", sceneEx.BoomMul, " | sceneEx.bombTime: ", sceneEx.bombTime) for _, playerEx := range sceneEx.players { if playerEx != nil { playerEx.PlayerAutoBet(this.GetState()) playerEx.StopBetCoin() SmallRocketSendPlayerInfo(s, playerEx, playerEx.betData, 0, 0) for i := 0; i < len(playerEx.betData); i++ { if playerEx.betData[i].IsCurBet && !playerEx.betData[i].IsTakeGain { var gainSearchTime = float64(sceneEx.logic.GetBombTimeByBombMul(int32(playerEx.betData[i].TakeMul * float64(rule.SmallRocketPlayerTransDataMul)))) if gainSearchTime < rule.SmallRocketPlayerTransDataMul { gainSearchTime = rule.SmallRocketPlayerTransDataMul } playerEx.betData[i].GainSearchTime = time.Duration((gainSearchTime / rule.SmallRocketPlayerTransDataMul) * float64(time.Second)) logger.Logger.Trace("StateStart------OnEnter: SnId=", playerEx.SnId, " | betData[", i, "]: ", " | GainSearchTime: ", playerEx.betData[i].GainSearchTime) // 没有自动的才扣钱 if !playerEx.IsAutoBetAndTakeByPos(int64(i)) { if playerEx.betData[i].BetVal > 0 { playerEx.AddCoin(-playerEx.betData[i].BetVal, common.GainWay_SmallRocket, base.SyncFlag_ToClient, "system", s.GetSceneName()) } else if playerEx.betData[i].BetVal < 0 { logger.Logger.Error("(this *StateStart) OnEnter, sceneid:", s.GetSceneId(), " | Player SnId:", playerEx.SnId, " | BetCoinVal:", playerEx.betData[i].BetVal) playerEx.PrintBetData(rule.SmallRocketSceneStateStart) } } } } playerEx.CopyToCurBetData() if sceneEx.logic.IsCurRoundBet(playerEx.betData) { playerEx.PrintBetData(rule.SmallRocketSceneStateStart) sceneEx.TotalBetPlayer++ } } } SmallRocketBroadcastRoomBetPlayerNum(s) } } func (this *StateStart) OnTick(s *base.Scene) { this.BaseState.OnTick(s) if sceneEx, ok := s.ExtraData.(*SceneEx); ok { if time.Now().Sub(sceneEx.StateStartTime) > rule.SmallRocketSceneStartTimeout { //切换到等待操作状态 if sceneEx.CanStart() { logger.Logger.Trace("StateStart------SmallRocketSceneStartTimeout: ", rule.SmallRocketSceneStartTimeout) s.ChangeSceneState(rule.SmallRocketSceneStatePlayGame) } else { s.ChangeSceneState(rule.SmallRocketSceneStateWait) } } } } func (this *StateStart) OnPlayerOp(s *base.Scene, p *base.Player, opcode int, params []int64) bool { if this.BaseState.OnPlayerOp(s, p, opcode, params) { return true } sceneEx, ok := s.ExtraData.(*SceneEx) if !ok { return false } playerEx, ok := p.ExtraData.(*PlayerEx) if !ok { return false } //if !playerEx.IsGameing() { // //returnFunc(thirteen.OpResultCode_OPRC_Error) // return true //} logger.Logger.Trace("StateStart OnPlayerOp-----SnId:", playerEx.SnId, " opcode: ", opcode, " params:", params) playerEx.PrintBetData(rule.SmallRocketSceneStateStart) switch opcode { case rule.SmallRocketPlayerOpBet: // 下注 if len(params) >= 3 { betPos := params[0] betVal := params[1] takeMul := params[2] if !sceneEx.CheckBetOp(betVal, takeMul) { return false } if len(playerEx.betData) >= 2 && (betPos >= 0 && betPos <= 1) { // 当前位置已经下注不允许再次下注 if sceneEx.logic.IsCurRoundBetPos(playerEx.betData, betPos) && !playerEx.betData[betPos].IsAutoBetAndTake { sceneEx.OnPlayerSCOp(p, opcode, smallrocket.OpResultCode_OPRC_PosAlReadyBet, params, playerEx.betData) return false } // 检测能否下注 if !playerEx.CanBetCoinByPos(int(betPos), betVal) { return false } // 之前没有下过注 下注人数增加, 通知服务器 if !sceneEx.logic.IsCurRoundBet(playerEx.betData) { sceneEx.TotalBetPlayer++ SmallRocketBroadcastRoomBetPlayerNum(s) } playerEx.betData[betPos].BetVal = betVal playerEx.betData[betPos].TakeMul = float64(takeMul) / 100.00 playerEx.betData[betPos].IsCurBet = true playerEx.betData[betPos].IsNextBet = false playerEx.betData[betPos].IsTakeGain = false if playerEx.betData[betPos].IsCurBet { var gainSearchTime = float64(sceneEx.logic.GetBombTimeByBombMul(int32(playerEx.betData[betPos].TakeMul * float64(rule.SmallRocketPlayerTransDataMul)))) if gainSearchTime < rule.SmallRocketPlayerTransDataMul { gainSearchTime = rule.SmallRocketPlayerTransDataMul } playerEx.betData[betPos].GainSearchTime = time.Duration((gainSearchTime / rule.SmallRocketPlayerTransDataMul) * float64(time.Second)) if playerEx.betData[betPos].BetVal > 0 { playerEx.AddCoin(-playerEx.betData[betPos].BetVal, common.GainWay_SmallRocket, base.SyncFlag_ToClient, "system", s.GetSceneName()) } else if playerEx.betData[betPos].BetVal < 0 { logger.Logger.Error("(this *StateStart) OnPlayerOp, sceneid:", s.GetSceneId(), " | Player SnId:", playerEx.SnId, " | betData[", betPos, "]: ", " | BetCoinVal:", playerEx.betData[betPos].BetVal) playerEx.PrintBetData(rule.SmallRocketSceneStateStart) } logger.Logger.Trace("StateStart SmallRocketPlayerOpBet------SnId:", playerEx.SnId, " | betData[", betPos, "]: ", " | BetVal: ", playerEx.betData[betPos].BetVal) } params = append(params, playerEx.Coin) playerEx.CopyToCurBetData() sceneEx.OnPlayerSCOp(p, opcode, smallrocket.OpResultCode_OPRC_Success, params, playerEx.betData) } } case rule.SmallRocketPlayerOpSetAutoBet, rule.SmallRocketPlayerOpSetAutoTakeGain: // 设置自动下注状态 if len(params) >= 4 { isAutoTakeGain := params[0] betPos := params[1] betVal := params[2] takeMul := params[3] if !sceneEx.CheckBetOp(betVal, takeMul) { return false } if len(playerEx.betData) >= 2 && (betPos >= 0 && betPos <= 1) { // 检测能否下注 if !playerEx.CanBetCoinByPos(int(betPos), betVal) { return false } // 下一局已下注 if playerEx.betData[betPos].IsNextBet { return false } // 本局还在下注状态下 if playerEx.betData[betPos].IsCurBet && !playerEx.betData[betPos].IsTakeGain { return false } playerEx.betData[betPos].BetVal = betVal playerEx.betData[betPos].TakeMul = float64(takeMul) / 100.00 playerEx.betData[betPos].IsCurBet = true playerEx.SetAutoBetAndTake(isAutoTakeGain, betPos) // 自动 下注未领取奖励 if playerEx.betData[betPos].IsCurBet && !playerEx.betData[betPos].IsTakeGain { var gainSearchTime = float64(sceneEx.logic.GetBombTimeByBombMul(int32(playerEx.betData[betPos].TakeMul * float64(rule.SmallRocketPlayerTransDataMul)))) if gainSearchTime < rule.SmallRocketPlayerTransDataMul { gainSearchTime = rule.SmallRocketPlayerTransDataMul } playerEx.betData[betPos].GainSearchTime = time.Duration((gainSearchTime / rule.SmallRocketPlayerTransDataMul) * float64(time.Second)) if playerEx.betData[betPos].BetVal > 0 { playerEx.AddCoin(-playerEx.betData[betPos].BetVal, common.GainWay_SmallRocket, base.SyncFlag_ToClient, "system", s.GetSceneName()) } else if playerEx.betData[betPos].BetVal < 0 { logger.Logger.Error("(this *StateStart) OnPlayerOp 4 , sceneid:", s.GetSceneId(), " | Player SnId:", playerEx.SnId, " | BetCoinVal:", playerEx.betData[betPos].BetVal) playerEx.PrintBetData(rule.SmallRocketSceneStateStart) } } params = append(params, playerEx.Coin) sceneEx.OnPlayerSCOp(p, opcode, smallrocket.OpResultCode_OPRC_Success, params, playerEx.betData) playerEx.CopyToCurBetData() } else { sceneEx.OnPlayerSCOp(p, opcode, smallrocket.OpResultCode_OPRC_Error, params, playerEx.betData) } } case rule.SmallRocketPlayerOpAutoSubCoin: if len(params) >= 8 { //isAutoTakeGain := params[0] betPos0 := params[1] betVal0 := params[2] takeMul0 := params[3] betPos1 := params[5] betVal1 := params[6] takeMul1 := params[7] if !sceneEx.CheckBetOp(betVal0, takeMul0) { return false } if !sceneEx.CheckBetOp(betVal1, takeMul1) { return false } if len(playerEx.betData) >= 2 && (betPos0 >= 0 && betPos0 <= 1) && (betPos1 >= 0 && betPos1 <= 1) { playerEx.betData[betPos0].BetVal = betVal0 playerEx.betData[betPos0].TakeMul = float64(takeMul0) / 100.00 playerEx.betData[betPos1].BetVal = betVal1 playerEx.betData[betPos1].TakeMul = float64(takeMul1) / 100.00 playerEx.StopBetCoin() for i := 0; i < len(playerEx.betData); i++ { // 自动下注领取 扣除金币 if playerEx.betData[i].IsCurBet && playerEx.betData[i].IsAutoBetAndTake { var gainSearchTime = float64(sceneEx.logic.GetBombTimeByBombMul(int32(playerEx.betData[i].TakeMul * float64(rule.SmallRocketPlayerTransDataMul)))) if gainSearchTime < rule.SmallRocketPlayerTransDataMul { gainSearchTime = rule.SmallRocketPlayerTransDataMul } playerEx.betData[i].GainSearchTime = time.Duration((gainSearchTime / rule.SmallRocketPlayerTransDataMul) * float64(time.Second)) if playerEx.betData[i].BetVal > 0 { playerEx.AddCoin(-playerEx.betData[i].BetVal, common.GainWay_SmallRocket, base.SyncFlag_ToClient, "system", s.GetSceneName()) } else if playerEx.betData[i].BetVal <= 0 { logger.Logger.Error("(this *StateStart) OnPlayerOp 7, sceneid:", s.GetSceneId(), " | Player SnId:", playerEx.SnId, " | BetCoinVal:", playerEx.betData[i].BetVal) playerEx.PrintBetData(rule.SmallRocketSceneStateStart) } //params = append(params, playerEx.Coin) // //sceneEx.OnPlayerSCOp(p, opcode, smallrocket.OpResultCode_OPRC_Success, params, playerEx.betData) } } playerEx.CopyToCurBetData() } else { sceneEx.OnPlayerSCOp(p, opcode, smallrocket.OpResultCode_OPRC_Error, params, playerEx.betData) } } default: return false } return false } func (this *StateStart) OnPlayerEvent(s *base.Scene, p *base.Player, evtcode int, params []int64) { logger.Logger.Trace("(this *StateStart) OnPlayerEvent, sceneId=", s.GetSceneId(), " player=", p.SnId, " evtcode=", evtcode) this.BaseState.OnPlayerEvent(s, p, evtcode, params) if sceneEx, ok := s.ExtraData.(*SceneEx); ok { switch evtcode { case base.PlayerEventLeave: if !sceneEx.CanStart() { logger.Logger.Trace("(this *StateStart) OnPlayerEvent s.ChangeSceneState(SmallRocketSceneStateWait):", s.GetSceneId()) s.ChangeSceneState(rule.SmallRocketSceneStateWait) } case base.PlayerEventEnter: if !p.IsReady() { p.MarkFlag(base.PlayerState_Ready) p.SyncFlag() } } } } // ===================================== // PlayGame 游戏中 // ===================================== type PlayGame struct { BaseState } func (this *PlayGame) GetState() int { return rule.SmallRocketSceneStatePlayGame } func (this *PlayGame) CanChangeTo(s base.SceneState) bool { switch s.GetState() { case rule.SmallRocketSceneStateBilled: return true } return false } func (this *PlayGame) OnEnter(s *base.Scene) { logger.Logger.Trace("(this *PlayGame) OnEnter, sceneid=", s.GetSceneId()) this.BaseState.OnEnter(s) s.Gaming = true sceneEx, ok := s.ExtraData.(*SceneEx) if !ok { return } for _, playerEx := range sceneEx.players { if playerEx != nil { SmallRocketSendPlayerInfo(s, playerEx, playerEx.betData, 0, 0) } } SmallRocketBroadcastRoomState(s, float32(0), float32(0)) SmallRocketBroadcastRoomBetPlayerNum(s) } func (this *PlayGame) OnPlayerOp(s *base.Scene, p *base.Player, opcode int, params []int64) bool { logger.Logger.Trace("StatePlayGame OnPlayerOp-----SnId:", p.SnId, " opcode: ", opcode, " params:", params) if this.BaseState.OnPlayerOp(s, p, opcode, params) { return true } sceneEx, ok := s.ExtraData.(*SceneEx) if !ok { return false } playerEx, ok := p.ExtraData.(*PlayerEx) if !ok { return false } //if !playerEx.IsGameing() { // //returnFunc(thirteen.OpResultCode_OPRC_Error) // return true //} // playerEx.PrintBetData(rule.SmallRocketSceneStatePlayGame) switch opcode { case rule.SmallRocketPlayerOpBet: // 为下一局下注 if len(params) >= 3 { betPos := params[0] betVal := params[1] takeMul := params[2] if !sceneEx.CheckBetOp(betVal, takeMul) { return false } if len(playerEx.betData) >= 2 && (betPos >= 0 && betPos <= 1) { // 检测能否下注 if !playerEx.CanBetCoinByPos(int(betPos), betVal) { return false } // 下一局已下注 if playerEx.betData[betPos].IsNextBet { return false } // 本局还在下注状态下 if playerEx.betData[betPos].IsCurBet && !playerEx.betData[betPos].IsTakeGain { return false } playerEx.betData[betPos].BetVal = betVal playerEx.betData[betPos].TakeMul = float64(takeMul) / 100.00 playerEx.betData[betPos].IsNextBet = true params = append(params, playerEx.Coin) sceneEx.OnPlayerSCOp(p, opcode, smallrocket.OpResultCode_OPRC_Success, params, playerEx.betData) } } case rule.SmallRocketPlayerOpCancelBet: //取消下一局下注 if len(params) >= 1 { betPos := params[0] if len(playerEx.betData) >= 2 && betPos <= 1 { // 没有下注 if !playerEx.betData[betPos].IsNextBet { return false } // 本局还在下注状态下 if playerEx.betData[betPos].IsCurBet && !playerEx.betData[betPos].IsTakeGain { return false } playerEx.betData[betPos].IsNextBet = false sceneEx.OnPlayerSCOp(p, opcode, smallrocket.OpResultCode_OPRC_Success, params, playerEx.betData) } } case rule.SmallRocketPlayerOpTakeReward: // 下车收取奖励 if len(params) >= 1 { betPos := params[0] if len(playerEx.betData) >= 2 && (betPos >= 0 && betPos <= 1) { if playerEx.betData[betPos].IsCurBet && !playerEx.betData[betPos].IsTakeGain { //var startTimeDur = time.Now().Sub(sceneEx.StateStartTime) //logger.Logger.Trace("StatePlayGame OnPlayerOp OpTakeReward:-----SnId:", playerEx.SnId, " startTimeDur: ", startTimeDur, " GainSearchTime:", playerEx.betData[betPos].GainSearchTime) gainSearchMul := sceneEx.logic.GetBombMulByBombTime(int32(this.GetTimeout(s) * rule.SmallRocketPlayerTransDataMul)) gainCoinMul := float64(gainSearchMul) / rule.SmallRocketPlayerTransDataMul gainCoin := int64(float64(playerEx.betData[betPos].BetVal) * gainCoinMul) playerEx.gainCoin += gainCoin if gainCoin > 0 { playerEx.AddCoin(gainCoin, common.GainWay_SmallRocket, base.SyncFlag_ToClient, "system", s.GetSceneName()) playerEx.CurIsWin = 1 playerEx.betData[betPos].GainCoinMul = gainCoinMul } playerEx.betData[betPos].IsTakeGain = true params = append(params, gainCoin) params = append(params, playerEx.Coin) sceneEx.OnPlayerSCOp(p, opcode, smallrocket.OpResultCode_OPRC_Success, params, playerEx.betData) SmallRocketBroadcastRoomPlayerTakeGain(s, playerEx.SnId, float64(this.GetTimeout(s))) if sceneEx.logic.IsExistRoundTakenGain(playerEx.betData) { sceneEx.SubBetPlayerNum() SmallRocketBroadcastRoomBetPlayerNum(s) } playerEx.CopyToCurBetData() } else { sceneEx.OnPlayerSCOp(p, opcode, smallrocket.OpResultCode_OPRC_Error, params, playerEx.betData) } } } case rule.SmallRocketPlayerOpSetAutoBet, rule.SmallRocketPlayerOpSetAutoTakeGain: // 设置自动下注状态 if len(params) >= 4 { isAutoTakeGain := params[0] betPos := params[1] betVal := params[2] takeMul := params[3] if !sceneEx.CheckBetOp(betVal, takeMul) { return false } if len(playerEx.betData) >= 2 && (betPos >= 0 && betPos <= 1) { // 检测能否下注 if !playerEx.CanBetCoinByPos(int(betPos), betVal) { return false } // 下一局已下注 if playerEx.betData[betPos].IsNextBet { return false } // 本局还在下注状态下 if playerEx.betData[betPos].IsCurBet && !playerEx.betData[betPos].IsTakeGain { return false } playerEx.betData[betPos].BetVal = betVal playerEx.betData[betPos].TakeMul = float64(takeMul) / 100.00 playerEx.SetAutoBetAndTake(isAutoTakeGain, betPos) params = append(params, playerEx.Coin) sceneEx.OnPlayerSCOp(p, opcode, smallrocket.OpResultCode_OPRC_Success, params, playerEx.betData) } else { sceneEx.OnPlayerSCOp(p, opcode, smallrocket.OpResultCode_OPRC_Error, params, playerEx.betData) } } default: return false } return false } func (this *PlayGame) OnTick(s *base.Scene) { this.BaseState.OnTick(s) if sceneEx, ok := s.ExtraData.(*SceneEx); ok { if time.Now().Sub(sceneEx.StateStartTime) > sceneEx.bombTime { logger.Logger.Trace("PlayGame------sceneEx.bombTime: ", sceneEx.bombTime) s.ChangeSceneState(rule.SmallRocketSceneStateBilled) } else { // 玩家自动收取功能 for _, playerEx := range sceneEx.players { if playerEx != nil && playerEx.IsAutoBetAndTake() { for i := 0; i < len(playerEx.betData); i++ { if playerEx.betData[i].IsAutoBetAndTake && playerEx.betData[i].IsCurBet && !playerEx.betData[i].IsTakeGain { if time.Now().Sub(sceneEx.StateStartTime) >= playerEx.betData[i].GainSearchTime { gainCoin := int64(float64(playerEx.betData[i].BetVal) * playerEx.betData[i].TakeMul) playerEx.gainCoin += gainCoin logger.Logger.Trace("(this *PlayGame) OnTick: SnId:", playerEx.SnId, " | timeOut: ", time.Now().Sub(sceneEx.StateStartTime), " gainSearchTime: ", playerEx.betData[i].GainSearchTime) if gainCoin > 0 { playerEx.AddCoin(gainCoin, common.GainWay_SmallRocket, base.SyncFlag_ToClient, "system", s.GetSceneName()) playerEx.CurIsWin = 1 playerEx.betData[i].GainCoinMul = playerEx.betData[i].TakeMul if playerEx.betData[i].IsCurBet { playerEx.betData[i].IsTakeGain = true } logger.Logger.Trace("(this *PlayGame) OnTick------SnId:", playerEx.SnId, " | playerEx.gainCoin: ", gainCoin) GainCoinBet1 := int64(0) GainCoinBet2 := int64(0) if i == 0 { GainCoinBet1 = gainCoin GainCoinBet2 = 0 } else if i == 1 { GainCoinBet1 = 0 GainCoinBet2 = gainCoin } SmallRocketSendPlayerInfo(s, playerEx, playerEx.betData, GainCoinBet1, GainCoinBet2) //playerEx.PrintBetData(rule.SmallRocketSceneStatePlayGame) SmallRocketBroadcastRoomPlayerTakeGain(s, playerEx.SnId, float64(this.GetTimeout(s))) if sceneEx.logic.IsExistRoundTakenGain(playerEx.betData) { //sceneEx.TotalBetPlayer-- sceneEx.SubBetPlayerNum() SmallRocketBroadcastRoomBetPlayerNum(s) } } } } } playerEx.CopyToCurBetData() } } } } } //===================================== // StateBilled 结算 //===================================== type StateBilled struct { BaseState } func (this *StateBilled) GetState() int { return rule.SmallRocketSceneStateBilled } func (this *StateBilled) CanChangeTo(s base.SceneState) bool { switch s.GetState() { case rule.SmallRocketSceneStateStart: return true } return false } func (this *StateBilled) OnPlayerOp(s *base.Scene, p *base.Player, opcode int, params []int64) bool { return false } func (this *StateBilled) OnEnter(s *base.Scene) { logger.Logger.Trace("(this *StateBilled) OnEnter, sceneid=", s.GetSceneId()) this.BaseState.OnEnter(s) if sceneEx, ok := s.ExtraData.(*SceneEx); ok { boomMul := sceneEx.BoomMul if boomMul < 1 { boomMul = 1 } // 添加历史爆炸倍数记录 sceneEx.HistoryBombMul.Push(boomMul) SmallRocketBroadcastRoomState(s, float32(0), float32(0)) // 没离开,剩余玩家结算 for _, playerEx := range sceneEx.players { if playerEx != nil { pack := &smallrocket.SCSmallRocketRoundGameBilled{ RoundId: proto.Int32(int32(sceneEx.RoundId)), BombMul: proto.Float32(float32(boomMul)), Award: proto.Int64(playerEx.gainCoin), Balance: proto.Int64(playerEx.Coin), } if sceneEx.HistoryBombMul != nil { hisBoomMul := sceneEx.HistoryBombMul.GetFloat64Items() for i := 0; i < len(hisBoomMul); i++ { pack.RoundBoomMuHistory = append(pack.RoundBoomMuHistory, float32(hisBoomMul[i])) } } // logger.Logger.Trace("SCSmallRocketRoundGameBilled is pack: ", pack) proto.SetDefaults(pack) playerEx.SendToClient(int(smallrocket.SmallRocketPacketID_PACKET_SC_SMALLROCKET_GAMEBILLED), pack) // 本局下注才记录 if sceneEx.logic.IsCurRoundBet(playerEx.CurBetData) { logger.Logger.Trace("SmallRocketSaveLog Save ", playerEx.SnId) TotalBetValue := sceneEx.logic.GetRoundBetCoin(playerEx.CurBetData) // 统计金币变动 changeCoin := playerEx.gainCoin - playerEx.taxCoin - int64(TotalBetValue) startCoin := playerEx.Coin - changeCoin sceneEx.StaticsLaba(&base.StaticLabaParam{ SnId: playerEx.SnId, Gain: changeCoin, GainTax: playerEx.taxCoin, IsAddTimes: true, }) //playerEx.SaveSceneCoinLog(startCoin, changeCoin, playerEx.GetCoin(), int64(TotalBetValue), playerEx.taxCoin, playerEx.gainCoin, 0, 0) //GainTotalBetVal := sceneEx.logic.GetRoundGainCoin(playerEx.betData, ) LogBaseResult := model.SmallRocketBaseResultType{} LogBaseResult.RoomId = int32(sceneEx.GetSceneId()) LogBaseResult.TotalBetVal = int64(TotalBetValue) LogBaseResult.BeforeCoin = startCoin LogBaseResult.AfterCoin = playerEx.GetCoin() LogBaseResult.WinCoin = playerEx.gainCoin LogBaseResult.PlayerSnid = playerEx.SnId if len(playerEx.CurBetData) >= 2 { LogBaseResult.BetCoin1 = playerEx.CurBetData[0].BetVal LogBaseResult.BetMul1 = playerEx.CurBetData[0].TakeMul LogBaseResult.IsAutoBetAndTake1 = playerEx.CurBetData[0].IsAutoBetAndTake LogBaseResult.TakeBetMul1 = playerEx.CurBetData[0].GainCoinMul LogBaseResult.BetCoin2 = playerEx.CurBetData[1].BetVal LogBaseResult.BetMul2 = playerEx.CurBetData[1].TakeMul LogBaseResult.IsAutoBetAndTake2 = playerEx.CurBetData[1].IsAutoBetAndTake LogBaseResult.TakeBetMul2 = playerEx.CurBetData[1].GainCoinMul } if !playerEx.IsRob { info, err := model.MarshalGameNoteByHUNDRED(LogBaseResult) if err == nil { sceneEx.SaveGameDetailedLog(&base.SaveGameDetailedParam{ LogId: sceneEx.logid, Detail: info, }) } totalin := int64(TotalBetValue) totalout := playerEx.gainCoin sceneEx.SaveGamePlayerListLog(&base.SaveGamePlayerListLogParam{ LogId: sceneEx.logid, Platform: playerEx.Platform, Snid: playerEx.SnId, PlayerName: playerEx.Name, Channel: playerEx.Channel, ChannelId: playerEx.ChannelId, TotalIn: totalin, TotalOut: totalout, TaxCoin: playerEx.taxCoin, BetAmount: int64(TotalBetValue), WinAmountNoAnyTax: playerEx.gainCoin, IsFirstGame: s.IsPlayerFirst(playerEx.Player), }) } } //playerEx.PrintBetData(rule.SmallRocketSceneStateBilled) playerEx.ReStartGame() //playerEx.StopBetCoin() SmallRocketSendPlayerInfo(s, playerEx, playerEx.betData, 0, 0) } } // 提前离开的 for _, playerEx := range sceneEx.PlayerBackup { if playerEx != nil && playerEx.isBilled { TotalBetValue := sceneEx.logic.GetRoundBetCoin(playerEx.CurBetData) // 统计金币变动 changeCoin := playerEx.gainCoin - playerEx.taxCoin - int64(TotalBetValue) startCoin := playerEx.Coin - changeCoin if sceneEx.logic.IsCurRoundBet(playerEx.CurBetData) { sceneEx.StaticsLaba(&base.StaticLabaParam{ SnId: playerEx.SnId, Gain: changeCoin, GainTax: playerEx.taxCoin, IsAddTimes: true, }) } //playerEx.SaveSceneCoinLog(startCoin, changeCoin, playerEx.Coin, int64(TotalBetValue), playerEx.taxCoin, playerEx.gainCoin, 0, 0) LogBaseResult := model.SmallRocketBaseResultType{} LogBaseResult.RoomId = int32(sceneEx.GetSceneId()) LogBaseResult.TotalBetVal = int64(TotalBetValue) LogBaseResult.BeforeCoin = startCoin LogBaseResult.AfterCoin = playerEx.Coin LogBaseResult.WinCoin = playerEx.gainCoin LogBaseResult.PlayerSnid = playerEx.SnId if len(playerEx.CurBetData) >= 2 { LogBaseResult.BetCoin1 = playerEx.CurBetData[0].BetVal LogBaseResult.BetMul1 = playerEx.CurBetData[0].TakeMul LogBaseResult.IsAutoBetAndTake1 = playerEx.CurBetData[0].IsAutoBetAndTake LogBaseResult.TakeBetMul1 = playerEx.CurBetData[0].GainCoinMul LogBaseResult.BetCoin2 = playerEx.CurBetData[1].BetVal LogBaseResult.BetMul2 = playerEx.CurBetData[1].TakeMul LogBaseResult.IsAutoBetAndTake2 = playerEx.CurBetData[1].IsAutoBetAndTake LogBaseResult.TakeBetMul2 = playerEx.CurBetData[1].GainCoinMul } if !playerEx.IsRob { info, err := model.MarshalGameNoteByHUNDRED(LogBaseResult) if err == nil { sceneEx.SaveGameDetailedLog(&base.SaveGameDetailedParam{ LogId: sceneEx.logid, Detail: info, }) } totalin := int64(TotalBetValue) totalout := playerEx.gainCoin //validFlow := totalin + totalout //validBet := common.AbsI64(totalin - totalout) sceneEx.SaveGamePlayerListLog(&base.SaveGamePlayerListLogParam{ LogId: sceneEx.logid, Platform: playerEx.Platform, Snid: playerEx.SnId, PlayerName: playerEx.Name, Channel: playerEx.Channel, ChannelId: playerEx.ChannelId, TotalIn: totalin, TotalOut: totalout, TaxCoin: playerEx.taxCoin, BetAmount: int64(TotalBetValue), WinAmountNoAnyTax: playerEx.gainCoin, IsFirstGame: playerEx.IsPlayerFirst, }) } } } //通知客户端结算结果 sceneEx.TotalBetPlayer = 0 //sceneEx.BoomMul = 0 sceneEx.RoundId++ s.Gaming = false } } func (this *StateBilled) OnLeave(s *base.Scene) { logger.Logger.Trace("(this *StateBilled) OnLeave, sceneid=", s.GetSceneId()) this.BaseState.OnLeave(s) if sceneEx, ok := s.ExtraData.(*SceneEx); ok { for _, playerEx := range sceneEx.players { if playerEx != nil { // 不在线停止自动下注 if !playerEx.IsOnLine() { playerEx.StopLineAutoBetCoin() sceneEx.PlayerLeave(playerEx.Player, common.PlayerLeaveReason_DropLine, true) } } } sceneEx.PlayerBackup = make(map[int32]*PlayerData) if s.CheckNeedDestroy() { sceneEx.SceneDestroy(true) } } } func (this *StateBilled) OnTick(s *base.Scene) { this.BaseState.OnTick(s) if sceneEx, ok := s.ExtraData.(*SceneEx); ok { if time.Now().Sub(sceneEx.StateStartTime) > rule.SmallRocketSceneBilledTimeout { if sceneEx.CanStart() { logger.Logger.Trace("StateStart------SmallRocketSceneBilledTimeout: ", rule.SmallRocketSceneBilledTimeout) s.ChangeSceneState(rule.SmallRocketSceneStateStart) } else { s.ChangeSceneState(rule.SmallRocketSceneStateWait) } return } } } // // ////////////////////////////////////////////////////////////////////////////// func (this *PolicySmallRocket) RegisteSceneState(state base.SceneState) { if state == nil { return } stateid := state.GetState() if stateid < 0 || stateid >= rule.SmallRocketSceneStateMax { return } this.states[stateid] = state } func (this *PolicySmallRocket) GetSceneState(s *base.Scene, stateid int) base.SceneState { if stateid >= 0 && stateid < rule.SmallRocketSceneStateMax { return this.states[stateid] } return nil } func init() { PolicySmallRocketSingleton.RegisteSceneState(&StateWait{}) PolicySmallRocketSingleton.RegisteSceneState(&StateStart{}) PolicySmallRocketSingleton.RegisteSceneState(&PlayGame{}) PolicySmallRocketSingleton.RegisteSceneState(&StateBilled{}) core.RegisteHook(core.HOOK_BEFORE_START, func() error { base.RegisteScenePolicy(common.GameId_SmallRoket, 0, PolicySmallRocketSingleton) return nil }) }