2893 lines
102 KiB
Go
2893 lines
102 KiB
Go
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()),
|
||
})
|
||
sceneEx.PlayerAward[p.SnId] = &items
|
||
}
|
||
}
|
||
}
|
||
s.Broadcast(int(tienlen.TienLenPacketID_PACKET_SCTienLenCycleBilled), packBilled, 0)
|
||
s.SyncSceneState(common.SceneStateEnd)
|
||
sceneEx.SaveCustomLog()
|
||
}
|
||
}
|
||
|
||
// 牌局记录
|
||
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,
|
||
})
|
||
|
||
// 保存玩家游戏记录
|
||
param := 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)
|
||
param.CycleId = sceneEx.CycleID
|
||
sceneEx.SaveGamePlayerListLog(o_player.UserId, param)
|
||
}
|
||
}
|
||
if isSave {
|
||
// 牌局记录
|
||
sceneEx.SaveGameDetailedLog(sceneEx.recordId, info, &base.GameDetailedParam{
|
||
Trend20Lately: "",
|
||
CtrlType: sceneEx.ctrlType,
|
||
PlayerPool: tienlenType.PlayerPool,
|
||
CycleId: sceneEx.CycleID,
|
||
})
|
||
}
|
||
}
|
||
|
||
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
|
||
})
|
||
}
|