package tienlen import ( "fmt" "math" "math/rand" "sort" "time" "mongo.games.com/goserver/core" "mongo.games.com/goserver/core/logger" "mongo.games.com/game/common" rule "mongo.games.com/game/gamerule/tienlen" "mongo.games.com/game/gamesrv/base" "mongo.games.com/game/model" "mongo.games.com/game/proto" "mongo.games.com/game/protocol/tienlen" "mongo.games.com/game/srvdata" ) var ScenePolicyTienLenSingleton = &ScenePolicyTienLen{} type ScenePolicyTienLen struct { base.BaseScenePolicy states [rule.TienLenSceneStateMax]base.SceneState } // 创建场景扩展数据 func (this *ScenePolicyTienLen) CreateSceneExData(s *base.Scene) interface{} { sceneEx := NewTienLenSceneData(s) if sceneEx != nil { sceneEx.Clear() if sceneEx.init() { s.SetExtraData(sceneEx) } } return sceneEx } // 创建玩家扩展数据 func (this *ScenePolicyTienLen) CreatePlayerExData(s *base.Scene, p *base.Player) interface{} { playerEx := &TienLenPlayerData{Player: p} if playerEx != nil { playerEx.init() p.SetExtraData(playerEx) } return playerEx } // 场景开启事件 func (this *ScenePolicyTienLen) OnStart(s *base.Scene) { logger.Logger.Trace("(this *ScenePolicyTienLen) OnStart, GetSceneId()=", s.GetSceneId()) sceneEx := NewTienLenSceneData(s) if sceneEx != nil { sceneEx.Clear() if sceneEx.init() { s.SetExtraData(sceneEx) s.ChangeSceneState(rule.TienLenSceneStateWaitPlayer) } } } // 场景心跳事件 func (this *ScenePolicyTienLen) OnTick(s *base.Scene) { if s == nil { return } if s.GetSceneState() != nil { s.GetSceneState().OnTick(s) } } // 玩家进入事件 func (this *ScenePolicyTienLen) OnPlayerEnter(s *base.Scene, p *base.Player) { if s == nil || p == nil { return } logger.Logger.Trace("(this *ScenePolicyTienLen) OnPlayerEnter, GetSceneId()=", s.GetSceneId(), " player=", p.GetName()) if sceneEx, ok := s.GetExtraData().(*TienLenSceneData); ok { // pos pos := sceneEx.FindOnePos() if p.Pos != -1 && sceneEx.seats[p.Pos] == nil { pos = p.Pos } if pos < 0 || pos > 3 || sceneEx.seats[pos] != nil { p.MarkFlag(base.PlayerState_EnterSceneFailed) cnt := len(sceneEx.players) logger.Logger.Warnf("ScenePolicyTienLen.OnPlayerEnter(scene:%v, player:%v) no found fit GetPos(), current player count:%v NumOfGames:%v", s.GetSceneId(), p.SnId, cnt, sceneEx.NumOfGames) return } // playerEx playerEx := &TienLenPlayerData{Player: p} playerEx.init() playerEx.SetPos(pos) if sceneEx.GetGaming() { playerEx.MarkFlag(base.PlayerState_WaitNext) playerEx.SyncFlag() } p.SetExtraData(playerEx) // sceneEx sceneEx.seats[pos] = playerEx sceneEx.players[p.SnId] = playerEx // 广播个人信息 playerData := TienLenCreatePlayerData(p, p.GetRankScore(rule.RankType)) if sceneEx.IsMatchScene() && p.IsRob { if len(p.MatchParams) > 2 { if p.MatchParams[2] != 0 { playerData.CopySnid = p.MatchParams[2] } } if len(p.MatchParams) > 3 { if p.MatchParams[3] != 0 { playerData.CopyRoleId = p.MatchParams[3] } } if len(p.MatchParams) > 4 { if p.MatchParams[4] != 0 { playerData.SkinId = p.MatchParams[4] } } } pack := &tienlen.SCTienLenPlayerEnter{ Data: playerData, } proto.SetDefaults(pack) s.Broadcast(int(tienlen.TienLenPacketID_PACKET_SCTienLenPlayerEnter), pack, p.GetSid()) // 给自己发送房间信息 TienLenSendRoomInfo(s, p, sceneEx) s.FirePlayerEvent(p, base.PlayerEventEnter, nil) } } // 玩家离开事件 func (this *ScenePolicyTienLen) OnPlayerLeave(s *base.Scene, p *base.Player, reason int) { if s == nil || p == nil { return } logger.Logger.Trace("(this *ScenePolicyTienLen) OnPlayerLeave, GetSceneId()=", s.GetSceneId(), " player=", p.SnId) sceneEx, ok := s.GetExtraData().(*TienLenSceneData) if !ok { return } sceneEx.OnPlayerLeave(p, reason) s.FirePlayerEvent(p, base.PlayerEventLeave, []int64{int64(reason)}) } // 玩家掉线 func (this *ScenePolicyTienLen) OnPlayerDropLine(s *base.Scene, p *base.Player) { if s == nil || p == nil { return } logger.Logger.Trace("(this *ScenePolicyTienLen) OnPlayerDropLine, GetSceneId()=", s.GetSceneId(), " player=", p.Name) sceneEx, ok := s.GetExtraData().(*TienLenSceneData) if !ok { return } if sceneEx.GetGaming() { p.MarkFlag(base.PlayerState_Auto) p.SyncFlag() } else { s.PlayerLeave(p, common.PlayerLeaveReason_DropLine, true) } s.FirePlayerEvent(p, base.PlayerEventDropLine, nil) } // 玩家重连 func (this *ScenePolicyTienLen) OnPlayerRehold(s *base.Scene, p *base.Player) { if s == nil || p == nil { return } logger.Logger.Trace("(this *ScenePolicyTienLen) OnPlayerRehold, GetSceneId()=", s.GetSceneId(), " player=", p.Name) if sceneEx, ok := s.GetExtraData().(*TienLenSceneData); ok { if _, ok := p.GetExtraData().(*TienLenPlayerData); ok { if p.IsMarkFlag(base.PlayerState_Auto) { p.UnmarkFlag(base.PlayerState_Auto) p.SyncFlag() } //发送房间信息给自己 TienLenSendRoomInfo(s, p, sceneEx) s.FirePlayerEvent(p, base.PlayerEventRehold, nil) } } } // 返回房间 func (this *ScenePolicyTienLen) OnPlayerReturn(s *base.Scene, p *base.Player) { if s == nil || p == nil { return } logger.Logger.Trace("(this *ScenePolicyTienLen) OnPlayerReturn, GetSceneId()=", s.GetSceneId(), " player=", p.Name) if sceneEx, ok := s.GetExtraData().(*TienLenSceneData); ok { if _, ok := p.GetExtraData().(*TienLenPlayerData); ok { if p.IsMarkFlag(base.PlayerState_Auto) { p.UnmarkFlag(base.PlayerState_Auto) p.SyncFlag() } //发送房间信息给自己 TienLenSendRoomInfo(s, p, sceneEx) s.FirePlayerEvent(p, base.PlayerEventReturn, nil) } } } func (this *ScenePolicyTienLen) OnPlayerOp(s *base.Scene, p *base.Player, opcode int, params []int64) bool { if s == nil || p == nil { return false } logger.Logger.Trace("(this *ScenePolicyTienLen) OnPlayerOp, GetSceneId()=", s.GetSceneId(), " player=", p.GetName(), " opcode=", opcode, " params=", params) if s.GetSceneState() != nil { if s.GetSceneState().OnPlayerOp(s, p, opcode, params) { p.LastOPTimer = time.Now() return true } return false } return true } func (this *ScenePolicyTienLen) OnPlayerEvent(s *base.Scene, p *base.Player, evtcode int, params []int64) { if s == nil || p == nil { return } logger.Logger.Trace("(this *ScenePolicyTienLen) OnPlayerEvent, GetSceneId()=", s.GetSceneId(), " player=", p.GetName(), " eventcode=", evtcode, " params=", params) if s.GetSceneState() != nil { s.GetSceneState().OnPlayerEvent(s, p, evtcode, params) } } func (this *ScenePolicyTienLen) OnAudienceEnter(s *base.Scene, p *base.Player) { if s == nil || p == nil { return } logger.Logger.Trace("ScenePolicyTienLen OnAudienceEnter, sceneId=", s.SceneId, " player=", p.SnId) this.BaseScenePolicy.OnAudienceEnter(s, p) if sceneEx, ok := s.ExtraData.(*TienLenSceneData); ok { //给自己发送房间信息 p.UnmarkFlag(base.PlayerState_Leave) TienLenSendRoomInfo(s, p, sceneEx) sceneEx.BroadcastAudienceNum(p) } } func (this *ScenePolicyTienLen) OnAudienceLeave(s *base.Scene, p *base.Player, reason int) { if s == nil || p == nil { return } logger.Logger.Trace("ScenePolicyTienLen OnAudienceLeave, sceneId=", s.SceneId, " player=", p.SnId, " reason=", reason) if sceneEx, ok := s.ExtraData.(*TienLenSceneData); ok { sceneEx.BroadcastAudienceNum(p) } } func (this *ScenePolicyTienLen) OnAudienceSit(s *base.Scene, p *base.Player) { if s == nil || p == nil { return } logger.Logger.Trace("ScenePolicyTienLen OnAudienceSit, sceneId=", s.SceneId, " player=", p.SnId) sceneEx, ok := s.GetExtraData().(*TienLenSceneData) if !ok { return } if s.Gaming && !s.GetBEnterAfterStart() { return } //自动带入金币 pos := sceneEx.FindOnePos() if pos < 0 || pos > 3 || sceneEx.seats[pos] != nil { p.MarkFlag(base.PlayerState_EnterSceneFailed) cnt := len(sceneEx.players) logger.Logger.Warnf("ScenePolicyTienLen.OnAudienceSit(scene:%v, player:%v) no found fit GetPos(), current player count:%v NumOfGames:%v", s.GetSceneId(), p.SnId, cnt, sceneEx.NumOfGames) return } playerEx := &TienLenPlayerData{Player: p} playerEx.init() playerEx.SetPos(pos) p.UnmarkFlag(base.PlayerState_Audience) p.UnmarkFlag(base.PlayerState_Leave) if sceneEx.GetGaming() { playerEx.MarkFlag(base.PlayerState_WaitNext) p.SyncFlag() } p.SetExtraData(playerEx) sceneEx.seats[pos] = playerEx sceneEx.players[p.SnId] = playerEx //广播个人信息 playerData := TienLenCreatePlayerData(p, p.GetRankScore(rule.RankType)) pack := &tienlen.SCTienLenPlayerEnter{ Data: playerData, } proto.SetDefaults(pack) s.Broadcast(int(tienlen.TienLenPacketID_PACKET_SCTienLenPlayerEnter), pack, p.GetSid()) //给自己发送房间信息 TienLenSendRoomInfo(s, p, sceneEx) sceneEx.BroadcastAudienceNum(p) s.FirePlayerEvent(p, base.PlayerEventEnter, nil) } func (this *ScenePolicyTienLen) OnAudienceDropLine(s *base.Scene, p *base.Player) { if s == nil || p == nil { return } logger.Logger.Trace("ScenePolicyTienLen OnAudienceDropLine, sceneId=", s.SceneId, " player=", p.SnId) s.AudienceLeave(p, common.PlayerLeaveReason_DropLine) if sceneEx, ok := s.ExtraData.(*TienLenSceneData); ok { sceneEx.BroadcastAudienceNum(p) } } // 是否完成了整个牌局 func (this *ScenePolicyTienLen) IsCompleted(s *base.Scene) bool { if s == nil { return false } return false } // 是否可以强制开始 func (this *ScenePolicyTienLen) IsCanForceStart(s *base.Scene) bool { return false } // 当前状态能否换桌 func (this *ScenePolicyTienLen) 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 *ScenePolicyTienLen) ForceStart(s *base.Scene) { s.ChangeSceneState(rule.TienLenSceneStateWaitStart) } func TienLenCreatePlayerData(p *base.Player, rankScore int64) *tienlen.TienLenPlayerData { playerEx, _ := p.GetExtraData().(*TienLenPlayerData) pd := &tienlen.TienLenPlayerData{ Name: proto.String(p.Name), SnId: proto.Int32(p.SnId), Head: proto.Int32(p.Head), Sex: proto.Int32(p.Sex), Coin: proto.Int64(p.GetCoin()), Flag: proto.Int(p.GetFlag()), Longitude: proto.Int32(p.Longitude), Latitude: proto.Int32(p.Latitude), City: proto.String(p.City), VIP: proto.Int32(p.VIP), HeadOutLine: proto.Int32(p.HeadOutLine), NiceId: proto.Int32(p.NiceId), Pos: proto.Int(p.GetPos()), RankScore: rankScore, Level: proto.Int64(p.Level), Exp: proto.Int64(p.Exp), } if playerEx != nil { pd.ThinkLongCnt = playerEx.ThinkLongCnt } if p.Roles != nil { pd.RoleId = proto.Int32(p.Roles.ModId) } if p.Items != nil { pd.Items = make(map[int32]int32) for id, num := range p.Items { pd.Items[id] = int32(num) } } if len(p.MatchParams) > 0 { pd.MatchRankId = p.MatchParams[0] } if len(p.MatchParams) > 1 { pd.Lv = p.MatchParams[1] } if p.WelfData != nil && p.WelfData.PigBank != nil { pd.PigBankCoin = p.WelfData.PigBank.BankCoin } if p.Pets != nil && p.Pets.SkillInfo != nil { for petId, data := range p.Pets.SkillInfo { skillInfo := &tienlen.PetSkillInfo{} skillInfo.PetId = proto.Int32(petId) for skillId, SkillLevel := range data { value := &tienlen.SkillInfo{} value.SkillId = proto.Int32(skillId) value.SkillLevel = proto.Int32(SkillLevel) skillInfo.SkillData = append(skillInfo.SkillData, value) } pd.SkillInfo = append(pd.SkillInfo, skillInfo) } } if p.Skin != nil { pd.SkinId = p.Skin.ModId } logger.Logger.Trace("TienLenCreatePlayerData pd : ", pd) return pd } func TienLenCreateRoomInfoPacket(s *base.Scene, p *base.Player, sceneEx *TienLenSceneData) *tienlen.SCTienLenRoomInfo { pack := &tienlen.SCTienLenRoomInfo{ RoomId: proto.Int(s.GetSceneId()), Creator: proto.Int32(s.GetCreator()), GameId: proto.Int(s.GetGameId()), RoomMode: proto.Int(s.GetSceneMode()), Params: common.CopySliceInt64ToInt32(s.GetParams()), State: proto.Int32(int32(s.GetSceneState().GetState())), TimeOut: proto.Int(s.GetSceneState().GetTimeout(s)), NumOfGames: proto.Int(sceneEx.NumOfGames), TotalOfGames: sceneEx.TotalOfGames, CurOpIdx: proto.Int(-1), MasterSnid: proto.Int32(sceneEx.masterSnid), AudienceNum: proto.Int(s.GetAudiencesNum()), BaseScore: proto.Int32(s.GetBaseScore()), MaxPlayerNum: proto.Int(s.GetPlayerNum()), RankType: s.GetDBGameFree().GetRankType(), SceneAdd: s.GetDBGameFree().GetSceneAdd(), // 比赛场相关 Round: s.GetMatch().GetCurrRound(), CurPlayerNum: s.GetMatch().GetCurrPlayerNum(), NextNeed: s.GetMatch().GetNextPlayerNum(), RecordId: sceneEx.recordId, RoomTypeId: s.GetCustom().GetRoomTypeId(), RoomConfigId: s.GetCustom().GetRoomConfigId(), CostType: s.GetCustom().GetCostType(), Voice: s.GetCustom().GetVoice(), Password: s.GetCustom().GetPassword(), } if s.GetCustom().GetPassword() != "" { pack.NeedPassword = 1 } pack.IsMatch = int32(0) // 0.普通场 1.锦标赛 2.冠军赛 3.vip专属 if s.IsMatchScene() { pack.IsMatch = s.GetMatch().GetMatchType() } pack.MatchFinals = 0 if s.GetMatch().GetIsFinals() { pack.MatchFinals = 1 if s.NumOfGames >= 2 { pack.MatchFinals = 2 } } for _, snid := range sceneEx.winSnids { pack.WinSnids = append(pack.WinSnids, snid) } if s.GetSceneState().GetState() == rule.TienLenSceneStateBilled { sceneEx.currOpPos = -1 pack.CurOpIdx = proto.Int32(-1) } if s.GetSceneState().GetState() >= rule.TienLenSceneStatePlayerOp { pack.CurOpIdx = proto.Int32(sceneEx.currOpPos) } playerEx, _ := p.GetExtraData().(*TienLenPlayerData) //玩家信息.第一个必然是自己 pd := TienLenCreatePlayerData(p, p.GetRankScore(rule.RankType)) if playerEx != nil { //手牌 for i := int32(0); i < rule.HandCardNum; i++ { if playerEx.cards[i] != rule.InvalideCard { pd.Cards = append(pd.Cards, playerEx.cards[i]) } } if sceneEx.IsMatchScene() && p.IsRob { if len(p.MatchParams) > 2 { if p.MatchParams[2] != 0 { pd.CopySnid = p.MatchParams[2] } } if len(p.MatchParams) > 3 { if p.MatchParams[3] != 0 { pd.CopyRoleId = p.MatchParams[3] } } if len(p.MatchParams) > 4 { if p.MatchParams[4] != 0 { pd.SkinId = p.MatchParams[4] } } } pack.IsOutRecord = playerEx.CanUseRecordItem() pack.ItemRecExpireTime = playerEx.ItemRecExpireTime } pack.Players = append(pack.Players, pd) //剩下的按座位排序 for i := 0; i < sceneEx.GetPlayerNum(); i++ { nowPlayer := sceneEx.seats[i] if nowPlayer != nil { if nowPlayer.SnId != p.SnId { pd1 := TienLenCreatePlayerData(nowPlayer.Player, nowPlayer.Player.GetRankScore(rule.RankType)) if sceneEx.IsMatchScene() && nowPlayer.IsRob { if len(nowPlayer.MatchParams) > 2 { if nowPlayer.MatchParams[2] != 0 { pd1.CopySnid = nowPlayer.MatchParams[2] } } if len(nowPlayer.MatchParams) > 3 { if nowPlayer.MatchParams[3] != 0 { pd1.CopyRoleId = nowPlayer.MatchParams[3] } } if len(nowPlayer.MatchParams) > 4 { if nowPlayer.MatchParams[4] != 0 { pd1.SkinId = nowPlayer.MatchParams[4] } } } //手牌 for j := int32(0); j < rule.HandCardNum; j++ { if nowPlayer.cards[j] != rule.InvalideCard { if s.GetSceneState().GetState() == rule.TienLenSceneStateBilled || p.IsMarkFlag(base.PlayerState_Audience) { //结算状态显示用 pd1.Cards = append(pd1.Cards, nowPlayer.cards[j]) } else { pd1.Cards = append(pd1.Cards, rule.InvalideCard) } } } pack.Players = append(pack.Players, pd1) } } } //上两手玩家出的牌(有序) insertNum := 0 for i := len(sceneEx.delOrders) - 1; i >= 0 && insertNum < 2; i-- { lastDelCard := &tienlen.LastDelCard{} delCards := sceneEx.delCards[i] for j := 0; j < len(delCards); j++ { lastDelCard.Cards = append(lastDelCard.Cards, delCards[j]) } pack.LastDelCards = append(pack.LastDelCards, lastDelCard) insertNum++ } for _, cards := range sceneEx.card_play_action_seq_int32 { for _, card := range cards { if card >= 0 { pack.OutCardRecord = append(pack.OutCardRecord, card) } } } proto.SetDefaults(pack) return pack } func TienLenSendRoomInfo(s *base.Scene, p *base.Player, sceneEx *TienLenSceneData) { pack := TienLenCreateRoomInfoPacket(s, p, sceneEx) ok := p.SendToClient(int(tienlen.TienLenPacketID_PACKET_SCTienLenRoomInfo), pack) logger.Logger.Trace("SCTienLenSendRoomInfo isok : ", ok, ",pack", pack) } // ///////////////////////////////////////////////////////////////////////////////////////////////////////////// // BaseState // ///////////////////////////////////////////////////////////////////////////////////////////////////////////// type SceneBaseStateTienLen struct { } func (this *SceneBaseStateTienLen) GetTimeout(s *base.Scene) int { if sceneEx, ok := s.GetExtraData().(*TienLenSceneData); ok { return int(time.Now().Sub(sceneEx.StateStartTime) / time.Second) } return 0 } func (this *SceneBaseStateTienLen) CanChangeTo(s base.SceneState) bool { return true } // 当前状态能否换桌 func (this *SceneBaseStateTienLen) CanChangeCoinScene(s *base.Scene, p *base.Player) bool { return !p.IsGameing() || s.GetDestroyed() } func (this *SceneBaseStateTienLen) OnEnter(s *base.Scene) { if sceneEx, ok := s.GetExtraData().(*TienLenSceneData); ok { sceneEx.StateStartTime = time.Now() } } func (this *SceneBaseStateTienLen) OnLeave(s *base.Scene) {} func (this *SceneBaseStateTienLen) OnTick(s *base.Scene) { //场景状态是所有房间公用,房间的私有属性不能放到场景状态上 if time.Now().Unix() > s.GetTimerRandomRobot() { s.RandRobotCnt() s.SetTimerRandomRobot(s.GetRobotTime()) } } // 发送玩家操作情况 func (this *SceneBaseStateTienLen) OnPlayerSToCOp(s *base.Scene, p *base.Player, pos int, opcode int, opRetCode tienlen.OpResultCode, params []int64) { pack := &tienlen.SCTienLenPlayerOp{ OpCode: proto.Int(opcode), SnId: proto.Int32(p.SnId), OpRetCode: opRetCode, OpParam: params, } proto.SetDefaults(pack) p.SendToClient(int(tienlen.TienLenPacketID_PACKET_SCTienLenPlayerOp), pack) //logger.Logger.Trace("发送玩家操作情况 ", pack) } // 广播发送玩家操作情况 func (this *SceneBaseStateTienLen) BroadcastPlayerSToCOp(s *base.Scene, snid int32, pos int, opcode int, opRetCode tienlen.OpResultCode, params []int64) { pack := &tienlen.SCTienLenPlayerOp{ OpCode: proto.Int(opcode), SnId: proto.Int32(snid), OpRetCode: opRetCode, OpParam: params, } proto.SetDefaults(pack) s.Broadcast(int(tienlen.TienLenPacketID_PACKET_SCTienLenPlayerOp), pack, 0) if opRetCode == tienlen.OpResultCode_OPRC_Sucess { cards := []int{} for _, param := range params { cards = append(cards, rule.ValueStr(int32(param))) } //logger.Logger.Trace("广播发送玩家操作情况 ", pack, " snid:", snid, " cards:", cards) } } func (this *SceneBaseStateTienLen) OnPlayerOp(s *base.Scene, p *base.Player, opcode int, params []int64) bool { logger.Logger.Trace("SceneBaseStateTienLen.", " s.GetSceneId() : ", s.GetSceneId(), " p.SnId : ", p.SnId, " opcode : ", opcode, " params ", params) sceneEx, _ := s.GetExtraData().(*TienLenSceneData) if sceneEx == nil { return true } playerEx, _ := p.GetExtraData().(*TienLenPlayerData) if playerEx == nil { return true } switch opcode { case int(rule.TienLenPlayerOpTest): if !common.Config.IsDevMode { return false } sceneEx.testPokers = make([]int32, len(params)+1) sceneEx.testPokers[0] = p.SnId copy(sceneEx.testPokers[1:], common.Int64ToInt32(params)) return true case int(rule.TienLenPlayerOpCanelAuto): //取消托管 playerEx.LeaveAutoState(s) this.OnPlayerSToCOp(s, p, playerEx.GetPos(), opcode, tienlen.OpResultCode_OPRC_Sucess, params) return true } return false } func (this *SceneBaseStateTienLen) OnPlayerEvent(s *base.Scene, p *base.Player, evtcode int, params []int64) { sceneEx, ok := s.GetExtraData().(*TienLenSceneData) if ok { // 没有防住,选房主 if sceneEx.GetPlayer(sceneEx.masterSnid) == nil { findOne := false for i := 0; i < sceneEx.GetPlayerNum(); i++ { playerExSeat := sceneEx.seats[i] if playerExSeat != nil && playerExSeat.SnId != sceneEx.masterSnid { sceneEx.masterSnid = playerExSeat.SnId sceneEx.BroadcastUpdateMasterSnid() findOne = true break } } if !findOne { sceneEx.masterSnid = 0 sceneEx.BroadcastUpdateMasterSnid() } } } } func (this *SceneBaseStateTienLen) BroadcastRoomState(s *base.Scene, state int, params ...int64) { pack := &tienlen.SCTienLenRoomState{ State: proto.Int(state), Params: params, } proto.SetDefaults(pack) s.Broadcast(int(tienlen.TienLenPacketID_PACKET_SCTienLenRoomState), pack, 0) } // ///////////////////////////////////////////////////////////////////////////////////////////////////////////// // TienLenSceneStateWaitPlayer // ///////////////////////////////////////////////////////////////////////////////////////////////////////////// type SceneWaitPlayerStateTienLen struct { SceneBaseStateTienLen } func (this *SceneWaitPlayerStateTienLen) GetState() int { return rule.TienLenSceneStateWaitPlayer } func (this *SceneWaitPlayerStateTienLen) CanChangeTo(s base.SceneState) bool { if s.GetState() == rule.TienLenSceneStateWaitStart || s.GetState() == rule.TienLenSceneStateHandCard { return true } return false } // 当前状态能否换桌 func (this *SceneWaitPlayerStateTienLen) CanChangeCoinScene(s *base.Scene, p *base.Player) bool { if s.IsMatchScene() { return false } return true } func (this *SceneWaitPlayerStateTienLen) OnEnter(s *base.Scene) { this.SceneBaseStateTienLen.OnEnter(s) if sceneEx, ok := s.GetExtraData().(*TienLenSceneData); ok { sceneEx.Clear() sceneEx.SetGaming(false) this.BroadcastRoomState(s, this.GetState()) } } // 状态离开时 func (this *SceneWaitPlayerStateTienLen) OnLeave(s *base.Scene) { this.SceneBaseStateTienLen.OnLeave(s) logger.Logger.Tracef("(this *SceneWaitPlayerStateTienLen) OnLeave, sceneid=%v", s.GetSceneId()) } // 玩家操作 func (this *SceneWaitPlayerStateTienLen) OnPlayerOp(s *base.Scene, p *base.Player, opcode int, params []int64) bool { if this.SceneBaseStateTienLen.OnPlayerOp(s, p, opcode, params) { return true } return true } // 玩家事件 func (this *SceneWaitPlayerStateTienLen) OnPlayerEvent(s *base.Scene, p *base.Player, evtcode int, params []int64) { logger.Logger.Trace("(this *SceneWaitPlayerStateTienLen) OnPlayerEvent, GetSceneId()=", s.GetSceneId(), " player=", p.Name, " evtcode=", evtcode) this.SceneBaseStateTienLen.OnPlayerEvent(s, p, evtcode, params) if _, ok := p.GetExtraData().(*TienLenPlayerData); ok { if sceneEx, ok := s.GetExtraData().(*TienLenSceneData); ok { switch evtcode { case base.PlayerEventEnter: //如果有人进入, 检查在线人是否能够开启游戏,够的话,切换到延迟开启状态 if sceneEx.CanStart() { logger.Logger.Tracef("(this *SceneWaitPlayerStateTienLen) OnPlayerEvent s.ChangeSceneState(TienLenSceneStateWaitStart) %v", s.GetSceneId()) s.ChangeSceneState(rule.TienLenSceneStateWaitStart) } } } } } func (this *SceneWaitPlayerStateTienLen) OnTick(s *base.Scene) { this.SceneBaseStateTienLen.OnTick(s) if sceneEx, ok := s.GetExtraData().(*TienLenSceneData); ok { if s.CheckNeedDestroy() { sceneEx.SceneDestroy(true) return } if sceneEx.CanStart() { logger.Logger.Tracef("(this *SceneWaitPlayerStateTienLen) OnTick s.ChangeSceneState(TienLenSceneStateWaitStart) %v", s.GetSceneId()) s.ChangeSceneState(rule.TienLenSceneStateWaitStart) } else if !s.GetGaming() && s.GetRobotNum() == 1 { tNow := time.Now() for _, p := range s.Players { if p.IsRob && tNow.Sub(p.GetLastOPTimer()) > time.Second*time.Duration(30+rand.Int63n(60)) { //p.LastOPTimer = tNow.Add(time.Minute * 30) s.PlayerLeave(p, common.PlayerLeaveReason_Normal, true) } } } } } // ///////////////////////////////////////////////////////////////////////////////////////////////////////////// // TienLenSceneStateWaitStart // ///////////////////////////////////////////////////////////////////////////////////////////////////////////// type SceneWaitStartStateTienLen struct { SceneBaseStateTienLen } func (this *SceneWaitStartStateTienLen) GetState() int { return rule.TienLenSceneStateWaitStart } func (this *SceneWaitStartStateTienLen) CanChangeTo(s base.SceneState) bool { if s.GetState() == rule.TienLenSceneStateWaitPlayer || s.GetState() == rule.TienLenSceneStateWaitStart || s.GetState() == rule.TienLenSceneStateHandCard { return true } return false } // 当前状态能否换桌 func (this *SceneWaitStartStateTienLen) CanChangeCoinScene(s *base.Scene, p *base.Player) bool { if s.IsMatchScene() { return false } return true } func (this *SceneWaitStartStateTienLen) OnEnter(s *base.Scene) { this.SceneBaseStateTienLen.OnEnter(s) if sceneEx, ok := s.GetExtraData().(*TienLenSceneData); ok { sceneEx.Clear() sceneEx.SetGaming(false) this.BroadcastRoomState(s, this.GetState()) logger.Logger.Trace("(this *SceneWaitStartStateTienLen) OnEnter", this.GetState()) } } // 状态离开时 func (this *SceneWaitStartStateTienLen) OnLeave(s *base.Scene) { this.SceneBaseStateTienLen.OnLeave(s) logger.Logger.Tracef("(this *SceneWaitStartStateTienLen) OnLeave", this.GetState()) } // 玩家操作 func (this *SceneWaitStartStateTienLen) OnPlayerOp(s *base.Scene, p *base.Player, opcode int, params []int64) bool { if this.SceneBaseStateTienLen.OnPlayerOp(s, p, opcode, params) { return true } sceneEx, _ := s.GetExtraData().(*TienLenSceneData) if sceneEx != nil { playerEx, _ := p.GetExtraData().(*TienLenPlayerData) if playerEx != nil { opRetCode := tienlen.OpResultCode_OPRC_Error if playerEx.SnId == sceneEx.masterSnid && this.GetState() == rule.TienLenSceneStateWaitStart { if sceneEx.IsMatchScene() { return false } switch int32(opcode) { case rule.TienLenPlayerOpStart: //房主开始游戏 if sceneEx.CanStart() == false { s.ChangeSceneState(rule.TienLenSceneStateWaitPlayer) } else { opRetCode = tienlen.OpResultCode_OPRC_Sucess s.ChangeSceneState(rule.TienLenSceneStateHandCard) } } } if opRetCode == tienlen.OpResultCode_OPRC_Sucess { this.OnPlayerSToCOp(s, p, playerEx.GetPos(), opcode, opRetCode, params) } else { logger.Logger.Tracef("SceneWaitStartStateTienLen OnPlayerOp snid:%v, masterSnid:%v", playerEx.SnId, sceneEx.masterSnid) } } } return true } // 玩家事件 func (this *SceneWaitStartStateTienLen) OnPlayerEvent(s *base.Scene, p *base.Player, evtcode int, params []int64) { logger.Logger.Trace("(this *SceneWaitStartStateTienLen) OnPlayerEvent, GetSceneId()=", s.GetSceneId(), " player=", p.Name, " evtcode=", evtcode) this.SceneBaseStateTienLen.OnPlayerEvent(s, p, evtcode, params) if sceneEx, ok := s.GetExtraData().(*TienLenSceneData); ok { switch evtcode { case base.PlayerEventLeave: //如果有人退出, 检查在线人是否能够开启游戏,不够的话,切换到等待状态 if sceneEx.CanStart() == false { s.ChangeSceneState(rule.TienLenSceneStateWaitPlayer) } } } } func (this *SceneWaitStartStateTienLen) OnTick(s *base.Scene) { this.SceneBaseStateTienLen.OnTick(s) if sceneEx, ok := s.GetExtraData().(*TienLenSceneData); ok { if sceneEx.IsMatchScene() { delayT := time.Second * 2 if sceneEx.GetMatch().GetCurrRound() != 1 { //第一轮延迟2s,其他延迟3s 配合客户端播放动画 delayT = time.Second * 4 } if time.Now().Sub(sceneEx.StateStartTime) > delayT { s.ChangeSceneState(rule.TienLenSceneStateHandCard) // 比赛场直接发牌 return } } if sceneEx.SceneMode == common.SceneMode_Public { if time.Now().Sub(sceneEx.StateStartTime) > rule.TienLenWaitStartTimeout { if sceneEx.Creator != 0 && sceneEx.GetRealPlayerNum() == 0 { sceneEx.Destroy(true) return } //开始前再次检查开始条件 if sceneEx.CanStart() == true { s.ChangeSceneState(rule.TienLenSceneStateHandCard) } else { s.ChangeSceneState(rule.TienLenSceneStateWaitPlayer) } } } } } // ///////////////////////////////////////////////////////////////////////////////////////////////////////////// // TienLenSceneStateHandCard 发牌 // ///////////////////////////////////////////////////////////////////////////////////////////////////////////// type SceneHandCardStateTienLen struct { SceneBaseStateTienLen } func (this *SceneHandCardStateTienLen) GetState() int { return rule.TienLenSceneStateHandCard } func (this *SceneHandCardStateTienLen) CanChangeTo(s base.SceneState) bool { if s.GetState() == rule.TienLenSceneStatePlayerOp || s.GetState() == rule.TienLenSceneStateBilled { return true } return false } func (this *SceneHandCardStateTienLen) OnEnter(s *base.Scene) { this.SceneBaseStateTienLen.OnEnter(s) if sceneEx, ok := s.GetExtraData().(*TienLenSceneData); ok { sceneEx.Clear() sceneEx.SetGaming(true) sceneEx.GameNowTime = time.Now() sceneEx.AllPlayerEnterGame() //参与游戏次数 for i := 0; i < sceneEx.GetPlayerNum(); i++ { playerEx := sceneEx.seats[i] if playerEx != nil { if playerEx.IsGameing() { // 首次进入赠送记牌器 sceneEx.SendFirstGiveTimeItem(playerEx.Player) playerEx.GameTimes++ sceneEx.curGamingPlayerNum++ if playerEx.IsRob { playerEx.robotGameTimes-- sceneEx.robotGamingNum++ } } } } s.NumOfGames++ s.NotifySceneRoundStart(s.NumOfGames) this.BroadcastRoomState(s, this.GetState(), int64(s.NumOfGames)) if s.IsCustom() && s.NumOfGames == 1 { s.SyncSceneState(common.SceneStateStart) } //同步防伙牌数据 sceneEx.SyncScenePlayer() //发牌 if rule.TestOpen { sceneEx.SendHandCardTest() } else { if sceneEx.IsMatchScene() || sceneEx.IsCustom() { sceneEx.SendHandCard_Match() } else { sceneEx.SendHandCardOdds() } } for _, seat := range sceneEx.seats { if seat != nil { tmpCards := seat.cards[:] sceneEx.allPlayerCards = append(sceneEx.allPlayerCards, tmpCards) logger.Logger.Info("--------------------------------------allplayerCards = ", sceneEx.allPlayerCards) seat.tianHu = 0 switch { case rule.Have2FourBomb(tmpCards): seat.tianHu = rule.TianHu2Four case rule.Have6StraightTwin(tmpCards): seat.tianHu = rule.TianHu6StraightTwin case rule.Have12Straight(tmpCards): seat.tianHu = rule.TianHu12Straight } if seat.tianHu > 0 { keyNovice := common.GetKeyNoviceGameId(int(sceneEx.GameId)) data, ok := seat.GDatas[keyNovice] if !ok { data = &model.PlayerGameInfo{FirstTime: time.Now()} seat.GDatas[keyNovice] = data } data.Statics.Incr(rule.StaticsTianHuTimes) sceneEx.tianHuSnids = append(sceneEx.tianHuSnids, seat.SnId) // 天胡玩家 if !common.InSliceInt32(sceneEx.winSnids, seat.SnId) { sceneEx.winSnids = append(sceneEx.winSnids, seat.SnId) // 赢家snid } } // 手牌分数 cardsTypeMap := rule.GetCardsType(tmpCards, sceneEx.IsTienLenYule()) score, _ := rule.GetCardTypeScore(cardsTypeMap, sceneEx.IsTienLenYule(), tmpCards) seat.cardScore = score } } if len(sceneEx.tianHuSnids) == 0 { //没有天胡玩家 //有赢家,赢家先出;无赢家手持最小牌先 pos := int32(sceneEx.FindWinPos()) if pos == -1 { pos = sceneEx.startOpPos } pack := &tienlen.SCTienLenFirstOpPos{ Pos: proto.Int32(pos), } proto.SetDefaults(pack) sceneEx.Broadcast(int(tienlen.TienLenPacketID_PACKET_SCTienLenFirstOpPos), pack, 0) logger.Logger.Trace("SCTienLenFirstOpPos: ", pack) } } } // 状态离开时 func (this *SceneHandCardStateTienLen) OnLeave(s *base.Scene) { this.SceneBaseStateTienLen.OnLeave(s) logger.Logger.Tracef("(this *SceneHandCardStateTienLen) OnLeave, sceneid=%v", s.GetSceneId()) } // 玩家操作 func (this *SceneHandCardStateTienLen) OnPlayerOp(s *base.Scene, p *base.Player, opcode int, params []int64) bool { if this.SceneBaseStateTienLen.OnPlayerOp(s, p, opcode, params) { return true } return true } // 玩家事件 func (this *SceneHandCardStateTienLen) OnPlayerEvent(s *base.Scene, p *base.Player, evtcode int, params []int64) { logger.Logger.Trace("(this *SceneHandCardStateTienLen) OnPlayerEvent, GetSceneId()=", s.GetSceneId(), " player=", p.Name, " evtcode=", evtcode) this.SceneBaseStateTienLen.OnPlayerEvent(s, p, evtcode, params) } func (this *SceneHandCardStateTienLen) OnTick(s *base.Scene) { this.SceneBaseStateTienLen.OnTick(s) if sceneEx, ok := s.GetExtraData().(*TienLenSceneData); ok { newTime := rule.TienLenHandCardTimeout if sceneEx.isAllRob { newTime = time.Second * 1 } if time.Now().Sub(sceneEx.StateStartTime) > newTime { if len(sceneEx.tianHuSnids) != 0 { //天胡牌型直接结算 logger.Logger.Trace("tianHu to Billed: ", sceneEx.tianHuSnids) s.ChangeSceneState(rule.TienLenSceneStateBilled) } else { //正常出牌:有赢家,赢家先出;无赢家手持最小牌先出(最小牌必出) winPos := sceneEx.FindWinPos() if winPos != -1 { //有赢家 sceneEx.SetCurOpPos(int32(winPos)) } else { sceneEx.SetCurOpPos(sceneEx.startOpPos) } s.ChangeSceneState(rule.TienLenSceneStatePlayerOp) } } } } // ///////////////////////////////////////////////////////////////////////////////////////////////////////////// // TienLenSceneStatePlayerOp 出牌(玩家操作阶段) // ///////////////////////////////////////////////////////////////////////////////////////////////////////////// type ScenePlayerOpStateTienLen struct { SceneBaseStateTienLen } func (this *ScenePlayerOpStateTienLen) GetState() int { return rule.TienLenSceneStatePlayerOp } func (this *ScenePlayerOpStateTienLen) CanChangeTo(s base.SceneState) bool { if s.GetState() == rule.TienLenSceneStateBilled { return true } return false } func (this *ScenePlayerOpStateTienLen) OnEnter(s *base.Scene) { this.SceneBaseStateTienLen.OnEnter(s) this.BroadcastRoomState(s, this.GetState()) sceneEx, _ := s.GetExtraData().(*TienLenSceneData) if sceneEx != nil { sceneEx.BroadcastOpPos() } } // 状态离开时 func (this *ScenePlayerOpStateTienLen) OnLeave(s *base.Scene) { this.SceneBaseStateTienLen.OnLeave(s) logger.Logger.Tracef("(this *SceneHandCardStateTienLen) OnLeave, sceneid=%v", s.GetSceneId()) } // 玩家操作 func (this *ScenePlayerOpStateTienLen) OnPlayerOp(s *base.Scene, p *base.Player, opcode int, params []int64) bool { if this.SceneBaseStateTienLen.OnPlayerOp(s, p, opcode, params) { return true } sceneEx, _ := s.GetExtraData().(*TienLenSceneData) if sceneEx != nil { playerEx, _ := p.GetExtraData().(*TienLenPlayerData) if playerEx != nil { if sceneEx.GetCurOpPos() != int32(playerEx.GetPos()) { return false } opRetCode := tienlen.OpResultCode_OPRC_Error switch int32(opcode) { case rule.TienLenPlayerOpPlay: //出牌 delCards := []int32{} for _, card := range params { isHave := false for _, hcard := range playerEx.cards { //去手牌里找找看有没有 if int32(card) == hcard && hcard != rule.InvalideCard { isHave = true } } if isHave { delCards = append(delCards, int32(card)) } else { opRetCode = tienlen.OpResultCode_OPRC_Error break } } if len(delCards) == len(params) && len(delCards) > 0 { isRule, _ := rule.RulePopEnable(delCards) ruleType := rule.Tienlen_Pass if sceneEx.IsTienLenYule() { isRule, ruleType = rule.RulePopEnable_yl(delCards) } //logger.Logger.Trace("ScenePlayerOpStateTienLen,2params:", params, " isRule:", isRule) if isRule { //符合出牌规则 if int32(playerEx.GetPos()) == sceneEx.lastOpPos || sceneEx.lastOpPos == rule.InvalidePos { //当前操作者和上一个操作者是同一个人,必出牌 if ruleType == rule.Plane_Single { //飞机带单只能最后一手出 haveCardNum := 0 for _, hcard := range playerEx.cards { if hcard != rule.InvalideCard { haveCardNum++ } } if len(delCards) != haveCardNum { isRule = false opRetCode = tienlen.OpResultCode_OPRC_Error logger.Logger.Trace("Plane_Single, delCards:", delCards, " haveCardNum:", haveCardNum) } } if isRule { if sceneEx.lastOpPos == rule.InvalidePos { //首出玩家 //有赢家,赢家先出,出牌不受限制 //无赢家,手持最小牌先出,最小牌必先出 winPos := sceneEx.FindWinPos() //logger.Logger.Trace("ScenePlayerOpStateTienLen,8params:", params, " winPos:", winPos) if winPos == -1 { //无赢家 haveMinCard := false for _, card := range delCards { if card == sceneEx.curMinCard { //最小牌必先出 haveMinCard = true } } //logger.Logger.Trace("ScenePlayerOpStateTienLen,9params:", params, " curMinCard:", sceneEx.curMinCard, " haveMinCard", haveMinCard) if haveMinCard { isDel := sceneEx.DelCards(playerEx, delCards) //logger.Logger.Trace("ScenePlayerOpStateTienLen,3params:", params, " isDel:", isDel) if isDel { playerEx.RefreshThinkLongCnt(time.Now().Sub(sceneEx.StateStartTime), false) sceneEx.DoNext(int32(playerEx.GetPos())) opRetCode = tienlen.OpResultCode_OPRC_Sucess sceneEx.SetLastOpPos(int32(playerEx.GetPos())) sceneEx.RefreshPlayerHandLimitTimeOut() } } } else { isDel := sceneEx.DelCards(playerEx, delCards) //logger.Logger.Trace("ScenePlayerOpStateTienLen,10params:", params, " isDel:", isDel) if isDel { playerEx.RefreshThinkLongCnt(time.Now().Sub(sceneEx.StateStartTime), false) sceneEx.DoNext(int32(playerEx.GetPos())) opRetCode = tienlen.OpResultCode_OPRC_Sucess sceneEx.SetLastOpPos(int32(playerEx.GetPos())) sceneEx.RefreshPlayerHandLimitTimeOut() } } } else { isDel := sceneEx.DelCards(playerEx, delCards) //logger.Logger.Trace("ScenePlayerOpStateTienLen,4params:", params, " isDel:", isDel) if isDel { playerEx.RefreshThinkLongCnt(time.Now().Sub(sceneEx.StateStartTime), false) nextPos := sceneEx.DoNext(int32(playerEx.GetPos())) //logger.Logger.Trace("ScenePlayerOpStateTienLen,4paramssss:", params, " nextPos:", nextPos) if sceneEx.IsTienLenToEnd() && nextPos == rule.InvalidePos { sceneEx.UnmarkPass() nextPos = sceneEx.DoNext(int32(playerEx.GetPos())) //logger.Logger.Trace("ScenePlayerOpStateTienLen,4paramssss:", params, " nextPos:", nextPos) } opRetCode = tienlen.OpResultCode_OPRC_Sucess sceneEx.SetLastOpPos(int32(playerEx.GetPos())) sceneEx.RefreshPlayerHandLimitTimeOut() } } if opRetCode == tienlen.OpResultCode_OPRC_Sucess { isBomb := rule.IsFourBomb(delCards) if isBomb { sceneEx.isKongBomb = true } } sceneEx.UnmarkPass() } } else { //当前操作者和上一个操作者不是同一个人,必压制 if !playerEx.isPass { lastOpPlayer := sceneEx.GetLastOpPlayer() //logger.Logger.Trace("ScenePlayerOpStateTienLen,5params:", params, " lastOpPlayer:", lastOpPlayer) if lastOpPlayer != nil && len(lastOpPlayer.delCards) != 0 { lastDelCards := lastOpPlayer.delCards[len(lastOpPlayer.delCards)-1] canDel, isBomb, bombScore := rule.CanDel(lastDelCards, delCards, sceneEx.IsTienLenToEnd()) if sceneEx.IsTienLenYule() { canDel, isBomb, bombScore = rule.CanDel_yl(lastDelCards, delCards, sceneEx.IsTienLenToEnd()) } //logger.Logger.Trace("ScenePlayerOpStateTienLen,6params:", params, " canDel:", canDel, " lastDelCards:", lastDelCards) if canDel { if isBomb { sceneEx.curBombPos = int32(playerEx.GetPos()) sceneEx.lastBombPos = sceneEx.lastOpPos sceneEx.roundScore += bombScore } else { sceneEx.curBombPos = rule.InvalidePos sceneEx.lastBombPos = rule.InvalidePos sceneEx.roundScore = 0 } isDel := sceneEx.DelCards(playerEx, delCards) //logger.Logger.Trace("ScenePlayerOpStateTienLen,7params:", params, " isDel:", isDel) if isDel { playerEx.RefreshThinkLongCnt(time.Now().Sub(sceneEx.StateStartTime), false) nextPos := sceneEx.DoNext(int32(playerEx.GetPos())) if sceneEx.IsTienLenToEnd() && nextPos == rule.InvalidePos { sceneEx.UnmarkPass() sceneEx.DoNext(int32(playerEx.GetPos())) } sceneEx.SetLastOpPos(int32(playerEx.GetPos())) sceneEx.RefreshPlayerHandLimitTimeOut() opRetCode = tienlen.OpResultCode_OPRC_Sucess sceneEx.isKongBomb = false } } } } } } } case rule.TienLenPlayerOpPass: //过牌 if int32(playerEx.GetPos()) == sceneEx.lastOpPos { //当前操作者和上一个操作者是同一个人,必出牌,不能过牌 opRetCode = tienlen.OpResultCode_OPRC_Error } else { if sceneEx.lastOpPos != rule.InvalidePos { playerEx.RefreshThinkLongCnt(time.Now().Sub(sceneEx.StateStartTime), false) sceneEx.card_play_action_seq = append(sceneEx.card_play_action_seq, fmt.Sprintf("%v-过", playerEx.GetPos())) sceneEx.card_play_action_seq_int32 = append(sceneEx.card_play_action_seq_int32, []int32{-1}) nextPos := sceneEx.DoNext(int32(playerEx.GetPos())) if sceneEx.IsTienLenToEnd() && nextPos == rule.InvalidePos { sceneEx.UnmarkPass() nextPos = sceneEx.DoNext(int32(playerEx.GetPos())) sceneEx.SetLastOpPos(int32(nextPos)) } sceneEx.RefreshPlayerHandLimitTimeOut() opRetCode = tienlen.OpResultCode_OPRC_Sucess playerEx.isPass = true if nextPos == sceneEx.lastOpPos { //一轮都不出牌 sceneEx.TrySmallGameBilled() } } } case rule.TienLenPlayerClientHintCards: if int32(playerEx.GetPos()) == sceneEx.lastOpPos || sceneEx.lastOpPos == rule.InvalidePos { logger.Logger.Trace("ScenePlayerOpStateTienLen,107 OPRC_Error:", params, " opcode:", opcode, " snid:", p.SnId, " pos:", playerEx.GetPos()) } else { if len(params) > 0 { sceneEx.cHintCards = make([]int32, len(params)+1) sceneEx.cHintCards[0] = p.SnId copy(sceneEx.cHintCards[1:], common.Int64ToInt32(params)) opRetCode = tienlen.OpResultCode_OPRC_Hint } } default: opRetCode = tienlen.OpResultCode_OPRC_Error } //next if opRetCode == tienlen.OpResultCode_OPRC_Sucess { this.BroadcastPlayerSToCOp(s, playerEx.SnId, playerEx.GetPos(), opcode, opRetCode, params) delCardNum := 0 for _, hcard := range playerEx.cards { if hcard == rule.InvalideCard { delCardNum++ } } if delCardNum == rule.Hand_CardNum { //牌出完了 sceneEx.TrySmallGameBilled() if !common.InSliceInt32(sceneEx.winSnids, playerEx.SnId) { sceneEx.winSnids = append(sceneEx.winSnids, playerEx.SnId) } if sceneEx.IsTienLenToEnd() { //打到底 if sceneEx.GetGameingPlayerCnt()-1 == len(sceneEx.winSnids) { sceneEx.ChangeSceneState(rule.TienLenSceneStateBilled) } else { playerEx.isDelAll = true sceneEx.BroadcastOpPos() } } else { sceneEx.ChangeSceneState(rule.TienLenSceneStateBilled) } } else { sceneEx.BroadcastOpPos() } } else if opRetCode == tienlen.OpResultCode_OPRC_Error { this.OnPlayerSToCOp(s, p, playerEx.GetPos(), opcode, opRetCode, params) logger.Logger.Trace("ScenePlayerOpStateTienLen,100 OPRC_Error:", params, " opcode:", opcode, " snid:", p.SnId, " pos:", playerEx.GetPos()) } } } return true } // 玩家事件 func (this *ScenePlayerOpStateTienLen) OnPlayerEvent(s *base.Scene, p *base.Player, evtcode int, params []int64) { logger.Logger.Trace("(this *SceneHandCardStateTienLen) OnPlayerEvent, GetSceneId()=", s.GetSceneId(), " player=", p.Name, " evtcode=", evtcode) this.SceneBaseStateTienLen.OnPlayerEvent(s, p, evtcode, params) } func (this *ScenePlayerOpStateTienLen) OnTick(s *base.Scene) { this.SceneBaseStateTienLen.OnTick(s) sceneEx, ok := s.GetExtraData().(*TienLenSceneData) if !ok { return } curOpPos := sceneEx.GetCurOpPos() if curOpPos == rule.InvalidePos { return } playerEx := sceneEx.seats[curOpPos] if playerEx == nil { return } if time.Now().Sub(sceneEx.StateStartTime) < playerEx.GetCurHandLimitTimeOut() { return } if !playerEx.IsRob { logger.Logger.Trace("(this *ScenePlayerOpStateTienLen) OnTick snid: ", playerEx.SnId, " HandLTime:", playerEx.GetCurHandLimitTimeOut(), " thinkCnt:", playerEx.ThinkLongCnt, " flag:", playerEx.GetFlag()) } playerEx.EnterAutoState() //超时后单轮首出玩家出最小的牌,非单轮首出玩家不出牌 if sceneEx.lastOpPos == curOpPos || sceneEx.lastOpPos == rule.InvalidePos { //单轮首出玩家 cpCards := playerEx.cards[:] rule.MinSortCards(cpCards) var delCards []int32 for _, card := range cpCards { if card != rule.InvalideCard { delCards = append(delCards, card) break } } isDel := sceneEx.DelCards(playerEx, delCards) if isDel { sceneEx.DoNext(int32(playerEx.GetPos())) sceneEx.UnmarkPass() this.BroadcastPlayerSToCOp(s, playerEx.SnId, playerEx.GetPos(), int(rule.TienLenPlayerOpPlay), tienlen.OpResultCode_OPRC_Sucess, common.CopySliceInt32ToInt64(delCards)) sceneEx.SetLastOpPos(int32(playerEx.GetPos())) sceneEx.RefreshPlayerHandLimitTimeOut() sceneEx.BroadcastOpPos() } else { sceneEx.DoNext(int32(playerEx.GetPos())) playerEx.isPass = true this.BroadcastPlayerSToCOp(s, playerEx.SnId, playerEx.GetPos(), int(rule.TienLenPlayerOpPass), tienlen.OpResultCode_OPRC_Sucess, []int64{}) sceneEx.RefreshPlayerHandLimitTimeOut() sceneEx.BroadcastOpPos() } sceneEx.isKongBomb = false delAll := 0 for _, card := range playerEx.cards { if card == rule.InvalideCard { delAll++ } } if delAll == rule.Hand_CardNum { // 出完 sceneEx.TrySmallGameBilled() if !common.InSliceInt32(sceneEx.winSnids, playerEx.SnId) { sceneEx.winSnids = append(sceneEx.winSnids, playerEx.SnId) } if sceneEx.IsTienLenToEnd() { //打到底 if sceneEx.GetGameingPlayerCnt()-1 == len(sceneEx.winSnids) { sceneEx.ChangeSceneState(rule.TienLenSceneStateBilled) } else { playerEx.isDelAll = true sceneEx.BroadcastOpPos() } } else { sceneEx.ChangeSceneState(rule.TienLenSceneStateBilled) } } } else { bHandCard := false if len(sceneEx.cHintCards) >= 2 && playerEx.SnId == sceneEx.cHintCards[0] { lastOpPlayer := sceneEx.GetLastOpPlayer() if lastOpPlayer != nil && len(lastOpPlayer.delCards) != 0 { lastDelCards := lastOpPlayer.delCards[len(lastOpPlayer.delCards)-1] hintCards := sceneEx.cHintCards[1:] recmCards := make([]int32, len(hintCards)) copy(recmCards, hintCards) bExistHandCards := true for _, card := range recmCards { isHave := false for _, hcard := range playerEx.cards { //去手牌里找找看有没有 if int32(card) == hcard && hcard != rule.InvalideCard { isHave = true break } } if !isHave { bExistHandCards = false break } } isRule, _ := rule.RulePopEnable(recmCards) if sceneEx.IsTienLenYule() { isRule, _ = rule.RulePopEnable_yl(recmCards) } if bExistHandCards && isRule { // 检查能否压得住 canDel, isBomb, bombScore := rule.CanDel(lastDelCards, recmCards, sceneEx.IsTienLenToEnd()) if sceneEx.IsTienLenYule() { canDel, isBomb, bombScore = rule.CanDel_yl(lastDelCards, recmCards, sceneEx.IsTienLenToEnd()) } if canDel { if isBomb { sceneEx.curBombPos = int32(playerEx.GetPos()) sceneEx.lastBombPos = sceneEx.lastOpPos sceneEx.roundScore += bombScore } else { sceneEx.curBombPos = rule.InvalidePos sceneEx.lastBombPos = rule.InvalidePos sceneEx.roundScore = 0 } isDel := sceneEx.DelCards(playerEx, recmCards) if isDel { nextPos := sceneEx.DoNext(int32(playerEx.GetPos())) if sceneEx.IsTienLenToEnd() && nextPos == rule.InvalidePos { sceneEx.UnmarkPass() sceneEx.DoNext(int32(playerEx.GetPos())) } sceneEx.SetLastOpPos(int32(playerEx.GetPos())) sceneEx.isKongBomb = false sceneEx.RefreshPlayerHandLimitTimeOut() retParams := []int64{} for _, card := range recmCards { retParams = append(retParams, int64(card)) } this.BroadcastPlayerSToCOp(s, playerEx.SnId, playerEx.GetPos(), int(rule.TienLenPlayerOpAutoHandCard), tienlen.OpResultCode_OPRC_Sucess, retParams) delCardNum := 0 for _, hcard := range playerEx.cards { if hcard == rule.InvalideCard { delCardNum++ } } if delCardNum == rule.Hand_CardNum { //牌出完了 sceneEx.TrySmallGameBilled() if !common.InSliceInt32(sceneEx.winSnids, playerEx.SnId) { sceneEx.winSnids = append(sceneEx.winSnids, playerEx.SnId) } if sceneEx.IsTienLenToEnd() { //打到底 if sceneEx.GetGameingPlayerCnt()-1 == len(sceneEx.winSnids) { sceneEx.ChangeSceneState(rule.TienLenSceneStateBilled) } else { playerEx.isDelAll = true sceneEx.BroadcastOpPos() } } else { sceneEx.ChangeSceneState(rule.TienLenSceneStateBilled) } } else { sceneEx.BroadcastOpPos() } bHandCard = true } } } } // 用完后置空 sceneEx.cHintCards = []int32{} } if !bHandCard { sceneEx.card_play_action_seq = append(sceneEx.card_play_action_seq, fmt.Sprintf("%v-过", playerEx.GetPos())) sceneEx.card_play_action_seq_int32 = append(sceneEx.card_play_action_seq_int32, []int32{-1}) nextPos := sceneEx.DoNext(int32(playerEx.GetPos())) if sceneEx.IsTienLenToEnd() && nextPos == rule.InvalidePos { sceneEx.UnmarkPass() nextPos = sceneEx.DoNext(int32(playerEx.GetPos())) sceneEx.SetLastOpPos(int32(nextPos)) } sceneEx.RefreshPlayerHandLimitTimeOut() playerEx.isPass = true if nextPos == sceneEx.lastOpPos { //一轮都不出牌 sceneEx.TrySmallGameBilled() } this.BroadcastPlayerSToCOp(s, playerEx.SnId, playerEx.GetPos(), int(rule.TienLenPlayerOpPass), tienlen.OpResultCode_OPRC_Sucess, []int64{}) sceneEx.BroadcastOpPos() } } sceneEx.StateStartTime = time.Now() } // ///////////////////////////////////////////////////////////////////////////////////////////////////////////// // Billed // ///////////////////////////////////////////////////////////////////////////////////////////////////////////// type SceneBilledStateTienLen struct { SceneBaseStateTienLen } func (this *SceneBilledStateTienLen) GetState() int { return rule.TienLenSceneStateBilled } func (this *SceneBilledStateTienLen) CanChangeTo(s base.SceneState) bool { if s.GetState() == rule.TienLenSceneStateWaitPlayer || s.GetState() == rule.TienLenSceneStateWaitStart { return true } return false } func (this *SceneBilledStateTienLen) OnEnter(s *base.Scene) { this.SceneBaseStateTienLen.OnEnter(s) this.BroadcastRoomState(s, this.GetState()) //在这里执行结算 if sceneEx, ok := s.GetExtraData().(*TienLenSceneData); ok { addItems := func(billData *tienlen.TienLenPlayerGameBilled, sceneTypeScore, vipAdd, vipScore, roleAdd, roleScore, weekCardScore, skinAdd, skinScore int64) { // 场次加成配置 if sceneTypeScore > 0 { billData.AddItems = append(billData.AddItems, &tienlen.AddItem{ ItemType: 1, ItemId: 0, Addition: sceneEx.GetDBGameFree().GetSceneAdd(), Score: sceneTypeScore, }) } // vip加成 if vipScore > 0 { billData.AddItems = append(billData.AddItems, &tienlen.AddItem{ ItemType: 5, ItemId: 0, Addition: int32(vipAdd), Score: vipScore, }) } // 角色加成 if roleScore > 0 { billData.AddItems = append(billData.AddItems, &tienlen.AddItem{ ItemType: 4, ItemId: 0, Addition: int32(roleAdd), Score: roleScore, }) } // 周卡加成 if weekCardScore > 0 { billData.AddItems = append(billData.AddItems, &tienlen.AddItem{ ItemType: 6, ItemId: 0, Addition: 5, Score: weekCardScore, }) } // 皮肤加成 if skinScore > 0 { billData.AddItems = append(billData.AddItems, &tienlen.AddItem{ ItemType: 7, ItemId: 0, Addition: int32(skinAdd), Score: skinScore, }) } } winScore := int64(0) winRankScore := int64(0) pack := &tienlen.SCTienLenGameBilled{} tienlenType := model.TienLenType{ GameId: int(sceneEx.GameId), RoomId: int32(sceneEx.GetSceneId()), RoomType: sceneEx.GetFreeGameSceneType(), NumOfGames: int32(sceneEx.Scene.NumOfGames), BankId: sceneEx.masterSnid, PlayerCount: sceneEx.curGamingPlayerNum, BaseScore: s.GetBaseScore(), TaxRate: s.GetDBGameFree().GetTaxRate(), RoomMode: s.GetSceneMode(), PlayerPool: make(map[int]int), } for _, v := range sceneEx.seats { if v == nil || !v.IsGameing() { continue } tienlenType.PlayerPool[int(v.SnId)] = v.playerPool } nGamingPlayerCount := sceneEx.GetGameingPlayerCnt() if len(sceneEx.tianHuSnids) == nGamingPlayerCount { //和 for i := 0; i < sceneEx.GetPlayerNum(); i++ { playerEx := sceneEx.seats[i] if playerEx == nil { continue } if !playerEx.IsGameing() { continue } billData := &tienlen.TienLenPlayerGameBilled{ SnId: proto.Int32(playerEx.SnId), IsWin: proto.Int32(0), WinCoin: proto.Int64(0), GameCoin: proto.Int64(playerEx.GetCoin()), RankScore: playerEx.GetRankScore(sceneEx.GetDBGameFree().GetRankType()), TianHu: playerEx.tianHu, } playerEx.CurIsWin = int64(0) tienlenPerson := model.TienLenPerson{ UserId: playerEx.SnId, UserIcon: playerEx.Head, Platform: playerEx.Platform, Channel: playerEx.Channel, Promoter: playerEx.BeUnderAgentCode, PackageTag: playerEx.PackageID, InviterId: playerEx.InviterId, WBLevel: playerEx.WBLevel, IsRob: playerEx.IsRob, IsFirst: sceneEx.IsPlayerFirst(sceneEx.GetPlayer(playerEx.SnId)), IsLeave: false, IsWin: 0, GainCoin: 0, BombCoin: 0, BillCoin: 0, GainTaxCoin: 0, BombTaxCoin: 0, BillTaxCoin: 0, Seat: playerEx.GetPos(), IsTianHu: sceneEx.IsTianhuPlayer(playerEx.SnId), TestLog: playerEx.TestLog, CardsScore: playerEx.cardScore, } //排下序,正常应该客户端排序 cards := make([]int32, rule.HandCardNum) copy(cards, playerEx.cards[:]) sort.Slice(cards, func(i, j int) bool { v_i := rule.Value(int32(cards[i])) v_j := rule.Value(int32(cards[j])) c_i := rule.Color(int32(cards[i])) c_j := rule.Color(int32(cards[j])) if v_i > v_j { return false } else if v_i == v_j { return c_i < c_j } return true }) for _, card := range cards { if card != rule.InvalideCard { billData.Cards = append(billData.Cards, card) tienlenPerson.CardInfoEnd = append(tienlenPerson.CardInfoEnd, card) } } pack.Datas = append(pack.Datas, billData) sceneEx.TryBillExGameDrop(playerEx.Player) //和 tienlenType.PlayerData = append(tienlenType.PlayerData, tienlenPerson) } } else { //输赢局 if sceneEx.IsTienLenToEnd() && len(sceneEx.tianHuSnids) == 0 { lastSnid := int32(0) playerNum := 0 for _, p := range sceneEx.players { if p != nil && p.IsGameing() { playerNum++ if !common.InSliceInt32(sceneEx.winSnids, p.SnId) { lastSnid = p.SnId } } } if lastSnid == 0 { logger.Logger.Error("TienLenToEndGameBilled Error: lastSnid == 0") return } if playerNum-1 != len(sceneEx.winSnids) { logger.Logger.Error("TienLenToEndGameBilled Error: playerNum: ", playerNum, " this.winSnids: ", sceneEx.winSnids) return } // 没出完牌的输家 losePlayerScore := int64(0) loseRankScore := int64(0) losePlayer := sceneEx.players[lastSnid] if losePlayer != nil { var rankScore int64 // 排位积分 var sceneTypeScore int64 // 场次额外积分 var vipScore int64 // vip加成 var roleScore int64 // 角色加成 var weekCardScore int64 // 周卡加成 var skinScore int64 // 皮肤技能加成 var roleAdd, skinAdd int32 var otherScore int64 // 额外总加分 oldRankScore := losePlayer.GetRankScore(sceneEx.GetDBGameFree().GetRankType()) playerLoseScore := rule.GetLoseScore(losePlayer.cards, true) rankScore = int64(playerLoseScore) + 100 score := int64(float64(s.GetBaseScore()) * (float64(playerLoseScore) + 100.0) / 100.0) //手牌输分和基础 gainScore := score if sceneEx.IsTienLenYule() && sceneEx.bombToEnd > 0 { //娱乐版空放炸弹底分翻倍 logger.Logger.Trace("TienLenYule,bombToEnd: ", sceneEx.bombToEnd, " SnId: ", losePlayer.SnId) for bomb := 0; bomb < sceneEx.bombToEnd; bomb++ { gainScore *= 2 rankScore *= 2 } } losePlayerCoin := losePlayer.GetCoin() if !sceneEx.IsMatchScene() && losePlayerCoin < gainScore { gainScore = losePlayerCoin } losePlayerScore = gainScore if sceneEx.IsMatchScene() || sceneEx.IsCustom() { //比赛场是积分,不应该增加账变 losePlayer.AddCoinNoLog(int64(-gainScore), 0) } else { losePlayer.AddCoin(int64(-gainScore), common.GainWay_CoinSceneLost, 0, "system", s.GetSceneName()) } if sceneEx.IsRankMatch() { rankScore = int64(float64(rankScore) / 100.0 * float64(-rule.RankBaseScoreToEnd)) loseRankScore = -rankScore rankScore += losePlayer.bombRankScore if rankScore > 0 { // 场次加成分 sceneTypeScore = int64(math.Ceil(float64(rankScore) * float64(sceneEx.GetDBGameFree().GetSceneAdd()) / 100.0)) // 场次加成 // vip加成分 vipScore = int64(math.Ceil(float64(rankScore) * float64(losePlayer.VipExtra) / 100.0)) // 角色加成分 _, roleAdd = srvdata.RolePetMgrSington.GetRoleAdd(&losePlayer.PlayerData, common.RoleAddRankScore) roleScore = int64(math.Ceil(float64(rankScore) * float64(roleAdd) / 100.0)) //周卡加成 if losePlayer.GetWeekCardPrivilege(2) { weekCardScore = int64(math.Ceil(float64(rankScore) * float64(5) / 100.0)) } // 皮肤技能加成 skinAdd = losePlayer.GetSkillAdd(common.SkillIdRankScore) if skinAdd > 0 { skinScore = int64(math.Ceil(float64(rankScore) * float64(skinAdd) / 100.0)) } } otherScore = sceneTypeScore + vipScore + roleScore + weekCardScore + skinScore losePlayer.AddRankScore(sceneEx.GetDBGameFree().GetRankType(), rankScore+otherScore) // 炸弹分一起算 } losePlayer.winCoin -= gainScore billData := &tienlen.TienLenPlayerGameBilled{ SnId: proto.Int32(losePlayer.SnId), IsWin: proto.Int32(2), WinCoin: proto.Int64(gainScore), GameCoin: proto.Int64(losePlayer.GetCoin()), RankScore: losePlayer.GetRankScore(sceneEx.GetDBGameFree().GetRankType()), AddScore: otherScore, TianHu: losePlayer.tianHu, } billData.WinRankScore = billData.RankScore - oldRankScore if otherScore > 0 { addItems(billData, sceneTypeScore, int64(losePlayer.VipExtra), vipScore, int64(roleAdd), roleScore, weekCardScore, int64(skinAdd), skinScore) } isWin := int32(0) billCoin := losePlayer.bombScore - gainScore if billCoin > 0 { isWin = 1 } else if billCoin < 0 { isWin = -1 } losePlayer.CurIsWin = int64(isWin) tienlenPerson := model.TienLenPerson{ UserId: losePlayer.SnId, UserIcon: losePlayer.Head, Platform: losePlayer.Platform, Channel: losePlayer.Channel, Promoter: losePlayer.BeUnderAgentCode, PackageTag: losePlayer.PackageID, InviterId: losePlayer.InviterId, WBLevel: losePlayer.WBLevel, IsRob: losePlayer.IsRob, IsFirst: sceneEx.IsPlayerFirst(sceneEx.GetPlayer(losePlayer.SnId)), IsLeave: false, IsWin: isWin, GainCoin: -gainScore, BombCoin: losePlayer.bombScore, BillCoin: billCoin, GainTaxCoin: 0, BombTaxCoin: losePlayer.bombTaxScore, BillTaxCoin: losePlayer.bombTaxScore, Seat: losePlayer.GetPos(), IsTianHu: false, TestLog: losePlayer.TestLog, WinRankScore: rankScore + otherScore, RankScore: losePlayer.GetRankScore(sceneEx.GetDBGameFree().GetRankType()), AddScore: otherScore, BombRankScore: losePlayer.bombRankScore, CardsScore: losePlayer.cardScore, } tienlenPerson.DelOrderCards = make(map[int][]int32, len(sceneEx.delOrders)) for i2, orderSnid := range sceneEx.delOrders { if orderSnid == losePlayer.SnId { tienlenPerson.DelOrderCards[i2] = sceneEx.delCards[i2] } } //排下序,正常应该客户端排序 cards := make([]int32, rule.HandCardNum) copy(cards, losePlayer.cards[:]) sort.Slice(cards, func(i, j int) bool { v_i := rule.Value(int32(cards[i])) v_j := rule.Value(int32(cards[j])) c_i := rule.Color(int32(cards[i])) c_j := rule.Color(int32(cards[j])) if v_i > v_j { return false } else if v_i == v_j { return c_i < c_j } return true }) for _, card := range cards { if card != rule.InvalideCard { billData.Cards = append(billData.Cards, card) tienlenPerson.CardInfoEnd = append(tienlenPerson.CardInfoEnd, card) } } pack.Datas = append(pack.Datas, billData) sceneEx.TryBillExGameDrop(losePlayer.Player) //输家 tienlenType.PlayerData = append(tienlenType.PlayerData, tienlenPerson) lastWinPlayerScore := int64(0) lastWinPlayerRankScore := int64(0) if playerNum == 3 || playerNum == 4 { // 最后一位出完牌的输家 lastWinPlayer := sceneEx.players[sceneEx.winSnids[len(sceneEx.winSnids)-1]] if lastWinPlayer != nil { var rankScore int64 // 排位积分 var sceneTypeScore int64 // 场次额外积分 var vipScore int64 // vip加成 var roleScore int64 // 角色加成 var weekCardScore int64 // 周卡加成 var skinScore int64 // 皮肤技能加成 var roleAdd, skinAdd int32 var otherScore int64 // 额外总加分 oldRankScore := lastWinPlayer.GetRankScore(sceneEx.GetDBGameFree().GetRankType()) lastWinScore := rule.GetLoseScore(lastWinPlayer.cards, true) rankScore = int64(lastWinScore) + 50 lastWinscore := int64(float64(s.GetBaseScore()) * float64(int64(lastWinScore)+50) / 100.0) //手牌输分和基础 astWinGainScore := lastWinscore if sceneEx.IsTienLenYule() && sceneEx.bombToEnd > 0 { //娱乐版空放炸弹底分翻倍 logger.Logger.Trace("TienLenYule,bombToEnd: ", sceneEx.bombToEnd, " SnId: ", lastWinPlayer.SnId) for bomb := 0; bomb < sceneEx.bombToEnd; bomb++ { astWinGainScore *= 2 rankScore *= 2 } } lastWinPlayerCoin := lastWinPlayer.GetCoin() if !sceneEx.IsMatchScene() && lastWinPlayerCoin < astWinGainScore { astWinGainScore = lastWinPlayerCoin } lastWinPlayerScore = astWinGainScore if sceneEx.IsMatchScene() || sceneEx.IsCustom() { lastWinPlayer.AddCoinNoLog(int64(-astWinGainScore), 0) } else { lastWinPlayer.AddCoin(int64(-astWinGainScore), common.GainWay_CoinSceneLost, 0, "system", s.GetSceneName()) } if sceneEx.IsRankMatch() { rankScore = int64(float64(rankScore) / 100.0 * float64(-rule.RankBaseScoreToEnd)) lastWinPlayerRankScore = -rankScore rankScore += lastWinPlayer.bombRankScore if rankScore > 0 { // 场次加成分 sceneTypeScore = int64(math.Ceil(float64(rankScore) * float64(sceneEx.GetDBGameFree().GetSceneAdd()) / 100.0)) // 场次加成 // vip加成分 vipScore = int64(math.Ceil(float64(rankScore) * float64(lastWinPlayer.VipExtra) / 100.0)) // 角色加成分 _, roleAdd = srvdata.RolePetMgrSington.GetRoleAdd(&lastWinPlayer.PlayerData, common.RoleAddRankScore) roleScore = int64(math.Ceil(float64(rankScore) * float64(roleAdd) / 100.0)) //周卡加成 if lastWinPlayer.GetWeekCardPrivilege(2) { weekCardScore = int64(math.Ceil(float64(rankScore) * float64(5) / 100.0)) } // 皮肤技能加成 skinAdd = lastWinPlayer.GetSkillAdd(common.SkillIdRankScore) if skinAdd > 0 { skinScore = int64(math.Ceil(float64(rankScore) * float64(skinAdd) / 100.0)) } } otherScore = sceneTypeScore + vipScore + roleScore + weekCardScore + skinScore lastWinPlayer.AddRankScore(sceneEx.GetDBGameFree().GetRankType(), rankScore+otherScore) // 炸弹分一起算 } lastWinPlayer.winCoin -= astWinGainScore billData := &tienlen.TienLenPlayerGameBilled{ SnId: proto.Int32(lastWinPlayer.SnId), IsWin: proto.Int32(2), WinCoin: proto.Int64(astWinGainScore), GameCoin: proto.Int64(lastWinPlayer.GetCoin()), RankScore: lastWinPlayer.GetRankScore(sceneEx.GetDBGameFree().GetRankType()), AddScore: otherScore, TianHu: lastWinPlayer.tianHu, } billData.WinRankScore = billData.RankScore - oldRankScore if otherScore > 0 { addItems(billData, sceneTypeScore, int64(lastWinPlayer.VipExtra), vipScore, int64(roleAdd), roleScore, weekCardScore, int64(skinAdd), skinScore) } isWin := int32(0) billCoin := lastWinPlayer.bombScore - astWinGainScore if billCoin > 0 { isWin = 1 } else if billCoin < 0 { isWin = -1 } lastWinPlayer.CurIsWin = int64(isWin) tienlenPerson := model.TienLenPerson{ UserId: lastWinPlayer.SnId, UserIcon: lastWinPlayer.Head, Platform: lastWinPlayer.Platform, Channel: lastWinPlayer.Channel, Promoter: lastWinPlayer.BeUnderAgentCode, PackageTag: lastWinPlayer.PackageID, InviterId: lastWinPlayer.InviterId, WBLevel: lastWinPlayer.WBLevel, IsRob: lastWinPlayer.IsRob, IsFirst: sceneEx.IsPlayerFirst(sceneEx.GetPlayer(lastWinPlayer.SnId)), IsLeave: false, IsWin: isWin, GainCoin: -astWinGainScore, BombCoin: lastWinPlayer.bombScore, BillCoin: billCoin, GainTaxCoin: 0, BombTaxCoin: lastWinPlayer.bombTaxScore, BillTaxCoin: lastWinPlayer.bombTaxScore, Seat: lastWinPlayer.GetPos(), IsTianHu: false, TestLog: lastWinPlayer.TestLog, WinRankScore: rankScore + otherScore, RankScore: lastWinPlayer.GetRankScore(sceneEx.GetDBGameFree().GetRankType()), AddScore: otherScore, BombRankScore: lastWinPlayer.bombRankScore, CardsScore: lastWinPlayer.cardScore, } tienlenPerson.DelOrderCards = make(map[int][]int32, len(sceneEx.delOrders)) for i2, orderSnid := range sceneEx.delOrders { if orderSnid == lastWinPlayer.SnId { tienlenPerson.DelOrderCards[i2] = sceneEx.delCards[i2] } } pack.Datas = append(pack.Datas, billData) sceneEx.TryBillExGameDrop(lastWinPlayer.Player) //输家 tienlenType.PlayerData = append(tienlenType.PlayerData, tienlenPerson) } } //first playerEx := sceneEx.players[sceneEx.winSnids[0]] if playerEx != nil { var rankScore int64 // 排位积分 var sceneTypeScore int64 // 场次额外积分 var vipScore int64 // vip加成 var roleScore int64 // 角色加成 var weekCardScore int64 // 周卡加成 var skinScore int64 // 皮肤技能加成 var roleAdd, skinAdd int32 var otherScore int64 // 额外总加分 oldRankScore := playerEx.GetRankScore(sceneEx.GetDBGameFree().GetRankType()) rankScore = loseRankScore taxRate := sceneEx.GetDBGameFree().GetTaxRate() //万分比 gainScore := int64(float64(losePlayerScore) * float64(10000-taxRate) / 10000.0) //税后 gainTaxScore := losePlayerScore - gainScore // 税收 if playerNum == 3 { gainScore = int64(float64(losePlayerScore+lastWinPlayerScore) * float64(10000-taxRate) / 10000.0) //税后 gainTaxScore = losePlayerScore + lastWinPlayerScore - gainScore rankScore = loseRankScore + lastWinPlayerRankScore } if sceneEx.IsMatchScene() || sceneEx.IsCustom() { playerEx.AddCoinNoLog(int64(gainScore), 0) } else { playerEx.AddCoin(gainScore, common.GainWay_CoinSceneWin, 0, "system", s.GetSceneName()) } if sceneEx.IsRankMatch() { rankScore += playerEx.bombRankScore if rankScore > 0 { // 场次加成分 sceneTypeScore = int64(math.Ceil(float64(rankScore) * float64(sceneEx.GetDBGameFree().GetSceneAdd()) / 100.0)) // 场次加成 // vip加成分 vipScore = int64(math.Ceil(float64(rankScore) * float64(playerEx.VipExtra) / 100.0)) // 角色加成分 _, roleAdd = srvdata.RolePetMgrSington.GetRoleAdd(&playerEx.PlayerData, common.RoleAddRankScore) roleScore = int64(math.Ceil(float64(rankScore) * float64(roleAdd) / 100.0)) //周卡加成 if playerEx.GetWeekCardPrivilege(2) { weekCardScore = int64(math.Ceil(float64(rankScore) * float64(5) / 100.0)) } // 皮肤技能加成 skinAdd = playerEx.GetSkillAdd(common.SkillIdRankScore) if skinAdd > 0 { skinScore = int64(math.Ceil(float64(rankScore) * float64(skinAdd) / 100.0)) } } otherScore = sceneTypeScore + vipScore + roleScore + weekCardScore + skinScore playerEx.AddRankScore(sceneEx.GetDBGameFree().GetRankType(), rankScore+otherScore) // 炸弹分一起算 } playerEx.winCoin += gainScore billData := &tienlen.TienLenPlayerGameBilled{ SnId: proto.Int32(playerEx.SnId), IsWin: proto.Int32(1), WinCoin: proto.Int64(gainScore), GameCoin: proto.Int64(playerEx.GetCoin()), RankScore: playerEx.GetRankScore(sceneEx.GetDBGameFree().GetRankType()), AddScore: otherScore, TianHu: playerEx.tianHu, } billData.WinRankScore = billData.RankScore - oldRankScore if otherScore > 0 { addItems(billData, sceneTypeScore, int64(playerEx.VipExtra), vipScore, int64(roleAdd), roleScore, weekCardScore, int64(skinAdd), skinScore) } isWin := int32(0) billCoin := playerEx.bombScore + gainScore if billCoin > 0 { isWin = 1 } else if billCoin < 0 { isWin = -1 } playerEx.CurIsWin = int64(isWin) tienlenPerson := model.TienLenPerson{ UserId: playerEx.SnId, UserIcon: playerEx.Head, Platform: playerEx.Platform, Channel: playerEx.Channel, Promoter: playerEx.BeUnderAgentCode, PackageTag: playerEx.PackageID, InviterId: playerEx.InviterId, WBLevel: playerEx.WBLevel, IsRob: playerEx.IsRob, IsFirst: sceneEx.IsPlayerFirst(sceneEx.GetPlayer(playerEx.SnId)), IsLeave: false, IsWin: isWin, GainCoin: gainScore, BombCoin: playerEx.bombScore, BillCoin: billCoin, GainTaxCoin: gainTaxScore, BombTaxCoin: playerEx.bombTaxScore, BillTaxCoin: playerEx.bombTaxScore + gainTaxScore, Seat: playerEx.GetPos(), IsTianHu: sceneEx.IsTianhuPlayer(playerEx.SnId), TestLog: playerEx.TestLog, WinRankScore: rankScore + otherScore, RankScore: playerEx.GetRankScore(sceneEx.GetDBGameFree().GetRankType()), AddScore: otherScore, BombRankScore: playerEx.bombRankScore, CardsScore: playerEx.cardScore, } tienlenPerson.DelOrderCards = make(map[int][]int32, len(sceneEx.delOrders)) for i2, orderSnid := range sceneEx.delOrders { if orderSnid == playerEx.SnId { tienlenPerson.DelOrderCards[i2] = sceneEx.delCards[i2] } } pack.Datas = append(pack.Datas, billData) sceneEx.TryBillExGameDrop(playerEx.Player) //赢家 tienlenType.PlayerData = append(tienlenType.PlayerData, tienlenPerson) } //second if playerNum == 4 { playerEx = sceneEx.players[sceneEx.winSnids[1]] if playerEx != nil { var rankScore int64 // 排位积分 var sceneTypeScore int64 // 场次额外积分 var vipScore int64 // vip加成 var roleScore int64 // 角色加成 var weekCardScore int64 // 周卡加成 var skinScore int64 // 皮肤技能加成 var roleAdd, skinAdd int32 var otherScore int64 // 额外总加分 oldRankScore := playerEx.GetRankScore(sceneEx.GetDBGameFree().GetRankType()) rankScore = lastWinPlayerRankScore taxRate := sceneEx.GetDBGameFree().GetTaxRate() //万分比 gainScore := int64(float64(lastWinPlayerScore) * float64(10000-taxRate) / 10000.0) //税后 gainTaxScore := lastWinPlayerScore - gainScore if sceneEx.IsMatchScene() || sceneEx.IsCustom() { playerEx.AddCoinNoLog(int64(gainScore), 0) } else { playerEx.AddCoin(gainScore, common.GainWay_CoinSceneWin, 0, "system", s.GetSceneName()) } if sceneEx.IsRankMatch() { rankScore += playerEx.bombRankScore if rankScore > 0 { // 场次加成分 sceneTypeScore = int64(math.Ceil(float64(rankScore) * float64(sceneEx.GetDBGameFree().GetSceneAdd()) / 100.0)) // 场次加成 // vip加成分 vipScore = int64(math.Ceil(float64(rankScore) * float64(playerEx.VipExtra) / 100.0)) // 角色加成分 _, roleAdd = srvdata.RolePetMgrSington.GetRoleAdd(&playerEx.PlayerData, common.RoleAddRankScore) roleScore = int64(math.Ceil(float64(rankScore) * float64(roleAdd) / 100.0)) //周卡加成 if playerEx.GetWeekCardPrivilege(2) { weekCardScore = int64(math.Ceil(float64(rankScore) * float64(5) / 100.0)) } // 皮肤技能加成 skinAdd = playerEx.GetSkillAdd(common.SkillIdRankScore) if skinAdd > 0 { skinScore = int64(math.Ceil(float64(rankScore) * float64(skinAdd) / 100.0)) } } otherScore = sceneTypeScore + vipScore + roleScore + weekCardScore + skinScore playerEx.AddRankScore(sceneEx.GetDBGameFree().GetRankType(), rankScore+otherScore) // 炸弹分一起算 } playerEx.winCoin += gainScore billData := &tienlen.TienLenPlayerGameBilled{ SnId: proto.Int32(playerEx.SnId), IsWin: proto.Int32(1), WinCoin: proto.Int64(gainScore), GameCoin: proto.Int64(playerEx.GetCoin()), RankScore: playerEx.GetRankScore(sceneEx.GetDBGameFree().GetRankType()), AddScore: otherScore, TianHu: playerEx.tianHu, } billData.WinRankScore = billData.RankScore - oldRankScore if otherScore > 0 { addItems(billData, sceneTypeScore, int64(playerEx.VipExtra), vipScore, int64(roleAdd), roleScore, weekCardScore, int64(skinAdd), skinScore) } isWin := int32(0) billCoin := playerEx.bombScore + gainScore if billCoin > 0 { isWin = 1 } else if billCoin < 0 { isWin = -1 } playerEx.CurIsWin = int64(isWin) tienlenPerson := model.TienLenPerson{ UserId: playerEx.SnId, UserIcon: playerEx.Head, Platform: playerEx.Platform, Channel: playerEx.Channel, Promoter: playerEx.BeUnderAgentCode, PackageTag: playerEx.PackageID, InviterId: playerEx.InviterId, WBLevel: playerEx.WBLevel, IsRob: playerEx.IsRob, IsFirst: sceneEx.IsPlayerFirst(sceneEx.GetPlayer(playerEx.SnId)), IsLeave: false, IsWin: isWin, GainCoin: gainScore, BombCoin: playerEx.bombScore, BillCoin: billCoin, GainTaxCoin: gainTaxScore, BombTaxCoin: playerEx.bombTaxScore, BillTaxCoin: playerEx.bombTaxScore + gainTaxScore, Seat: playerEx.GetPos(), IsTianHu: sceneEx.IsTianhuPlayer(playerEx.SnId), TestLog: playerEx.TestLog, WinRankScore: rankScore + otherScore, RankScore: playerEx.GetRankScore(sceneEx.GetDBGameFree().GetRankType()), AddScore: otherScore, BombRankScore: playerEx.bombRankScore, CardsScore: playerEx.cardScore, } tienlenPerson.DelOrderCards = make(map[int][]int32, len(sceneEx.delOrders)) for i2, orderSnid := range sceneEx.delOrders { if orderSnid == playerEx.SnId { tienlenPerson.DelOrderCards[i2] = sceneEx.delCards[i2] } } pack.Datas = append(pack.Datas, billData) sceneEx.TryBillExGameDrop(playerEx.Player) //赢家 tienlenType.PlayerData = append(tienlenType.PlayerData, tienlenPerson) } } } } else { // 输家 for i := 0; i < sceneEx.GetPlayerNum(); i++ { var rankScore int64 // 排位积分 var sceneTypeScore int64 // 场次额外积分 var vipScore int64 // vip加成 var roleScore int64 // 角色加成 var weekCardScore int64 // 周卡加成 var skinScore int64 // 皮肤技能加成 var roleAdd, skinAdd int32 var otherScore int64 // 额外总加分 playerEx := sceneEx.seats[i] if playerEx == nil { continue } oldRankScore := playerEx.GetRankScore(sceneEx.GetDBGameFree().GetRankType()) if !playerEx.IsGameing() { continue } if sceneEx.IsTianhuPlayer(playerEx.SnId) { continue } if sceneEx.IsWinPlayer(playerEx.SnId) && !sceneEx.IsTienLenToEnd() { continue } logger.Logger.Trace("SceneBilledStateTienLe,losePos: ", i, " SnId: ", playerEx.SnId, " BaseScore: ", s.GetBaseScore()) playerLoseScore := rule.GetLoseScore(playerEx.cards, sceneEx.IsTienLenToEnd()) score := int64(s.GetBaseScore()) * int64(playerLoseScore) rankScore = int64(playerLoseScore) gainScore := int64(0) if len(sceneEx.tianHuSnids) != 0 { //天胡结算翻倍 gainScore = int64(score) * int64(len(sceneEx.tianHuSnids)) * 2 rankScore = int64(playerLoseScore) * int64(len(sceneEx.tianHuSnids)) * 2 if sceneEx.IsTienLenToEnd() { //打到底天胡结算加上2倍底注(不是翻倍) gainScore = int64(float64(score)/100.0 + float64(s.GetBaseScore()*2)) rankScore = int64(playerLoseScore) + 200 } } else { //正常结算 gainScore = int64(score) if sceneEx.IsTienLenYule() && sceneEx.bombToEnd > 0 { //娱乐版空放炸弹底分翻倍 logger.Logger.Trace("TienLenYule,bombToEnd: ", sceneEx.bombToEnd, " SnId: ", playerEx.SnId) for bomb := 0; bomb < sceneEx.bombToEnd; bomb++ { gainScore *= 2 rankScore *= 2 } } } losePlayerCoin := playerEx.GetCoin() if !sceneEx.IsMatchScene() && losePlayerCoin < gainScore { gainScore = losePlayerCoin } winScore += gainScore if sceneEx.IsMatchScene() || sceneEx.IsCustom() { playerEx.AddCoinNoLog(int64(-gainScore), 0) } else { playerEx.AddCoin(int64(-gainScore), common.GainWay_CoinSceneLost, 0, "system", s.GetSceneName()) } if sceneEx.IsRankMatch() { // 排位积分 if sceneEx.IsTienLenToEnd() { rankScore = int64(float64(rankScore) / 100.0 * float64(-rule.RankBaseScoreToEnd)) } else { rankScore *= -rule.RankBaseScore } winRankScore += -rankScore // 不含炸弹分 rankScore += playerEx.bombRankScore if rankScore > 0 { // 场次加成分 sceneTypeScore = int64(math.Ceil(float64(rankScore) * float64(sceneEx.GetDBGameFree().GetSceneAdd()) / 100)) // 场次加成 // vip加成分 vipScore = int64(math.Ceil(float64(rankScore) * float64(playerEx.VipExtra) / 100.0)) // 角色加成分 _, roleAdd = srvdata.RolePetMgrSington.GetRoleAdd(&playerEx.PlayerData, common.RoleAddRankScore) roleScore = int64(math.Ceil(float64(rankScore) * float64(roleAdd) / 100.0)) //周卡加成 if playerEx.GetWeekCardPrivilege(2) { weekCardScore = int64(math.Ceil(float64(rankScore) * float64(5) / 100.0)) } // 皮肤技能加成 skinAdd = playerEx.GetSkillAdd(common.SkillIdRankScore) if skinAdd > 0 { skinScore = int64(math.Ceil(float64(rankScore) * float64(skinAdd) / 100.0)) } } otherScore = sceneTypeScore + vipScore + roleScore + weekCardScore + skinScore playerEx.AddRankScore(sceneEx.GetDBGameFree().GetRankType(), rankScore+otherScore) // 炸弹分一起算 } playerEx.winCoin -= gainScore billData := &tienlen.TienLenPlayerGameBilled{ SnId: proto.Int32(playerEx.SnId), IsWin: proto.Int32(2), WinCoin: proto.Int64(gainScore), GameCoin: proto.Int64(playerEx.GetCoin()), //WinRankScore: -rankScore, RankScore: playerEx.GetRankScore(sceneEx.GetDBGameFree().GetRankType()), AddScore: otherScore, TianHu: playerEx.tianHu, } billData.WinRankScore = billData.RankScore - oldRankScore if otherScore > 0 { addItems(billData, sceneTypeScore, int64(playerEx.VipExtra), vipScore, int64(roleAdd), roleScore, weekCardScore, int64(skinAdd), skinScore) } isWin := int32(0) billCoin := playerEx.bombScore - gainScore if billCoin > 0 { isWin = 1 } else if billCoin < 0 { isWin = -1 } playerEx.CurIsWin = int64(isWin) tienlenPerson := model.TienLenPerson{ UserId: playerEx.SnId, UserIcon: playerEx.Head, Platform: playerEx.Platform, Channel: playerEx.Channel, Promoter: playerEx.BeUnderAgentCode, PackageTag: playerEx.PackageID, InviterId: playerEx.InviterId, WBLevel: playerEx.WBLevel, IsRob: playerEx.IsRob, IsFirst: sceneEx.IsPlayerFirst(sceneEx.GetPlayer(playerEx.SnId)), IsLeave: false, IsWin: isWin, GainCoin: -gainScore, BombCoin: playerEx.bombScore, BillCoin: billCoin, GainTaxCoin: 0, BombTaxCoin: playerEx.bombTaxScore, BillTaxCoin: playerEx.bombTaxScore, Seat: playerEx.GetPos(), IsTianHu: false, TestLog: playerEx.TestLog, WinRankScore: rankScore + otherScore, RankScore: playerEx.GetRankScore(sceneEx.GetDBGameFree().GetRankType()), AddScore: otherScore, BombRankScore: playerEx.bombRankScore, CardsScore: playerEx.cardScore, } tienlenPerson.DelOrderCards = make(map[int][]int32, len(sceneEx.delOrders)) for i2, orderSnid := range sceneEx.delOrders { if orderSnid == playerEx.SnId { tienlenPerson.DelOrderCards[i2] = sceneEx.delCards[i2] } } //排下序,正常应该客户端排序 cards := make([]int32, rule.HandCardNum) copy(cards, playerEx.cards[:]) sort.Slice(cards, func(i, j int) bool { v_i := rule.Value(int32(cards[i])) v_j := rule.Value(int32(cards[j])) c_i := rule.Color(int32(cards[i])) c_j := rule.Color(int32(cards[j])) if v_i > v_j { return false } else if v_i == v_j { return c_i < c_j } return true }) for _, card := range cards { if card != rule.InvalideCard { billData.Cards = append(billData.Cards, card) tienlenPerson.CardInfoEnd = append(tienlenPerson.CardInfoEnd, card) } } pack.Datas = append(pack.Datas, billData) sceneEx.TryBillExGameDrop(playerEx.Player) //输家 tienlenType.PlayerData = append(tienlenType.PlayerData, tienlenPerson) } logger.Logger.Trace("SceneBilledStateTienLe, winSnids: ", sceneEx.winSnids, " winScore: ", winScore) //赢家 if len(sceneEx.tianHuSnids) != 0 { winScore = winScore / int64(len(sceneEx.tianHuSnids)) winRankScore = winRankScore / int64(len(sceneEx.tianHuSnids)) } for _, winSnid := range sceneEx.winSnids { var rankScore = winRankScore // 排位积分 var sceneTypeScore int64 // 场次额外积分 var vipScore int64 // vip加成 var roleScore int64 // 角色加成 var weekCardScore int64 // 周卡加成 var skinScore int64 // 皮肤技能加成 var roleAdd, skinAdd int32 var otherScore int64 // 额外总加分 playerEx := sceneEx.players[winSnid] if playerEx != nil { taxRate := sceneEx.GetDBGameFree().GetTaxRate() //万分比 gainScore := int64(float64(winScore) * float64(10000-taxRate) / 10000.0) //税后 gainTaxScore := winScore - gainScore if sceneEx.IsMatchScene() || sceneEx.IsCustom() { playerEx.AddCoinNoLog(int64(gainScore), 0) } else { playerEx.AddCoin(gainScore, common.GainWay_CoinSceneWin, 0, "system", s.GetSceneName()) } if sceneEx.IsRankMatch() { // 排位积分 rankScore += playerEx.bombRankScore // 场次加成分 sceneTypeScore = int64(math.Ceil(float64(rankScore) * float64(sceneEx.GetDBGameFree().GetSceneAdd()) / 100.0)) // 场次加成 // vip加成分 vipScore = int64(math.Ceil(float64(rankScore) * float64(playerEx.VipExtra) / 100.0)) // 角色加成分 _, roleAdd = srvdata.RolePetMgrSington.GetRoleAdd(&playerEx.PlayerData, common.RoleAddRankScore) roleScore = int64(math.Ceil(float64(rankScore) * float64(roleAdd) / 100.0)) //周卡加成 if playerEx.GetWeekCardPrivilege(2) { weekCardScore = int64(math.Ceil(float64(rankScore) * float64(5) / 100.0)) } // 皮肤技能加成 skinAdd = playerEx.GetSkillAdd(common.SkillIdRankScore) if skinAdd > 0 { skinScore = int64(math.Ceil(float64(rankScore) * float64(skinAdd) / 100.0)) } otherScore = sceneTypeScore + vipScore + roleScore + weekCardScore + skinScore playerEx.AddRankScore(sceneEx.GetDBGameFree().GetRankType(), rankScore+otherScore) } playerEx.winCoin += gainScore billData := &tienlen.TienLenPlayerGameBilled{ SnId: proto.Int32(playerEx.SnId), IsWin: proto.Int32(1), WinCoin: proto.Int64(gainScore), GameCoin: proto.Int64(playerEx.GetCoin()), WinRankScore: rankScore + otherScore, RankScore: playerEx.GetRankScore(sceneEx.GetDBGameFree().GetRankType()), AddScore: otherScore, TianHu: playerEx.tianHu, } if otherScore > 0 { addItems(billData, sceneTypeScore, int64(playerEx.VipExtra), vipScore, int64(roleAdd), roleScore, weekCardScore, int64(skinAdd), skinScore) } isWin := int32(0) billCoin := playerEx.bombScore + gainScore if billCoin > 0 { isWin = 1 } else if billCoin < 0 { isWin = -1 } playerEx.CurIsWin = int64(isWin) tienlenPerson := model.TienLenPerson{ UserId: playerEx.SnId, UserIcon: playerEx.Head, Platform: playerEx.Platform, Channel: playerEx.Channel, Promoter: playerEx.BeUnderAgentCode, PackageTag: playerEx.PackageID, InviterId: playerEx.InviterId, WBLevel: playerEx.WBLevel, IsRob: playerEx.IsRob, IsFirst: sceneEx.IsPlayerFirst(sceneEx.GetPlayer(playerEx.SnId)), IsLeave: false, IsWin: isWin, GainCoin: gainScore, BombCoin: playerEx.bombScore, BillCoin: billCoin, GainTaxCoin: gainTaxScore, BombTaxCoin: playerEx.bombTaxScore, BillTaxCoin: playerEx.bombTaxScore + gainTaxScore, Seat: playerEx.GetPos(), IsTianHu: sceneEx.IsTianhuPlayer(playerEx.SnId), TestLog: playerEx.TestLog, WinRankScore: rankScore + otherScore, RankScore: playerEx.GetRankScore(sceneEx.GetDBGameFree().GetRankType()), AddScore: otherScore, BombRankScore: playerEx.bombRankScore, CardsScore: playerEx.cardScore, } tienlenPerson.DelOrderCards = make(map[int][]int32, len(sceneEx.delOrders)) for i2, orderSnid := range sceneEx.delOrders { if orderSnid == playerEx.SnId { tienlenPerson.DelOrderCards[i2] = sceneEx.delCards[i2] } } //排下序,正常应该客户端排序 cards := make([]int32, rule.HandCardNum) copy(cards, playerEx.cards[:]) sort.Slice(cards, func(i, j int) bool { v_i := rule.Value(int32(cards[i])) v_j := rule.Value(int32(cards[j])) c_i := rule.Color(int32(cards[i])) c_j := rule.Color(int32(cards[j])) if v_i > v_j { return false } else if v_i == v_j { return c_i < c_j } return true }) for _, card := range cards { if card != rule.InvalideCard { billData.Cards = append(billData.Cards, card) tienlenPerson.CardInfoEnd = append(tienlenPerson.CardInfoEnd, card) } } pack.Datas = append(pack.Datas, billData) sceneEx.TryBillExGameDrop(playerEx.Player) //赢家 tienlenType.PlayerData = append(tienlenType.PlayerData, tienlenPerson) } } } } proto.SetDefaults(pack) s.Broadcast(int(tienlen.TienLenPacketID_PACKET_SCTienLenGameBilled), pack, 0) logger.Logger.Trace("TienLenPacketID_PACKET_SCTienLenGameBilled gameFreeId:", sceneEx.GetGameFreeId(), ";pack:", pack) if sceneEx.IsCustom() && sceneEx.TotalOfGames > 0 { for _, v := range tienlenType.PlayerData { d := sceneEx.BilledList[v.UserId] if d == nil { arr := make([]*BilledInfo, 0) d = &arr sceneEx.BilledList[v.UserId] = d } *d = append(*d, &BilledInfo{ Round: int32(sceneEx.NumOfGames), ChangeScore: v.BillCoin, Score: base.PlayerMgrSington.GetPlayerBySnId(v.UserId).GetCoin(), }) } sceneEx.RoundEndTime = append(sceneEx.RoundEndTime, time.Now().Unix()) sceneEx.RoundLogId = append(sceneEx.RoundLogId, sceneEx.recordId) if sceneEx.NumOfGames >= int(sceneEx.TotalOfGames) { sceneEx.BilledList = make(map[int32]*[]*BilledInfo) sceneEx.RoundEndTime = sceneEx.RoundEndTime[:0] sceneEx.RoundLogId = sceneEx.RoundLogId[:0] packBilled := &tienlen.SCTienLenCycleBilled{} for snid, billedList := range sceneEx.BilledList { info := &tienlen.TienLenCycleBilledInfo{ SnId: snid, TotalScore: 1000, Score: 1000, } for _, bill := range *billedList { info.RoundScore = append(info.RoundScore, bill.ChangeScore) info.TotalScore += bill.ChangeScore } packBilled.List = append(packBilled.List, info) } sort.Slice(packBilled.List, func(i, j int) bool { var a, b int64 for _, v := range packBilled.List[i].RoundScore { a += v } a += packBilled.List[i].Score for _, v := range packBilled.List[j].RoundScore { b += v } b += packBilled.List[j].Score return a > b }) if len(packBilled.List) > 0 { for _, v := range sceneEx.Items { packBilled.List[0].Award = append(packBilled.List[0].Award, &tienlen.ItemInfo{ Id: v.Id, Num: v.Num, }) } // 发奖品 if len(sceneEx.Items) > 0 { p := base.PlayerMgrSington.GetPlayerBySnId(packBilled.List[0].SnId) if p != nil { var items []*model.Item for _, v := range packBilled.List[0].Award { itemData := srvdata.GameItemMgr.Get(p.Platform, p.SnId) if itemData != nil { items = append(items, &model.Item{ ItemId: v.GetId(), ItemNum: v.GetNum(), }) } } p.AddItems(&model.AddItemParam{ P: &p.PlayerData, Change: items, GainWay: common.GainWayRoomGain, Operator: "system", Remark: "房卡场奖励", GameId: int64(sceneEx.GameId), GameFreeId: int64(sceneEx.GetGameFreeId()), }) } } } s.Broadcast(int(tienlen.TienLenPacketID_PACKET_SCTienLenCycleBilled), packBilled, 0) s.SyncSceneState(common.SceneStateEnd) } } // 牌局记录 info, err := model.MarshalGameNoteByFIGHT(&tienlenType) if err == nil { isSave := false for _, o_player := range tienlenType.PlayerData { if !sceneEx.Testing && !o_player.IsRob { isSave = true var totalin, totalout int64 if o_player.GainCoin < 0 { totalin -= (o_player.GainCoin + o_player.GainTaxCoin) } else { totalout += (o_player.GainCoin + o_player.GainTaxCoin) } if o_player.BombCoin < 0 { totalin -= (o_player.BombCoin + o_player.BombTaxCoin) } else { totalout += (o_player.BombCoin + o_player.BombTaxCoin) } // 刷新存钱罐 playerEx := s.GetPlayer(o_player.UserId) if playerEx != nil && (!(s.IsFreePublic() || s.IsMatchScene())) { playerEx.UpdatePigBankCoin(o_player.GainCoin) } validFlow := totalin + totalout validBet := common.AbsI64(totalin - totalout) sceneEx.SaveFriendRecord(o_player.UserId, o_player.IsWin, o_player.BillCoin, sceneEx.GetBaseScore()) // 玩家数据统计 winState := int32(0) if o_player.IsWin == 1 { winState = 1 } else if o_player.IsWin == 2 { winState = 2 } else { winState = 3 } sceneEx.Statistics(&base.StaticParam{ SnId: o_player.UserId, Gain: o_player.GainCoin + o_player.BombCoin, GainTax: o_player.GainTaxCoin + o_player.BombTaxCoin, IsAddTimes: true, HasRobotGaming: sceneEx.robotGamingNum > 0, WinState: winState, }) // 保存玩家游戏记录 sceneEx.SaveGamePlayerListLog(o_player.UserId, base.GetSaveGamePlayerListLogParam(o_player.Platform, o_player.Channel, o_player.Promoter, o_player.PackageTag, sceneEx.recordId, o_player.InviterId, totalin, totalout, o_player.BillTaxCoin, 0, 0, o_player.GainCoin+o_player.BombCoin, validBet, validFlow, o_player.IsFirst, o_player.IsLeave)) } } if isSave { // 牌局记录 sceneEx.SaveGameDetailedLog(sceneEx.recordId, info, &base.GameDetailedParam{ Trend20Lately: "", CtrlType: sceneEx.ctrlType, PlayerPool: tienlenType.PlayerPool, }) } } if s.IsMatchScene() { //记录比赛数据 var matchRobotGrades []base.MatchRobotGrade var realPlayers []*base.Player for _, p := range sceneEx.players { if p != nil && p.IsGameing() { if p.IsRob { CopySnid := p.SnId if len(p.MatchParams) > 2 && p.MatchParams[2] != 0 { CopySnid = p.MatchParams[2] } mrg := &base.MatchRobotGrade{ CopySnid: CopySnid, Grade: int32(p.Coin), } matchRobotGrades = append(matchRobotGrades, *mrg) } else { p.MatchRobotGrades = nil realPlayers = append(realPlayers, p.Player) } } } if realPlayers != nil && len(realPlayers) == 1 && matchRobotGrades != nil && len(matchRobotGrades) > 0 { //真人把机器人记录带出去 realPlayers[0].MatchRobotGrades = matchRobotGrades } } if sceneEx.isCardsKu { playerEx := sceneEx.players[sceneEx.winSnids[0]] logger.Logger.Infof("telnet使用牌库,模式:是否娱乐 %t,随机到的牌库id = %d,赢家是否是机器人:%t,赢家snid = %d\n", sceneEx.IsTienLenYule(), sceneEx.cardsKuId, playerEx.IsRob, playerEx.SnId) } sceneEx.isCardsKu = false sceneEx.cardsKuId = -1 if !sceneEx.IsRankMatch() { sceneEx.NotifySceneRoundPause() } } } // 状态离开时 func (this *SceneBilledStateTienLen) OnLeave(s *base.Scene) { this.SceneBaseStateTienLen.OnLeave(s) if sceneEx, ok := s.GetExtraData().(*TienLenSceneData); ok { sceneEx.lastGamingPlayerNum = sceneEx.curGamingPlayerNum sceneEx.curGamingPlayerNum = 0 if len(sceneEx.tianHuSnids) != sceneEx.GetGameingPlayerCnt() { //非和局 sceneEx.lastWinSnid = sceneEx.winSnids[0] } sceneEx.SetGaming(false) hasLeave := false //剔除下线玩家 for i := 0; i < sceneEx.GetPlayerNum(); i++ { player_data := sceneEx.seats[i] if player_data == nil { continue } player_data.Clear() if sceneEx.IsMatchScene() { continue } if !player_data.IsOnLine() { sceneEx.PlayerLeave(player_data.Player, common.PlayerLeaveReason_DropLine, true) hasLeave = true continue } if player_data.IsRob { if player_data.robotGameTimes <= 0 { sceneEx.PlayerLeave(player_data.Player, common.PlayerLeaveReason_Normal, true) hasLeave = true continue } if s.CoinOverMaxLimit(player_data.GetCoin(), player_data.Player) { sceneEx.PlayerLeave(player_data.Player, common.PlayerLeaveReason_Normal, true) hasLeave = true continue } } if !s.CoinInLimit(player_data.GetCoin()) { sceneEx.PlayerLeave(player_data.Player, s.NotCoinInLimitType(player_data.GetCoin()), true) hasLeave = true continue } if player_data.IsAuto() && !player_data.IsRob { player_data.LeaveAutoState(s) if !(s.IsMatchScene() || s.IsRankMatch()) { sceneEx.PlayerLeave(player_data.Player, common.PlayerLeaveReason_AutoState, true) hasLeave = true } continue } } if !hasLeave && !sceneEx.IsRobFightGame() && !sceneEx.IsMatchScene() { s.TryDismissRob() } if s.CheckNeedDestroy() || (s.IsMatchScene() && (!s.GetMatch().GetIsFinals() || (s.GetMatch().GetIsFinals() && s.NumOfGames >= 2))) { // 非决赛打一场 决赛打两场 sceneEx.SceneDestroy(true) } if s.TotalOfGames > 0 && s.NumOfGames >= int(s.TotalOfGames) { sceneEx.SceneDestroy(true) } s.RankMatchDestroy() s.TryRelease() } } // 玩家操作 func (this *SceneBilledStateTienLen) OnPlayerOp(s *base.Scene, p *base.Player, opcode int, params []int64) bool { if this.SceneBaseStateTienLen.OnPlayerOp(s, p, opcode, params) { return true } return true } // 玩家事件 func (this *SceneBilledStateTienLen) OnPlayerEvent(s *base.Scene, p *base.Player, evtcode int, params []int64) { this.SceneBaseStateTienLen.OnPlayerEvent(s, p, evtcode, params) } func (this *SceneBilledStateTienLen) OnTick(s *base.Scene) { this.SceneBaseStateTienLen.OnTick(s) if sceneEx, ok := s.GetExtraData().(*TienLenSceneData); ok { newTime := rule.TienLenBilledTimeout if sceneEx.isAllRob { newTime = time.Second * 1 } n := len(sceneEx.tianHuSnids) newTime += time.Duration(n) * rule.TIenLenTianhuTimeout if time.Now().Sub(sceneEx.StateStartTime) > newTime { //开始前再次检查开始条件 if sceneEx.CanStart() == true { s.ChangeSceneState(rule.TienLenSceneStateWaitStart) } else { s.ChangeSceneState(rule.TienLenSceneStateWaitPlayer) } } } } // ////////////////////////////////////////////////////////////////////////////// func (this *ScenePolicyTienLen) RegisteSceneState(state base.SceneState) { if state == nil { return } stateid := state.GetState() if stateid < 0 || stateid >= rule.TienLenSceneStateMax { return } this.states[stateid] = state } func (this *ScenePolicyTienLen) GetSceneState(s *base.Scene, stateid int) base.SceneState { if stateid >= 0 && stateid < rule.TienLenSceneStateMax { return this.states[stateid] } return nil } func init() { ScenePolicyTienLenSingleton.RegisteSceneState(&SceneWaitPlayerStateTienLen{}) ScenePolicyTienLenSingleton.RegisteSceneState(&SceneWaitStartStateTienLen{}) ScenePolicyTienLenSingleton.RegisteSceneState(&SceneHandCardStateTienLen{}) ScenePolicyTienLenSingleton.RegisteSceneState(&ScenePlayerOpStateTienLen{}) ScenePolicyTienLenSingleton.RegisteSceneState(&SceneBilledStateTienLen{}) core.RegisteHook(core.HOOK_BEFORE_START, func() error { // 自由桌 base.RegisteScenePolicy(common.GameId_TienLen, 0, ScenePolicyTienLenSingleton) base.RegisteScenePolicy(common.GameId_TienLen_yl, 0, ScenePolicyTienLenSingleton) base.RegisteScenePolicy(common.GameId_TienLen_toend, 0, ScenePolicyTienLenSingleton) base.RegisteScenePolicy(common.GameId_TienLen_yl_toend, 0, ScenePolicyTienLenSingleton) // 比赛 base.RegisteScenePolicy(common.GameId_TienLen_m, 0, ScenePolicyTienLenSingleton) base.RegisteScenePolicy(common.GameId_TienLen_m_toend, 0, ScenePolicyTienLenSingleton) // 手动选场 base.RegisteScenePolicy(common.GameId_TienLenSelect, 0, ScenePolicyTienLenSingleton) base.RegisteScenePolicy(common.GameId_TienLenSelect_toend, 0, ScenePolicyTienLenSingleton) base.RegisteScenePolicy(common.GameId_TienLenSelect_yl, 0, ScenePolicyTienLenSingleton) base.RegisteScenePolicy(common.GameId_TienLenSelect_yl_toend, 0, ScenePolicyTienLenSingleton) // 排位赛 base.RegisteScenePolicy(common.GameId_TienLenRank, 0, ScenePolicyTienLenSingleton) base.RegisteScenePolicy(common.GameId_TienLenRank_toend, 0, ScenePolicyTienLenSingleton) base.RegisteScenePolicy(common.GameId_TienLenRank_yl, 0, ScenePolicyTienLenSingleton) base.RegisteScenePolicy(common.GameId_TienLenRank_yl_toend, 0, ScenePolicyTienLenSingleton) // 房卡场 base.RegisteScenePolicy(common.GameId_TienLenCustom, 0, ScenePolicyTienLenSingleton) base.RegisteScenePolicy(common.GameId_TienLenCustom_toend, 0, ScenePolicyTienLenSingleton) base.RegisteScenePolicy(common.GameId_TienLenCustom_yl, 0, ScenePolicyTienLenSingleton) base.RegisteScenePolicy(common.GameId_TienLenCustom_yl_toend, 0, ScenePolicyTienLenSingleton) return nil }) }