开启拉霸游戏

This commit is contained in:
sk 2024-04-19 11:43:13 +08:00
parent aadfc98306
commit 33a087d1d7
42 changed files with 9024 additions and 551 deletions

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@ -54,18 +54,6 @@
"GameId": 401, "GameId": 401,
"GameDif": "401" "GameDif": "401"
}, },
{
"Id": 30600,
"Name": "水果拉霸",
"GameId": 306,
"GameDif": "306"
},
{
"Id": 30400,
"Name": "冰河世纪",
"GameId": 304,
"GameDif": "304"
},
{ {
"Id": 52100, "Id": 52100,
"Name": "ChessCambodian", "Name": "ChessCambodian",
@ -165,6 +153,48 @@
"Name": "小火箭", "Name": "小火箭",
"GameId": 607, "GameId": 607,
"GameDif": "607" "GameDif": "607"
},
{
"Id": 30100,
"Name": "财运神",
"GameId": 301,
"GameDif": "301"
},
{
"Id": 30200,
"Name": "复仇者联盟",
"GameId": 302,
"GameDif": "302"
},
{
"Id": 30300,
"Name": "复活节岛",
"GameId": 303,
"GameDif": "303"
},
{
"Id": 30400,
"Name": "冰河世纪",
"GameId": 304,
"GameDif": "304"
},
{
"Id": 30500,
"Name": "百战成神",
"GameId": 305,
"GameDif": "305"
},
{
"Id": 30600,
"Name": "水果拉霸",
"GameId": 306,
"GameDif": "306"
},
{
"Id": 30700,
"Name": "多财多福",
"GameId": 307,
"GameDif": "307"
} }
] ]
} }

View File

@ -1,5 +1,5 @@
6в├с├т├уж"║█ю└= 6ж├в├с├т├у├"║█ю└=
.؆Ù†Ú†Û†"¡<>À„= .؆Ù†Ú†Û†"¡<>À„=
Wу├ж├ш├с├в├ь├ы├з├т" ║█─╜Б Wс├ж├т├у├в├ь├ы├з├ш" ║█─╜Б
]ь├ы├э├с├т├у├ж├в├з├ш"╒█Т ]т├у├ы├э├з├ш├с├ж├в├ь"╒█Т

Binary file not shown.

View File

@ -0,0 +1,54 @@
package avengers
import (
"mongo.games.com/goserver/core/logger"
"mongo.games.com/goserver/core/netlib"
"mongo.games.com/game/common"
"mongo.games.com/game/gamesrv/base"
"mongo.games.com/game/protocol/avengers"
)
// 复仇者联盟的操作
type CSAvengersOpPacketFactory struct {
}
type CSAvengersOpHandler struct {
}
func (this *CSAvengersOpPacketFactory) CreatePacket() interface{} {
pack := &avengers.CSAvengersOp{}
return pack
}
func (this *CSAvengersOpHandler) Process(s *netlib.Session, packetid int, data interface{}, sid int64) error {
logger.Logger.Trace("CSAvengersOpHandler Process recv ", data)
if csAvengersOp, ok := data.(*avengers.CSAvengersOp); ok {
p := base.PlayerMgrSington.GetPlayer(sid)
if p == nil {
logger.Logger.Warn("CSAvengersOpHandler p == nil")
return nil
}
scene := p.GetScene()
if scene == nil {
logger.Logger.Warn("CSAvengersOpHandler p.scene == nil")
return nil
}
if scene.GameId != common.GameId_Avengers {
logger.Logger.Error("CSAvengersOpHandler gameId Error ", scene.GameId)
return nil
}
if !scene.HasPlayer(p) {
return nil
}
sp := scene.GetScenePolicy()
if sp != nil {
sp.OnPlayerOp(scene, p, int(csAvengersOp.GetOpCode()), csAvengersOp.GetParams())
}
return nil
}
return nil
}
func init() {
// 复仇者联盟的操作
common.RegisterHandler(int(avengers.AvengersPacketID_PACKET_CS_AVENGERS_PLAYEROP), &CSAvengersOpHandler{})
netlib.RegisterFactory(int(avengers.AvengersPacketID_PACKET_CS_AVENGERS_PLAYEROP), &CSAvengersOpPacketFactory{})
}

View File

@ -0,0 +1,116 @@
package avengers
import (
"encoding/json"
"time"
"mongo.games.com/game/model"
)
// 玩家游戏数据索引
const (
AvengersFreeTimes int = iota //0 当前剩余免费次数
AvengersIndexMax
)
// 场景状态
const (
AvengersSceneStateStart int = iota //开始游戏
AvengersSceneStateMax
)
// 玩家操作
const (
AvengersPlayerOpStart int = iota //游戏
AvengersPlayerHistory // 游戏记录
AvengersBurstHistory // 奖池记录
AvengersBonusGame // 小游戏
AvengersBonusGameRecord // 小游戏操作记录
)
const (
AvengersBonusGameTimeout = time.Second * 60 // 小游戏最大超时时间
AvengersBonusGameStageTimeout = 15 // 小游戏每阶段的超时时间 秒
)
type GameResultLog struct {
BaseResult *model.SlotBaseResultType
AllLine int32 //线路数
UserName string //昵称
WinLines []int //赢分的线
BetLines []int64 //下注的线
}
// 复仇者联盟解析的数据
type AvengersGameNoteData struct {
Source int32
Data *GameResultLog
}
// 复仇者联盟游戏记录
func UnMarshalAvengersGameNote(data string) (roll interface{}, err error) {
gnd := &AvengersGameNoteData{}
if err := json.Unmarshal([]byte(data), gnd); err != nil {
return nil, err
}
roll = gnd.Data
return
}
var DebugData = [][]int{
{
5, 5, 8, 4, 5,
4, 4, 1, 4, 1,
4, 4, 2, 4, 10,
},
{
2, 2, 2, 2, 2,
2, 2, 2, 2, 2,
2, 2, 2, 2, 2,
},
{
3, 3, 3, 3, 3,
3, 3, 3, 3, 3,
3, 3, 3, 3, 3,
},
{
4, 4, 4, 4, 4,
4, 4, 4, 4, 4,
4, 4, 4, 4, 4,
},
{
5, 5, 5, 5, 5,
5, 5, 5, 5, 5,
5, 5, 5, 5, 5,
},
{
6, 6, 6, 6, 6,
6, 6, 6, 6, 6,
6, 6, 6, 6, 6,
},
{
7, 7, 7, 7, 7,
7, 7, 7, 7, 7,
7, 7, 7, 7, 7,
},
{
8, 8, 8, 8, 8,
8, 8, 8, 8, 8,
8, 8, 8, 8, 8,
},
{
9, 9, 9, 9, 9,
9, 9, 9, 9, 9,
9, 9, 9, 9, 9,
},
{
10, 10, 10, 10, 10,
10, 10, 10, 10, 10,
10, 10, 10, 10, 10,
},
{
11, 11, 11, 11, 11,
11, 11, 11, 11, 11,
11, 11, 11, 11, 11,
},
}

View File

@ -0,0 +1,156 @@
package avengers
import (
"encoding/json"
"math/rand"
"mongo.games.com/goserver/core/timer"
rule "mongo.games.com/game/gamerule/avengers"
"mongo.games.com/game/gamesrv/base"
"mongo.games.com/game/model"
"mongo.games.com/game/protocol/avengers"
)
type AvengersPlayerData struct {
*base.Player
spinID int64 //当前旋转ID
score int32 //单线押注数
freeTimes int32 //免费转动次数
cards []int32 //15张牌
//RollGameType *model.AvengersType //记录信息
RollGameType *GameResultLog //记录信息
enterGameCoin int64 //玩家进入初始金币
taxCoin int64 //本局税收
winCoin int64 //本局收税前赢的钱
linesWinCoin int64 //本局中奖线赢得钱
jackpotWinCoin int64 //本局奖池赢的钱
smallGameWinCoin int64 //本局小游戏赢的钱
betLines []int64 //下注的选线
currentLogId string //爆奖玩家logid
leavetime int32 //用户离开时间
totalPriceBonus int64 //小游戏得分
bonusTimerHandle timer.TimerHandle //托管超时handle
bonusStage int32 //小游戏所处阶段 1选金额 2选倍率
bonusStartTime int64 //小游戏阶段开始时间
bonusOpRecord []int32 //小游戏操作记录
bonusGame *avengers.AvengersBonusGameInfo //小游戏
bonusX []int32 //小游戏倍率选项
billedData *avengers.GameBilledData //上一局结算信息
DebugGame bool //测试
TestNum int
}
// 玩家初始化
func (this *AvengersPlayerData) init(s *base.Scene) {
this.Clean()
this.score = 0
this.freeTimes = 0
//this.RollGameType = &model.AvengersType{}
//this.RollGameType.Init()
this.RollGameType = &GameResultLog{}
this.RollGameType.BaseResult = &model.SlotBaseResultType{}
this.enterGameCoin = this.Coin
this.currentLogId = ""
this.billedData = &avengers.GameBilledData{}
this.DebugGame = true
this.TestNum = 0
// 加载玩家游戏数据
if this.GDatas == nil {
this.GDatas = make(map[string]*model.PlayerGameInfo)
}
if d, exist := this.GDatas[s.KeyGamefreeId]; exist {
gLen := len(d.Data)
if gLen < AvengersIndexMax {
for i := gLen; i < AvengersIndexMax; i++ {
d.Data = append(d.Data, 0)
}
}
} else {
pgd := &model.PlayerGameInfo{
Data: make([]int64, AvengersIndexMax),
}
this.GDatas[s.KeyGamefreeId] = pgd
}
this.LoadPlayerGameData(s.KeyGamefreeId)
//线条全选
if len(this.betLines) == 0 {
this.betLines = rule.AllBetLines
}
}
// 玩家清理数据
func (this *AvengersPlayerData) Clean() {
for i := 0; i < len(this.cards); i++ {
this.cards[i] = -1
}
this.winCoin = 0
this.taxCoin = 0
this.linesWinCoin = 0
this.jackpotWinCoin = 0
this.smallGameWinCoin = 0
this.CleanBonus()
}
// 清理小游戏数据
func (this *AvengersPlayerData) CleanBonus() {
this.totalPriceBonus = 0
this.bonusStage = 0
this.bonusTimerHandle = timer.TimerHandle(0)
this.bonusStartTime = 0
this.bonusOpRecord = make([]int32, 0)
this.bonusGame = nil
this.bonusX = nil
}
// 加载玩家游戏数据
func (this *AvengersPlayerData) LoadPlayerGameData(gameFreeId string) {
if d, exist := this.GDatas[gameFreeId]; exist {
this.freeTimes = int32(d.Data[AvengersFreeTimes])
if this.freeTimes > 0 && len(d.DataEx) != 0 {
json.Unmarshal(d.DataEx, &this.betLines)
}
}
}
// 存储玩家游戏数据
func (this *AvengersPlayerData) SavePlayerGameData(gameFreeId string) {
if d, exist := this.GDatas[gameFreeId]; exist {
d.Data[AvengersFreeTimes] = int64(this.freeTimes)
d.DataEx, _ = json.Marshal(this.betLines)
}
}
// 黑白名单的限制是否生效
func (this *AvengersPlayerData) CheckBlackWriteList(isWin bool) bool {
if isWin && this.BlackLevel > 0 && this.BlackLevel <= 10 {
if rand.Int31n(100) < this.BlackLevel*10 {
return true
}
} else if !isWin && this.WhiteLevel > 0 && this.WhiteLevel <= 10 {
if rand.Int31n(100) < this.WhiteLevel*10 {
return true
}
}
return false
}
// 玩家是否是新手
func (this *AvengersPlayerData) IsFNovice(keyGameId string) {
if f, ok := this.IsFoolPlayer[keyGameId]; ok {
if !f {
return
}
} else {
this.IsFoolPlayer[keyGameId] = true
return
}
if data, ok := this.GDatas[keyGameId]; ok {
if data.Statics.GameTimes < 100 && data.Statics.TotalOut-data.Statics.TotalIn <= 2000000 {
return
}
this.IsFoolPlayer[keyGameId] = false
}
}

View File

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

File diff suppressed because it is too large Load Diff

View File

@ -1,94 +1,98 @@
package base package base
//import ( import (
// "encoding/json" "encoding/json"
// "fmt" "fmt"
"time"
"mongo.games.com/goserver/core/logger"
"mongo.games.com/goserver/core/module"
"mongo.games.com/game/common"
"mongo.games.com/game/model"
)
var XSlotsPoolMgr = &XSlotsPoolManager{
SlotsPoolData: make(map[string]interface{}),
SlotsPoolStr: make(map[string]string),
}
type XSlotsPoolManager struct {
// //
// "mongo.games.com/goserver/core/logger" SlotsPoolData map[string]interface{}
// "mongo.games.com/goserver/core/module"
// //
// "mongo.games.com/game/common" SlotsPoolStr map[string]string
// "mongo.games.com/game/model"
//)
// //
//var XSlotsPoolMgr = &XSlotsPoolManager{ SlotsPoolDBKey string
// //SlotsPoolData: make(map[string]interface{}), }
// SlotsPoolStr: make(map[string]string),
//} func (this *XSlotsPoolManager) GetPool(gamefreeId int32, platform string) string {
// key := fmt.Sprintf("%v-%v", gamefreeId, platform)
//type XSlotsPoolManager struct { if str, exist := this.SlotsPoolStr[key]; exist {
// //SlotsPoolData map[string]interface{} return str
// SlotsPoolStr map[string]string }
// SlotsPoolDBKey string return ""
//} }
//
//func (this *XSlotsPoolManager) GetPool(gamefreeId int32, platform string) string { //func (this *XSlotsPoolManager) SetPool(gamefreeId int32, platform string, pool interface{}) {
// key := fmt.Sprintf("%v-%v", gamefreeId, platform) // key := fmt.Sprintf("%v-%v", gamefreeId, platform)
// if str, exist := this.SlotsPoolStr[key]; exist { // this.SlotsPoolData[key] = pool
// return str
//} //}
// return ""
//} //func (this *XSlotsPoolManager) GetPoolByPlatform(platform string) map[string]interface{} {
// // slots := make(map[string]interface{})
////func (this *XSlotsPoolManager) SetPool(gamefreeId int32, platform string, pool interface{}) { // for k, v := range this.SlotsPoolData {
//// key := fmt.Sprintf("%v-%v", gamefreeId, platform) // str := strings.Split(k, "-")
//// this.SlotsPoolData[key] = pool // if len(str) == 2 && str[1] == platform {
////} // idStr := str[0]
// // slots[idStr] = v
////func (this *XSlotsPoolManager) GetPoolByPlatform(platform string) map[string]interface{} {
//// slots := make(map[string]interface{})
//// for k, v := range this.SlotsPoolData {
//// str := strings.Split(k, "-")
//// if len(str) == 2 && str[1] == platform {
//// idStr := str[0] // gamefreeid
//// slots[idStr] = v
//// }
//// }
//// return slots
////}
//
//// //////////////////////////////////////////////////////////////////
//// / Module Implement [beg]
//// //////////////////////////////////////////////////////////////////
//func (this *XSlotsPoolManager) ModuleName() string {
// return "XSlotsPoolManager"
//}
//
//func (this *XSlotsPoolManager) Init() {
// this.SlotsPoolDBKey = fmt.Sprintf("XSlotsPoolManager_Srv%v", common.GetSelfSrvId())
// data := model.GetStrKVGameData(this.SlotsPoolDBKey)
// err := json.Unmarshal([]byte(data), &this.SlotsPoolStr)
// if err != nil {
// logger.Logger.Error("Unmarshal slots pool error:", err)
// } // }
// } // }
// // return slots
//func (this *XSlotsPoolManager) Update() {
// this.Save()
//}
//
//func (this *XSlotsPoolManager) Shutdown() {
// this.Save()
// module.UnregisteModule(this)
//}
//
//func (this *XSlotsPoolManager) Save() {
// //数据先整合
// //for k, v := range this.SlotsPoolData {
// // data, err := json.Marshal(v)
// // if err == nil {
// // this.SlotsPoolStr[k] = string(data)
// // }
// //}
// //再保存
// buff, err := json.Marshal(this.SlotsPoolStr)
// if err == nil {
// model.UptStrKVGameData(this.SlotsPoolDBKey, string(buff))
// } else {
// logger.Logger.Error("Marshal coin pool error:", err)
// }
//}
//
//func init() {
// //module.RegisteModule(XSlotsPoolMgr, time.Minute, 0)
//} //}
// //////////////////////////////////////////////////////////////////
// / Module Implement [beg]
// //////////////////////////////////////////////////////////////////
func (this *XSlotsPoolManager) ModuleName() string {
return "XSlotsPoolManager"
}
func (this *XSlotsPoolManager) Init() {
this.SlotsPoolDBKey = fmt.Sprintf("XSlotsPoolManager_Srv%v", common.GetSelfSrvId())
data := model.GetStrKVGameData(this.SlotsPoolDBKey)
err := json.Unmarshal([]byte(data), &this.SlotsPoolStr)
if err != nil {
logger.Logger.Error("Unmarshal slots pool error:", err)
}
}
func (this *XSlotsPoolManager) Update() {
this.Save()
}
func (this *XSlotsPoolManager) Shutdown() {
this.Save()
module.UnregisteModule(this)
}
func (this *XSlotsPoolManager) Save() {
//数据先整合
for k, v := range this.SlotsPoolData {
data, err := json.Marshal(v)
if err == nil {
this.SlotsPoolStr[k] = string(data)
}
}
//再保存
buff, err := json.Marshal(this.SlotsPoolStr)
if err == nil {
model.UptStrKVGameData(this.SlotsPoolDBKey, string(buff))
} else {
logger.Logger.Error("Marshal coin pool error:", err)
}
}
func init() {
module.RegisteModule(XSlotsPoolMgr, time.Minute, 0)
}

View File

@ -0,0 +1,55 @@
package caishen
import (
"mongo.games.com/goserver/core/logger"
"mongo.games.com/goserver/core/netlib"
"mongo.games.com/game/common"
"mongo.games.com/game/gamesrv/base"
"mongo.games.com/game/protocol/caishen"
)
// 财神的操作
type CSCaiShenOpPacketFactory struct {
}
type CSCaiShenOpHandler struct {
}
func (this *CSCaiShenOpPacketFactory) CreatePacket() interface{} {
pack := &caishen.CSCaiShenOp{}
return pack
}
func (this *CSCaiShenOpHandler) Process(s *netlib.Session, packetid int, data interface{}, sid int64) error {
logger.Logger.Trace("CSCaiShenOpHandler Process recv ", data)
if csCaiShenOp, ok := data.(*caishen.CSCaiShenOp); ok {
p := base.PlayerMgrSington.GetPlayer(sid)
if p == nil {
logger.Logger.Warn("CSCaiShenOpHandler p == nil")
return nil
}
scene := p.GetScene()
if scene == nil {
logger.Logger.Warn("CSCaiShenOpHandler p.scene == nil")
return nil
}
if scene.GameId != common.GameId_CaiShen {
logger.Logger.Error("CSCaiShenOpHandler gameId Error ", scene.GameId)
return nil
}
if !scene.HasPlayer(p) {
return nil
}
sp := scene.GetScenePolicy()
if sp != nil {
sp.OnPlayerOp(scene, p, int(csCaiShenOp.GetOpCode()), csCaiShenOp.GetParams())
}
return nil
}
return nil
}
func init() {
// 财神的操作
common.RegisterHandler(int(caishen.CaiShenPacketID_PACKET_CS_CAISHEN_PLAYEROP), &CSCaiShenOpHandler{})
netlib.RegisterFactory(int(caishen.CaiShenPacketID_PACKET_CS_CAISHEN_PLAYEROP), &CSCaiShenOpPacketFactory{})
}

120
gamesrv/caishen/constant.go Normal file
View File

@ -0,0 +1,120 @@
package caishen
import (
"encoding/json"
"time"
"mongo.games.com/game/model"
)
// 玩家游戏数据索引
const (
CaiShenFreeTimes int = iota //0 当前剩余免费次数
CaiShenIndexMax
)
// 通知奖池变化的时间间隔
const jackpotNoticeInterval = time.Second
// 场景状态
const (
CaiShenSceneStateStart int = iota //开始游戏
CaiShenSceneStateMax
)
// 玩家操作
const (
CaiShenPlayerOpStart int = iota //游戏
CaiShenPlayerHistory // 游戏记录
CaiShenBurstHistory // 爆奖记录
CaiShenBonusGame // 小游戏
CaiShenBonusGameRecord // 小游戏操作记录
)
// 小游戏超时时间
const (
CaiShenBonusGameTimeout = time.Second * 60
CaiShenBonusGameStageTimeout = 15 // 小游戏每阶段的超时时间 秒
)
type GameResultLog struct {
BaseResult *model.SlotBaseResultType
AllLine int32 //线路数
UserName string //昵称
WinLines []int //赢分的线
BetLines []int64 //下注的线
}
// 财神解析的数据
type CaiShenGameNoteData struct {
Source int32
Data *GameResultLog
}
// 财神游戏记录
func UnMarshalCaiShenGameNote(data string) (roll interface{}, err error) {
gnd := &CaiShenGameNoteData{}
if err := json.Unmarshal([]byte(data), gnd); err != nil {
return nil, err
}
roll = gnd.Data
return
}
var DebugData = [][]int{
{
1, 1, 1, 5, 5,
1, 1, 1, 3, 4,
6, 7, 8, 9, 10,
},
{
2, 2, 2, 2, 2,
2, 2, 2, 2, 2,
2, 2, 2, 2, 2,
},
{
3, 3, 3, 3, 3,
3, 3, 3, 3, 3,
3, 3, 3, 3, 3,
},
{
4, 4, 4, 4, 4,
4, 4, 4, 4, 4,
4, 4, 4, 4, 4,
},
{
5, 5, 5, 5, 5,
5, 5, 5, 5, 5,
5, 5, 5, 5, 5,
},
{
6, 6, 6, 6, 6,
6, 6, 6, 6, 6,
6, 6, 6, 6, 6,
},
{
7, 7, 7, 7, 7,
7, 7, 7, 7, 7,
7, 7, 7, 7, 7,
},
{
8, 8, 8, 8, 8,
8, 8, 8, 8, 8,
8, 8, 8, 8, 8,
},
{
9, 9, 9, 9, 9,
9, 9, 9, 9, 9,
9, 9, 9, 9, 9,
},
{
10, 10, 10, 10, 10,
10, 10, 10, 10, 10,
10, 10, 10, 10, 10,
},
{
11, 11, 11, 11, 11,
11, 11, 11, 11, 11,
11, 11, 11, 11, 11,
},
}

View File

@ -0,0 +1,156 @@
package caishen
import (
"encoding/json"
"math/rand"
"mongo.games.com/goserver/core/timer"
rule "mongo.games.com/game/gamerule/caishen"
"mongo.games.com/game/gamesrv/base"
"mongo.games.com/game/model"
"mongo.games.com/game/protocol/caishen"
)
type CaiShenPlayerData struct {
*base.Player
spinID int64 //当前旋转ID
score int32 //单线押注数
freeTimes int32 //免费转动次数
cards []int32 //15张牌
//RollGameType *model.CaiShenType //记录信息
RollGameType *GameResultLog //记录信息
enterGameCoin int64 //玩家进入初始金币
taxCoin int64 //本局税收
winCoin int64 //本局收税前赢的钱
linesWinCoin int64 //本局中奖线赢得钱
jackpotWinCoin int64 //本局奖池赢的钱
smallGameWinCoin int64 //本局小游戏赢的钱 //新版本已废弃
betLines []int64 //下注的选线
totalPriceBonus int64 //小游戏得分
bonusTimerHandle timer.TimerHandle //托管handle
currentLogId string //爆奖玩家logid
leavetime int32 //用户离开时间
bonusStage int32 //小游戏所处阶段 1选金额 2选倍率
bonusStartTime int64 //小游戏阶段开始时间
bonusOpRecord []int32 //小游戏操作记录
bonusGame *caishen.CaiShenBonusGameInfo //小游戏
bonusX []int32 //小游戏倍率选项
bonusGameIconData []int32 //小游戏选项图标,用于客户端展示
billedData *caishen.GameBilledData
DebugGame bool //测试
TestNum int
}
// 玩家初始化
func (this *CaiShenPlayerData) init(s *base.Scene) {
this.Clean()
this.score = 0
this.freeTimes = 0
//this.RollGameType = &model.CaiShenType{}
this.RollGameType = &GameResultLog{}
this.RollGameType.BaseResult = &model.SlotBaseResultType{}
this.enterGameCoin = this.Coin
this.currentLogId = ""
this.billedData = &caishen.GameBilledData{}
this.DebugGame = true
this.TestNum = 0
// 加载玩家游戏数据
if this.GDatas == nil {
this.GDatas = make(map[string]*model.PlayerGameInfo)
}
if d, exist := this.GDatas[s.KeyGamefreeId]; exist {
gLen := len(d.Data)
if gLen < CaiShenIndexMax {
for i := gLen; i < CaiShenIndexMax; i++ {
d.Data = append(d.Data, 0)
}
}
} else {
pgd := &model.PlayerGameInfo{
Data: make([]int64, CaiShenIndexMax, CaiShenIndexMax),
}
this.GDatas[s.KeyGamefreeId] = pgd
}
this.LoadPlayerGameData(s.KeyGamefreeId)
//线条全选
if len(this.betLines) == 0 {
this.betLines = rule.AllBetLines
}
}
// 玩家清理数据
func (this *CaiShenPlayerData) Clean() {
for i := 0; i < len(this.cards); i++ {
this.cards[i] = -1
}
this.winCoin = 0
this.taxCoin = 0
this.linesWinCoin = 0
this.jackpotWinCoin = 0
this.smallGameWinCoin = 0
this.CleanBonus()
}
// 清理小游戏数据
func (this *CaiShenPlayerData) CleanBonus() {
this.totalPriceBonus = 0
this.bonusStage = 0
this.bonusTimerHandle = timer.TimerHandle(0)
this.bonusStartTime = 0
this.bonusOpRecord = make([]int32, 0)
this.bonusGame = nil
this.bonusX = nil
this.bonusGameIconData = make([]int32, 0)
}
// 加载玩家游戏数据
func (this *CaiShenPlayerData) LoadPlayerGameData(gameFreeId string) {
if d, exist := this.GDatas[gameFreeId]; exist {
this.freeTimes = int32(d.Data[CaiShenFreeTimes])
if this.freeTimes > 0 && len(d.DataEx) != 0 {
json.Unmarshal(d.DataEx, &this.betLines)
}
}
}
// 存储玩家游戏数据
func (this *CaiShenPlayerData) SavePlayerGameData(gameFreeId string) {
if d, exist := this.GDatas[gameFreeId]; exist {
d.Data[CaiShenFreeTimes] = int64(this.freeTimes)
d.DataEx, _ = json.Marshal(this.betLines)
}
}
// 黑白名单的限制是否生效
func (this *CaiShenPlayerData) CheckBlackWriteList(isWin bool) bool {
if isWin && this.BlackLevel > 0 && this.BlackLevel <= 10 {
if rand.Int31n(100) < this.BlackLevel*10 {
return true
}
} else if !isWin && this.WhiteLevel > 0 && this.WhiteLevel <= 10 {
if rand.Int31n(100) < this.WhiteLevel*10 {
return true
}
}
return false
}
// 玩家是否是新手
func (this *CaiShenPlayerData) IsFNovice(keyGameId string) {
if f, ok := this.IsFoolPlayer[keyGameId]; ok {
if !f {
return
}
} else {
this.IsFoolPlayer[keyGameId] = true
return
}
if data, ok := this.GDatas[keyGameId]; ok {
if data.Statics.GameTimes < 100 && data.Statics.TotalOut-data.Statics.TotalIn <= 2000000 {
return
}
this.IsFoolPlayer[keyGameId] = false
}
}

View File

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

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,55 @@
package easterisland
import (
"mongo.games.com/goserver/core/logger"
"mongo.games.com/goserver/core/netlib"
"mongo.games.com/game/common"
"mongo.games.com/game/gamesrv/base"
"mongo.games.com/game/protocol/easterisland"
)
// 复活岛的操作
type CSEasterIslandOpPacketFactory struct {
}
type CSEasterIslandOpHandler struct {
}
func (this *CSEasterIslandOpPacketFactory) CreatePacket() interface{} {
pack := &easterisland.CSEasterIslandOp{}
return pack
}
func (this *CSEasterIslandOpHandler) Process(s *netlib.Session, packetid int, data interface{}, sid int64) error {
logger.Logger.Trace("CSEasterIslandOpHandler Process recv ", data)
if csEasterIslandOp, ok := data.(*easterisland.CSEasterIslandOp); ok {
p := base.PlayerMgrSington.GetPlayer(sid)
if p == nil {
logger.Logger.Warn("CSEasterIslandOpHandler p == nil")
return nil
}
scene := p.GetScene()
if scene == nil {
logger.Logger.Warn("CSEasterIslandOpHandler p.scene == nil")
return nil
}
if scene.GameId != common.GameId_EasterIsland {
logger.Logger.Error("CSEasterIslandOpHandler gameId Error ", scene.GameId)
return nil
}
if !scene.HasPlayer(p) {
return nil
}
sp := scene.GetScenePolicy()
if sp != nil {
sp.OnPlayerOp(scene, p, int(csEasterIslandOp.GetOpCode()), csEasterIslandOp.GetParams())
}
return nil
}
return nil
}
func init() {
// 复活岛的操作
common.RegisterHandler(int(easterisland.EasterIslandPacketID_PACKET_CS_EASTERISLAND_PLAYEROP), &CSEasterIslandOpHandler{})
netlib.RegisterFactory(int(easterisland.EasterIslandPacketID_PACKET_CS_EASTERISLAND_PLAYEROP), &CSEasterIslandOpPacketFactory{})
}

View File

@ -0,0 +1,133 @@
package easterisland
import (
"encoding/json"
"time"
"mongo.games.com/game/model"
)
// 玩家游戏数据索引
const (
EasterIslandFreeTimes int = iota //0 当前剩余免费次数
EasterIslandIndexMax
)
// 通知奖池变化的时间间隔
const jackpotNoticeInterval = time.Second
// 场景状态
const (
EasterIslandSceneStateStart int = iota //开始游戏
EasterIslandSceneStateMax
)
// 玩家操作
const (
EasterIslandPlayerOpStart int = iota //游戏
EasterIslandPlayerHistory //游戏记录
EasterIslandBurstHistory //爆奖记录
EasterIslandBonusGame //小游戏
EasterIslandBonusGameRecord //小游戏操作记录
)
const (
EasterIslandBonusGameTimeout = time.Second * 60
EasterIslandBonusGameStageTimeout = 15 // 小游戏每阶段的超时时间 秒
)
type GameResultLog struct {
BaseResult *model.SlotBaseResultType
AllLine int32 //线路数
UserName string //昵称
WinLines []int //赢分的线
BetLines []int64 //下注的线
}
// 复活岛解析的数据
type EasterIslandGameNoteData struct {
Source int32
Data *GameResultLog
}
// 复活岛游戏记录
func UnMarshalEasterIslandGameNote(data string) (roll interface{}, err error) {
gnd := &EasterIslandGameNoteData{}
if err := json.Unmarshal([]byte(data), gnd); err != nil {
return nil, err
}
roll = gnd.Data
return
}
// {0, 6, 12, 8, 4}, //线条4
// {10, 6, 2, 8, 14}, //线条5
// {5, 1, 12, 3, 9}, //线条22
// {5, 11, 2, 13, 9}, //线条23
var DebugData = [][]int{
{
5, 8, 6, 8, 5,
9, 5, 8, 5, 4,
6, 7, 5, 9, 6,
},
{
6, 8, 5, 8, 6,
9, 5, 8, 5, 4,
5, 7, 6, 9, 5,
},
{
5, 8, 6, 8, 5,
6, 7, 8, 9, 6,
5, 6, 5, 6, 5,
},
{
5, 6, 5, 6, 5,
6, 7, 8, 9, 6,
5, 8, 6, 8, 5,
},
//{
// 3, 3, 3, 3, 3,
// 3, 3, 3, 3, 3,
// 3, 3, 3, 3, 3,
//},
//{
// 4, 4, 4, 4, 4,
// 4, 4, 4, 4, 4,
// 4, 4, 4, 4, 4,
//},
//{
// 5, 5, 5, 5, 5,
// 5, 5, 5, 5, 5,
// 5, 5, 5, 5, 5,
//},
//{
// 6, 6, 6, 6, 6,
// 6, 6, 6, 6, 6,
// 6, 6, 6, 6, 6,
//},
//{
// 7, 7, 7, 7, 7,
// 7, 7, 7, 7, 7,
// 7, 7, 7, 7, 7,
//},
//{
// 8, 8, 8, 8, 8,
// 8, 8, 8, 8, 8,
// 8, 8, 8, 8, 8,
//},
//{
// 9, 9, 9, 9, 9,
// 9, 9, 9, 9, 9,
// 9, 9, 9, 9, 9,
//},
//{
// 10, 10, 10, 10, 10,
// 10, 10, 10, 10, 10,
// 10, 10, 10, 10, 10,
//},
//{
// 11, 11, 11, 11, 11,
// 11, 11, 11, 11, 11,
// 11, 11, 11, 11, 11,
//},
}

View File

@ -0,0 +1,155 @@
package easterisland
import (
"encoding/json"
"math/rand"
"mongo.games.com/goserver/core/timer"
rule "mongo.games.com/game/gamerule/easterisland"
"mongo.games.com/game/gamesrv/base"
"mongo.games.com/game/model"
"mongo.games.com/game/protocol/easterisland"
)
type EasterIslandPlayerData struct {
*base.Player
score int32 //单线押注数
spinID int64 //当前旋转ID
freeTimes int32 //免费转动次数
cards []int32 //15张牌
//RollGameType *model.EasterIslandType //记录信息
RollGameType *GameResultLog //记录信息
enterGameCoin int64 //玩家进入老虎机初始金币
taxCoin int64 //本局税收
winCoin int64 //本局收税前赢的钱
linesWinCoin int64 //本局中奖线赢得钱
jackpotWinCoin int64 //本局奖池赢的钱
smallGameWinCoin int64 //本局小游戏赢的钱
betLines []int64 //下注的选线
totalPriceBonus int64 //小游戏得分
bonusTimerHandle timer.TimerHandle //托管handle
currentLogId string //爆奖玩家logid
leavetime int32 //用户离开时间
bonusStage int32 //小游戏所处阶段 1选金额 2选倍率
bonusStartTime int64 //小游戏阶段开始时间
bonusOpRecord []int32 //小游戏操作记录
bonusGame *easterisland.EasterIslandBonusGameInfo //小游戏
bonusX []int32 //小游戏倍率选项
billedData *easterisland.GameBilledData
DebugGame bool //测试
TestNum int
}
// 玩家初始化
func (this *EasterIslandPlayerData) init(s *base.Scene) {
this.Clean()
this.score = 0
this.freeTimes = 0
//this.RollGameType = &model.EasterIslandType{}
this.RollGameType = &GameResultLog{}
this.RollGameType.BaseResult = &model.SlotBaseResultType{}
this.enterGameCoin = this.Coin
this.currentLogId = ""
this.billedData = &easterisland.GameBilledData{}
this.DebugGame = true
this.TestNum = 0
// 加载玩家游戏数据
if this.GDatas == nil {
this.GDatas = make(map[string]*model.PlayerGameInfo)
}
if d, exist := this.GDatas[s.KeyGamefreeId]; exist {
gLen := len(d.Data)
if gLen < EasterIslandIndexMax {
for i := gLen; i < EasterIslandIndexMax; i++ {
d.Data = append(d.Data, 0)
}
}
} else {
pgd := &model.PlayerGameInfo{
Data: make([]int64, EasterIslandIndexMax, EasterIslandIndexMax),
}
this.GDatas[s.KeyGamefreeId] = pgd
}
this.LoadPlayerGameData(s.KeyGamefreeId)
//线条全选
if len(this.betLines) == 0 {
this.betLines = rule.AllBetLines
}
}
// 玩家清理数据
func (this *EasterIslandPlayerData) Clean() {
for i := 0; i < len(this.cards); i++ {
this.cards[i] = -1
}
this.winCoin = 0
this.taxCoin = 0
this.linesWinCoin = 0
this.jackpotWinCoin = 0
this.smallGameWinCoin = 0
this.CleanBonus()
}
// 清理小游戏数据
func (this *EasterIslandPlayerData) CleanBonus() {
this.totalPriceBonus = 0
this.bonusStage = 0
this.bonusTimerHandle = timer.TimerHandle(0)
this.bonusStartTime = 0
this.bonusOpRecord = make([]int32, 0)
this.bonusGame = nil
this.bonusX = nil
}
// 加载玩家游戏数据
func (this *EasterIslandPlayerData) LoadPlayerGameData(gameFreeId string) {
if d, exist := this.GDatas[gameFreeId]; exist {
this.freeTimes = int32(d.Data[EasterIslandFreeTimes])
if this.freeTimes > 0 && len(d.DataEx) != 0 {
json.Unmarshal(d.DataEx, &this.betLines)
}
}
}
// 存储玩家游戏数据
func (this *EasterIslandPlayerData) SavePlayerGameData(gameFreeId string) {
if d, exist := this.GDatas[gameFreeId]; exist {
d.Data[EasterIslandFreeTimes] = int64(this.freeTimes)
d.DataEx, _ = json.Marshal(this.betLines)
}
}
// 黑白名单的限制是否生效
func (this *EasterIslandPlayerData) CheckBlackWriteList(isWin bool) bool {
if isWin && this.BlackLevel > 0 && this.BlackLevel <= 10 {
if rand.Int31n(100) < this.BlackLevel*10 {
return true
}
} else if !isWin && this.WhiteLevel > 0 && this.WhiteLevel <= 10 {
if rand.Int31n(100) < this.WhiteLevel*10 {
return true
}
}
return false
}
// 玩家是否是新手
func (this *EasterIslandPlayerData) IsFNovice(keyGameId string) {
if f, ok := this.IsFoolPlayer[keyGameId]; ok {
if !f {
return
}
} else {
this.IsFoolPlayer[keyGameId] = true
return
}
if data, ok := this.GDatas[keyGameId]; ok {
if data.Statics.GameTimes < 100 && data.Statics.TotalOut-data.Statics.TotalIn <= 2000000 {
return
}
this.IsFoolPlayer[keyGameId] = false
}
}

View File

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

View File

@ -0,0 +1,958 @@
package easterisland
import (
"fmt"
"math"
"math/rand"
"os"
"strconv"
"sync"
"time"
"mongo.games.com/goserver/core"
"mongo.games.com/goserver/core/basic"
"mongo.games.com/goserver/core/logger"
"mongo.games.com/goserver/core/task"
"mongo.games.com/goserver/core/timer"
"mongo.games.com/game/common"
rule "mongo.games.com/game/gamerule/easterisland"
"mongo.games.com/game/gamesrv/base"
"mongo.games.com/game/model"
"mongo.games.com/game/proto"
"mongo.games.com/game/protocol/easterisland"
"mongo.games.com/game/protocol/server"
)
////////////////////////////////////////////////////////////////////////////////
//复活岛
////////////////////////////////////////////////////////////////////////////////
// 房间内主要逻辑
var ScenePolicyEasterIslandSington = &ScenePolicyEasterIsland{}
type ScenePolicyEasterIsland struct {
base.BaseScenePolicy
states [EasterIslandSceneStateMax]base.SceneState
}
// 创建场景扩展数据
func (this *ScenePolicyEasterIsland) CreateSceneExData(s *base.Scene) interface{} {
sceneEx := NewEasterIslandSceneData(s)
if sceneEx != nil {
if sceneEx.init() {
s.ExtraData = sceneEx
}
}
return sceneEx
}
// 创建玩家扩展数据
func (this *ScenePolicyEasterIsland) CreatePlayerExData(s *base.Scene, p *base.Player) interface{} {
playerEx := &EasterIslandPlayerData{Player: p}
if playerEx != nil {
p.ExtraData = playerEx
}
return playerEx
}
// 场景开启事件
func (this *ScenePolicyEasterIsland) OnStart(s *base.Scene) {
logger.Logger.Trace("(this *ScenePolicyEasterIsland) OnStart, sceneId=", s.SceneId)
sceneEx := NewEasterIslandSceneData(s)
if sceneEx != nil {
if sceneEx.init() {
s.ExtraData = sceneEx
s.ChangeSceneState(EasterIslandSceneStateStart) //改变当前的玩家状态
}
}
}
// 场景关闭事件
func (this *ScenePolicyEasterIsland) OnStop(s *base.Scene) {
logger.Logger.Trace("(this *ScenePolicyEasterIsland) OnStop , sceneId=", s.SceneId)
if sceneEx, ok := s.ExtraData.(*EasterIslandSceneData); ok {
sceneEx.SaveData(true)
}
}
// 场景心跳事件
func (this *ScenePolicyEasterIsland) OnTick(s *base.Scene) {
if s == nil {
return
}
if s.SceneState != nil {
s.SceneState.OnTick(s)
}
}
// 玩家进入事件
func (this *ScenePolicyEasterIsland) OnPlayerEnter(s *base.Scene, p *base.Player) {
if s == nil || p == nil {
return
}
logger.Logger.Trace("(this *ScenePolicyEasterIsland) OnPlayerEnter, sceneId=", s.SceneId, " player=", p.SnId)
if sceneEx, ok := s.ExtraData.(*EasterIslandSceneData); ok {
playerEx := &EasterIslandPlayerData{Player: p}
playerEx.init(s) // 玩家当前信息初始化
playerEx.score = sceneEx.DbGameFree.GetBaseScore() // 底注
sceneEx.players[p.SnId] = playerEx
p.ExtraData = playerEx
EasterIslandSendRoomInfo(s, p, sceneEx, playerEx, nil)
s.FirePlayerEvent(p, base.PlayerEventEnter, nil) //回调会调取 onPlayerEvent事件
}
}
// 玩家离开事件
func (this *ScenePolicyEasterIsland) OnPlayerLeave(s *base.Scene, p *base.Player, reason int) {
if s == nil || p == nil {
return
}
logger.Logger.Trace("(this *ScenePolicyEasterIsland) OnPlayerLeave, sceneId=", s.SceneId, " player=", p.SnId)
if sceneEx, ok := s.ExtraData.(*EasterIslandSceneData); ok {
if this.CanChangeCoinScene(s, p) {
if playerEx, ok := p.ExtraData.(*EasterIslandPlayerData); ok {
playerEx.SavePlayerGameData(s.KeyGamefreeId)
}
sceneEx.OnPlayerLeave(p, reason)
s.FirePlayerEvent(p, base.PlayerEventLeave, []int64{int64(reason)})
}
}
}
// 玩家掉线
func (this *ScenePolicyEasterIsland) OnPlayerDropLine(s *base.Scene, p *base.Player) {
if s == nil || p == nil {
return
}
logger.Logger.Trace("(this *ScenePolicyEasterIsland) OnPlayerDropLine, sceneId=", s.SceneId, " player=", p.SnId)
s.FirePlayerEvent(p, base.PlayerEventDropLine, nil)
if sceneEx, ok := s.ExtraData.(*EasterIslandSceneData); ok {
if sceneEx.Gaming {
return
}
}
}
// 玩家重连
func (this *ScenePolicyEasterIsland) OnPlayerRehold(s *base.Scene, p *base.Player) {
if s == nil || p == nil {
return
}
logger.Logger.Trace("(this *ScenePolicyEasterIsland) OnPlayerRehold, sceneId=", s.SceneId, " player=", p.Name)
//if sceneEx, ok := s.ExtraData.(*EasterIslandSceneData); ok {
// if playerEx, ok := p.ExtraData.(*EasterIslandPlayerData); ok {
//发送房间信息给自己
//EasterIslandSendRoomInfo(s, p, sceneEx, playerEx)
s.FirePlayerEvent(p, base.PlayerEventRehold, nil)
//}
//}
}
// 玩家重连
func (this *ScenePolicyEasterIsland) OnPlayerReturn(s *base.Scene, p *base.Player) {
if s == nil || p == nil {
return
}
logger.Logger.Trace("(this *ScenePolicyEasterIsland) OnPlayerReturn, sceneId=", s.SceneId, " player=", p.Name)
if sceneEx, ok := s.ExtraData.(*EasterIslandSceneData); ok {
if playerEx, ok := p.ExtraData.(*EasterIslandPlayerData); ok {
//发送房间信息给自己
EasterIslandSendRoomInfo(s, p, sceneEx, playerEx, playerEx.billedData)
s.FirePlayerEvent(p, base.PlayerEventReturn, nil)
}
}
}
// 玩家操作
func (this *ScenePolicyEasterIsland) OnPlayerOp(s *base.Scene, p *base.Player, opcode int, params []int64) bool {
if s == nil || p == nil {
return false
}
if s.SceneState != nil {
return s.SceneState.OnPlayerOp(s, p, opcode, params)
}
return true
}
// 玩家事件
func (this *ScenePolicyEasterIsland) OnPlayerEvent(s *base.Scene, p *base.Player, evtcode int, params []int64) {
if s == nil || p == nil {
return
}
if s.SceneState != nil {
s.SceneState.OnPlayerEvent(s, p, evtcode, params)
}
}
// 是否完成了整个牌局
func (this *ScenePolicyEasterIsland) IsCompleted(s *base.Scene) bool { return false }
// 是否可以强制开始
func (this *ScenePolicyEasterIsland) IsCanForceStart(s *base.Scene) bool { return true }
// 当前状态能否换桌
func (this *ScenePolicyEasterIsland) CanChangeCoinScene(s *base.Scene, p *base.Player) bool {
if s == nil || p == nil {
return true
}
if s.SceneState != nil {
return s.SceneState.CanChangeCoinScene(s, p)
}
return true
}
func (this *ScenePolicyEasterIsland) RegisteSceneState(state base.SceneState) {
if state == nil {
return
}
stateid := state.GetState()
if stateid < 0 || stateid >= EasterIslandSceneStateMax {
return
}
this.states[stateid] = state
}
func (this *ScenePolicyEasterIsland) GetSceneState(s *base.Scene, stateid int) base.SceneState {
if stateid >= 0 && stateid < EasterIslandSceneStateMax {
return ScenePolicyEasterIslandSington.states[stateid]
}
return nil
}
func (this *ScenePolicyEasterIsland) GetJackPotVal(s *base.Scene) int64 {
if sceneEx, ok := s.ExtraData.(*EasterIslandSceneData); ok {
if sceneEx.lastJackpotValue != sceneEx.jackpot.VirtualJK {
return sceneEx.jackpot.VirtualJK
}
}
return 0
}
func EasterIslandSendRoomInfo(s *base.Scene, p *base.Player, sceneEx *EasterIslandSceneData, playerEx *EasterIslandPlayerData, data *easterisland.GameBilledData) {
logger.Logger.Trace("-------------------发送房间消息 ", s.RoomId, p.SnId)
pack := &easterisland.SCEasterIslandRoomInfo{
RoomId: proto.Int(s.SceneId),
Creator: proto.Int32(s.Creator),
GameId: proto.Int(s.GameId),
RoomMode: proto.Int(s.GameMode),
Params: s.Params,
State: proto.Int(s.SceneState.GetState()),
Jackpot: proto.Int64(sceneEx.jackpot.VirtualJK),
GameFreeId: proto.Int32(s.DbGameFree.Id),
BilledData: data,
}
if playerEx != nil {
pd := &easterisland.EasterIslandPlayerData{
SnId: proto.Int32(playerEx.SnId),
Name: proto.String(playerEx.Name),
Head: proto.Int32(playerEx.Head),
Sex: proto.Int32(playerEx.Sex),
Coin: proto.Int64(playerEx.Coin),
HeadOutLine: proto.Int32(playerEx.HeadOutLine),
VIP: proto.Int32(playerEx.VIP),
}
pack.Players = append(pack.Players, pd)
//for _, value := range playerEx.cards {
// pack.Cards = append(pack.Cards, int32(value))
//}
pack.BetLines = playerEx.betLines
pack.FreeTimes = proto.Int32(playerEx.freeTimes)
pack.Chip = proto.Int32(s.DbGameFree.BaseScore)
pack.SpinID = proto.Int64(playerEx.spinID)
if playerEx.totalPriceBonus > 0 {
switch playerEx.bonusStage {
case 0:
pack.ParamsEx = append(pack.ParamsEx, playerEx.bonusStage)
case 1:
if time.Now().Unix()-playerEx.bonusStartTime >= EasterIslandBonusGameStageTimeout*2 {
playerEx.CleanBonus()
} else if time.Now().Unix()-playerEx.bonusStartTime >= EasterIslandBonusGameStageTimeout {
playerEx.bonusStage = 2
playerEx.bonusStartTime += EasterIslandBonusGameStageTimeout
pack.ParamsEx = append(pack.ParamsEx, playerEx.bonusStage)
leftTime := playerEx.bonusStartTime + EasterIslandBonusGameStageTimeout + 2 - time.Now().Unix()
pack.ParamsEx = append(pack.ParamsEx, int32(leftTime))
} else {
pack.ParamsEx = append(pack.ParamsEx, playerEx.bonusStage)
leftTime := playerEx.bonusStartTime + EasterIslandBonusGameStageTimeout + 2 - time.Now().Unix()
pack.ParamsEx = append(pack.ParamsEx, int32(leftTime))
pack.ParamsEx = append(pack.ParamsEx, playerEx.bonusOpRecord...)
}
case 2:
if time.Now().Unix()-playerEx.bonusStartTime >= EasterIslandBonusGameStageTimeout {
playerEx.CleanBonus()
} else {
pack.ParamsEx = append(pack.ParamsEx, playerEx.bonusStage)
leftTime := playerEx.bonusStartTime + EasterIslandBonusGameStageTimeout + 2 - time.Now().Unix()
pack.ParamsEx = append(pack.ParamsEx, int32(leftTime))
}
}
}
if playerEx.totalPriceBonus > 0 {
pack.TotalPriceBonus = proto.Int64(playerEx.totalPriceBonus)
pack.BonusGame = playerEx.bonusGame
pack.BonusX = playerEx.bonusX
}
}
proto.SetDefaults(pack)
p.SendToClient(int(easterisland.EasterIslandPacketID_PACKET_SC_EASTERISLAND_ROOMINFO), pack)
}
type SceneStateEasterIslandStart struct {
}
// 获取当前场景状态
func (this *SceneStateEasterIslandStart) GetState() int { return EasterIslandSceneStateStart }
// 是否可以切换状态到
func (this *SceneStateEasterIslandStart) CanChangeTo(s base.SceneState) bool { return true }
// 当前状态能否换桌
func (this *SceneStateEasterIslandStart) CanChangeCoinScene(s *base.Scene, p *base.Player) bool {
return true
}
func (this *SceneStateEasterIslandStart) GetTimeout(s *base.Scene) int { return 0 }
func (this *SceneStateEasterIslandStart) OnEnter(s *base.Scene) {
if sceneEx, ok := s.ExtraData.(*EasterIslandSceneData); ok {
logger.Logger.Tracef("(this *Scene) [%v] 场景状态进入 %v", s.SceneId, len(sceneEx.players))
sceneEx.StateStartTime = time.Now()
pack := &easterisland.SCEasterIslandRoomState{
State: proto.Int(this.GetState()),
}
proto.SetDefaults(pack)
s.Broadcast(int(easterisland.EasterIslandPacketID_PACKET_SC_EASTERISLAND_ROOMSTATE), pack, 0)
}
}
func (this *SceneStateEasterIslandStart) OnLeave(s *base.Scene) {}
func (this *SceneStateEasterIslandStart) OnTick(s *base.Scene) {
if sceneEx, ok := s.ExtraData.(*EasterIslandSceneData); ok {
sceneEx.AIAddJackPot()
sceneEx.AIBurstJackPot()
sceneEx.KickPlayerByTime()
}
}
func (this *SceneStateEasterIslandStart) OnPlayerOp(s *base.Scene, p *base.Player, opcode int, params []int64) bool {
playerEx, ok := p.ExtraData.(*EasterIslandPlayerData)
if !ok {
return false
}
sceneEx, ok := s.ExtraData.(*EasterIslandSceneData)
if !ok {
return false
}
if sceneEx.CheckNeedDestroy() && playerEx.freeTimes <= 0 {
//离开有统计
sceneEx.PlayerLeave(playerEx.Player, common.PlayerLeaveReason_OnDestroy, true)
return false
}
switch opcode {
case EasterIslandPlayerOpStart: //开始
//if !easterIslandBenchTest {
// easterIslandBenchTest = true
// for i := 0; i < 10; i++ {
// //this.BenchTest(s, p)
// this.WinTargetBenchTest(s, p)
// }
// return true
//}
//参数是否合法
//params 参数0底注后面跟客户端选择的线n条线(1<=n<=25)客户端线是从1开始算起1~25条线
if len(params) < 2 || len(params) > rule.LINENUM+1 {
this.OnPlayerSToCOp(s, p, playerEx.Pos, opcode, easterisland.OpResultCode_OPRC_Error, params)
return false
}
//先做底注校验
if sceneEx.DbGameFree.GetBaseScore() != int32(params[0]) {
this.OnPlayerSToCOp(s, p, playerEx.Pos, opcode, easterisland.OpResultCode_OPRC_Error, params)
return false
}
playerEx.score = int32(params[0]) // 单线押注数
// 小游戏未结束 不能进行下一次旋转
if playerEx.totalPriceBonus > 0 {
this.OnPlayerSToCOp(s, p, playerEx.Pos, opcode, easterisland.OpResultCode_OPRC_Error, params)
return false
}
//判断线条是否重复,是否合法
lineFlag := make(map[int64]bool)
lineParams := make([]int64, 0)
for i := 1; i < len(params); i++ {
lineNum := params[i]
if lineNum >= 1 && lineNum <= int64(rule.LINENUM) && !lineFlag[lineNum] {
lineParams = append(lineParams, lineNum)
lineFlag[lineNum] = true
} else {
this.OnPlayerSToCOp(s, p, playerEx.Pos, opcode, easterisland.OpResultCode_OPRC_Error, params)
return false
}
}
//没有选线参数
if len(lineParams) == 0 {
this.OnPlayerSToCOp(s, p, playerEx.Pos, opcode, easterisland.OpResultCode_OPRC_Error, params)
return false
}
//获取总投注金额(所有线的总投注) | 校验玩家余额是否足够
totalBetValue := (int64(len(lineParams))) * params[0]
if playerEx.freeTimes <= 0 && totalBetValue > playerEx.Coin {
this.OnPlayerSToCOp(s, p, playerEx.Pos, opcode, easterisland.OpResultCode_OPRC_CoinNotEnough, params)
return false
} else if playerEx.freeTimes <= 0 && int64(sceneEx.DbGameFree.GetBetLimit()) > playerEx.Coin { //押注限制
this.OnPlayerSToCOp(s, p, playerEx.Pos, opcode, easterisland.OpResultCode_OPRC_CoinNotEnough, params)
return false
}
p.LastOPTimer = time.Now()
sceneEx.GameNowTime = time.Now()
sceneEx.NumOfGames++
p.GameTimes++
//获取当前水池的上下文环境
sceneEx.CpCtx = base.CoinPoolMgr.GetCoinPoolCtx(sceneEx.Platform, sceneEx.GetGameFreeId(), sceneEx.GroupId)
taxRate := sceneEx.DbGameFree.GetTaxRate()
if taxRate < 0 || taxRate > 10000 {
logger.Logger.Warnf("EasterIslandErrorTaxRate [%v][%v][%v][%v]", sceneEx.GetGameFreeId(), playerEx.SnId, playerEx.spinID, taxRate)
taxRate = 500
}
coinPoolSetting := base.CoinPoolMgr.GetCoinPoolSetting(sceneEx.Platform, sceneEx.GetGameFreeId(), sceneEx.GroupId)
ctroRate := 500 //调节赔率 暗税系数
logger.Logger.Tracef("EasterIslandRates [%v][%v][%v][%v][%v]", sceneEx.GetGameFreeId(), playerEx.SnId, playerEx.spinID, taxRate, ctroRate)
playerEx.IsFNovice(sceneEx.KeyGameId)
isFoolPlayer := false
var gamePoolCoin int64
//if isFoolPlayer {
// gamePoolCoin = base.CoinPoolMgr.GetNoviceCoinPool(sceneEx.GetGameFreeId(), sceneEx.Platform, sceneEx.GroupId) // 当前水池金额
//} else {
gamePoolCoin = base.CoinPoolMgr.GetCoin(sceneEx.GetGameFreeId(), sceneEx.Platform, sceneEx.GroupId) // 当前水池金额
//}
prizeFund := gamePoolCoin - sceneEx.jackpot.VirtualJK // 除去奖池的水池剩余金额
jackpotParams := sceneEx.DbGameFree.GetJackpot() // 奖池参数
var jackpotInit = int64(jackpotParams[rule.EL_JACKPOT_InitJackpot] * sceneEx.DbGameFree.GetBaseScore()) //奖池初始值
var jackpotFundAdd, prizeFundAdd int64
if playerEx.freeTimes <= 0 { //正常模式才能记录用户的押注变化,免费模式不能改变押注
playerEx.betLines = lineParams // 选线记录
jackpotFundAdd = int64(math.Floor(float64(totalBetValue) * (float64(ctroRate) / 10000.0))) //奖池要增加的金额
prizeFundAdd = totalBetValue - jackpotFundAdd //现金池增加的金额
//扣除投注金币
p.AddCoin(-totalBetValue, common.GainWay_HundredSceneLost, base.SyncFlag_ToClient, "system", s.GetSceneName())
if !p.IsRob && !sceneEx.Testing {
// 推送金币
sceneEx.PushCoinPool(prizeFundAdd, isFoolPlayer)
}
////统计参与游戏次数
//if !sceneEx.Testing && !playerEx.IsRob {
// pack := &server.GWSceneEnd{
// GameFreeId: proto.Int32(sceneEx.DbGameFree.GetId()),
// Players: []*server.PlayerCtx{&server.PlayerCtx{SnId: proto.Int32(playerEx.SnId), Coin: proto.Int64(playerEx.Coin)}},
// }
// proto.SetDefaults(pack)
// sceneEx.SendToWorld(int(server.SSPacketID_PACKET_GW_SCENEEND), pack)
//}
} else {
totalBetValue = 0
}
writeBlackTryTimes := 0
WriteBlack:
slotData := make([]int, 0)
var spinRes EasterIslandSpinResult
var slotDataIsOk bool
for {
var symbolType rule.Symbol
if gamePoolCoin < int64(coinPoolSetting.GetLowerLimit()) { // userInfo.prizeFund < limit * roomId
symbolType = rule.SYMBOL1
} else {
symbolType = rule.SYMBOL2
}
slotData, _ = rule.GenerateSlotsData_v2(symbolType)
spinRes = sceneEx.CalcLinePrize(slotData, playerEx.betLines, params[0])
// 免费次数时 不允许爆奖
if playerEx.freeTimes > 0 && spinRes.IsJackpot {
break
}
if spinRes.JackpotCnt > 1 {
break
}
if spinRes.IsJackpot {
if sceneEx.jackpot.Small < sceneEx.jackpot.VirtualJK {
continue
}
}
spinCondition := prizeFund + prizeFundAdd - (spinRes.TotalPrizeLine + spinRes.BonusGame.GetTotalPrizeValue() + spinRes.TotalPrizeJackpot)
spinCondition += jackpotFundAdd + sceneEx.jackpot.VirtualJK - jackpotInit
win := spinRes.TotalPrizeLine + spinRes.BonusGame.GetTotalPrizeValue() + spinRes.TotalPrizeJackpot
// 现金池不足时 重新发牌
if spinCondition < 0 && win > totalBetValue {
if !spinRes.IsJackpot { // 非爆奖 水池不足 不再进行黑白名单调控
writeBlackTryTimes = 999
}
break
}
// 非爆奖时 不允许赢取太大的奖励
var limitBigWin int64 = 50
if spinCondition < int64(coinPoolSetting.GetLowerLimit()) { //现金池不足时
limitBigWin = int64(jackpotParams[rule.EL_JACKPOT_LIMITWIN_PRIZELOW])
} else {
limitBigWin = int64(jackpotParams[rule.EL_JACKPOT_LIMITWIN_PRIZEHIGH])
}
if totalBetValue > 0 && !spinRes.IsJackpot && spinRes.TotalPrizeLine+spinRes.BonusGame.GetTotalPrizeValue() > totalBetValue*limitBigWin {
break
}
slotDataIsOk = true
break
}
if !slotDataIsOk {
slotData = rule.MissData[rand.Intn(len(rule.MissData))]
spinRes = sceneEx.CalcLinePrize(slotData, playerEx.betLines, params[0])
}
// 黑白名单调控 防止异常循环,添加上限次数
if writeBlackTryTimes < 100 && playerEx.CheckBlackWriteList(spinRes.TotalPrizeLine+spinRes.TotalPrizeJackpot+spinRes.BonusGame.GetTotalPrizeValue() > totalBetValue) {
writeBlackTryTimes++
goto WriteBlack
} else if writeBlackTryTimes >= 100 && writeBlackTryTimes != 999 {
logger.Logger.Warnf("EasterIslandWriteBlackTryTimesOver [%v][%v][%v][%v][%v]", sceneEx.GetGameFreeId(), playerEx.SnId, gamePoolCoin, playerEx.BlackLevel, playerEx.WhiteLevel)
}
// 奖池水池处理
if spinRes.IsJackpot {
sceneEx.jackpot.Small -= sceneEx.jackpot.VirtualJK
if sceneEx.jackpot.Small < 0 {
sceneEx.jackpot.Small = 0
}
sceneEx.jackpot.VirtualJK = jackpotInit
} else {
sceneEx.jackpot.Small += jackpotFundAdd
sceneEx.jackpot.VirtualJK += jackpotFundAdd
}
// 玩家赢钱
totalWinScore := spinRes.TotalPrizeLine + spinRes.TotalPrizeJackpot
if totalWinScore > 0 || len(spinRes.BonusX) > 0 {
p.AddCoin(totalWinScore+spinRes.BonusGame.GetTotalPrizeValue(), common.GainWay_HundredSceneWin, 0, "system", s.GetSceneName())
if !p.IsRob && !sceneEx.Testing {
sceneEx.PopCoinPool(totalWinScore+spinRes.BonusGame.GetTotalPrizeValue()+spinRes.TotalTaxScore, isFoolPlayer)
}
playerEx.taxCoin = spinRes.TotalTaxScore
playerEx.AddServiceFee(playerEx.taxCoin)
}
p.StaticsLaba(sceneEx.KeyGameId, sceneEx.KeyGamefreeId, totalBetValue, totalWinScore+spinRes.BonusGame.GetTotalPrizeValue()+spinRes.TotalTaxScore)
this.OnPlayerSToCOp(s, p, playerEx.Pos, opcode, easterisland.OpResultCode_OPRC_Sucess, append(params[:1], playerEx.betLines...))
var isFreeFlag bool
if playerEx.freeTimes > 0 {
playerEx.freeTimes--
isFreeFlag = true
}
playerEx.freeTimes += spinRes.AddFreeTimes
rule.SpinID++
playerEx.spinID = rule.SpinID
playerEx.cards = spinRes.SlotsData
playerEx.winCoin = spinRes.TotalPrizeLine + spinRes.TotalPrizeJackpot + spinRes.BonusGame.GetTotalPrizeValue() + playerEx.taxCoin
playerEx.linesWinCoin = spinRes.TotalPrizeLine
playerEx.jackpotWinCoin = spinRes.TotalPrizeJackpot
playerEx.smallGameWinCoin = spinRes.BonusGame.GetTotalPrizeValue()
playerEx.CurrentBet = totalBetValue
playerEx.CurrentTax = playerEx.taxCoin
// 小游戏超时处理
if len(spinRes.BonusX) > 0 {
playerEx.totalPriceBonus = spinRes.BonusGame.GetTotalPrizeValue()
playerEx.bonusGame = &spinRes.BonusGame
playerEx.bonusX = spinRes.BonusX
logger.Logger.Tracef("BonusGame Start [%v][%v][%v][%v]", sceneEx.GetGameFreeId(), playerEx.SnId, playerEx.spinID, playerEx.totalPriceBonus)
}
playerEx.billedData = &easterisland.GameBilledData{
SpinID: proto.Int64(playerEx.spinID),
SlotsData: spinRes.SlotsData,
AddFreeSpin: proto.Int32(spinRes.AddFreeTimes),
IsJackpot: proto.Bool(spinRes.IsJackpot),
PrizeLines: spinRes.LinesInfo,
TotalPrizeValue: proto.Int64(spinRes.TotalPrizeLine + spinRes.TotalPrizeJackpot),
TotalPaylinePrizeValue: proto.Int64(spinRes.TotalPrizeLine),
TotalJackpotValue: proto.Int64(spinRes.TotalPrizeJackpot),
Balance: proto.Int64(playerEx.Coin - spinRes.BonusGame.GetTotalPrizeValue()),
FreeSpins: proto.Int32(playerEx.freeTimes),
Jackpot: proto.Int64(sceneEx.jackpot.VirtualJK),
BonusX: spinRes.BonusX,
BonusGame: &spinRes.BonusGame,
}
pack := &easterisland.SCEasterIslandGameBilled{
BilledData: playerEx.billedData,
}
proto.SetDefaults(pack)
logger.Logger.Infof("EasterIslandPlayerOpStart %v", pack)
p.SendToClient(int(easterisland.EasterIslandPacketID_PACKET_SC_EASTERISLAND_GAMEBILLED), pack)
// 记录本次操作
playerEx.RollGameType.BaseResult.WinTotal = pack.BilledData.GetTotalPrizeValue() + pack.BilledData.GetBonusGame().GetTotalPrizeValue()
playerEx.RollGameType.BaseResult.IsFree = isFreeFlag
playerEx.RollGameType.BaseResult.WinSmallGame = pack.BilledData.BonusGame.GetTotalPrizeValue()
playerEx.RollGameType.BaseResult.AllWinNum = int32(len(pack.BilledData.PrizeLines))
playerEx.RollGameType.BaseResult.WinRate = spinRes.TotalWinRate
playerEx.RollGameType.BaseResult.Cards = pack.BilledData.GetSlotsData()
playerEx.RollGameType.BaseResult.WinLineScore = pack.BilledData.TotalPaylinePrizeValue
playerEx.RollGameType.WinLines = spinRes.WinLines
playerEx.RollGameType.BaseResult.WinJackpot = pack.BilledData.GetTotalJackpotValue()
playerEx.RollGameType.BaseResult.IsFoolPlayer = isFoolPlayer
EasterIslandCheckAndSaveLog(sceneEx, playerEx)
// 广播奖池
if totalBetValue == 0 && !spinRes.IsJackpot { // 没改变奖池
return true
}
// 添加进开奖记录里面
if spinRes.IsJackpot {
sceneEx.RecordBurstLog(playerEx.Name, pack.BilledData.GetTotalJackpotValue(), playerEx.CurrentBet)
}
logger.Logger.Tracef("---easterisland---当前奖池:真人[%v] 虚拟[%v]", sceneEx.jackpot.Small, sceneEx.jackpot.VirtualJK)
case EasterIslandBurstHistory:
sceneEx.BurstHistory(playerEx)
case EasterIslandPlayerHistory:
task.New(nil, task.CallableWrapper(func(o *basic.Object) interface{} {
spinid := strconv.FormatInt(int64(playerEx.SnId), 10)
gpl := model.GetPlayerListByHallEx(p.SnId, p.Platform, 0, 80, 0, 0, 0, s.DbGameFree.GetGameClass(), s.GameId)
pack := &easterisland.SCEasterIslandPlayerHistory{}
for _, v := range gpl.Data {
//if v.GameDetailedLogId == "" {
// logger.Logger.Error("EasterIslandPlayerHistory GameDetailedLogId is nil")
// break
//}
//gdl := model.GetPlayerHistory(p.Platform, v.GameDetailedLogId)
//if gdl == nil {
// logger.Logger.Error("EasterIslandPlayerHistory gdl is nil")
// continue
//}
//data, err := UnMarshalEasterIslandGameNote(gdl.GameDetailedNote)
//if err != nil {
// logger.Logger.Errorf("UnMarshalEasterIslandGameNote error:%v", err)
// continue
//}
//if gnd, ok := data.(*GameResultLog); ok {
//
//}
player := &easterisland.EasterIslandPlayerHistoryInfo{
SpinID: proto.String(spinid),
CreatedTime: proto.Int64(int64(v.Ts)),
TotalBetValue: proto.Int64(v.BetAmount),
TotalPriceValue: proto.Int64(v.WinTotal),
IsFree: proto.Bool(v.IsFree),
TotalBonusValue: proto.Int64(v.WinSmallGame),
}
pack.PlayerHistory = append(pack.PlayerHistory, player)
}
proto.SetDefaults(pack)
logger.Logger.Info("EasterIslandPlayerHistory: ", pack)
return pack
}), task.CompleteNotifyWrapper(func(data interface{}, t task.Task) {
if data == nil {
logger.Logger.Error("EasterIslandPlayerHistory data is nil")
return
}
p.SendToClient(int(easterisland.EasterIslandPacketID_PACKET_SC_EASTERISLAND_PLAYERHISTORY), data)
}), "CSGetEasterIslandPlayerHistoryHandler").Start()
case EasterIslandBonusGame:
//参数是否合法 params 参数0 spinID
if len(params) < 1 {
this.OnPlayerSToCOp(s, p, playerEx.Pos, opcode, easterisland.OpResultCode_OPRC_Error, params)
return false
}
if playerEx.spinID != params[0] || playerEx.totalPriceBonus <= 0 {
this.OnPlayerSToCOp(s, p, playerEx.Pos, opcode, easterisland.OpResultCode_OPRC_Error, params)
return false
}
if playerEx.bonusTimerHandle != timer.TimerHandle(0) {
timer.StopTimer(playerEx.bonusTimerHandle)
playerEx.bonusTimerHandle = timer.TimerHandle(0)
}
logger.Logger.Tracef("BonusGame Start [%v][%v][%v][%v]", sceneEx.GetGameFreeId(), playerEx.SnId, playerEx.spinID, playerEx.totalPriceBonus)
this.OnPlayerSToCOp(s, p, playerEx.Pos, opcode, easterisland.OpResultCode_OPRC_Sucess, []int64{playerEx.totalPriceBonus, playerEx.Coin})
playerEx.CleanBonus()
case EasterIslandBonusGameRecord:
// params[0] 小游戏阶段: 0 小游戏动画开始 1 小游戏界面1 2 切换小游戏界面2
// params[1] 小游戏界面1时选择奖项的界面位置信息
if len(params) < 1 || params[0] < 0 || params[0] > 2 || playerEx.totalPriceBonus <= 0 || (params[0] == 1 && len(params) < 2) {
this.OnPlayerSToCOp(s, p, playerEx.Pos, opcode, easterisland.OpResultCode_OPRC_Error, params)
return false
}
if params[0] == 0 {
if playerEx.bonusStage > 0 {
this.OnPlayerSToCOp(s, p, playerEx.Pos, opcode, easterisland.OpResultCode_OPRC_Error, params)
return false
}
playerEx.bonusStage = 1
playerEx.bonusStartTime = time.Now().Unix()
} else if params[0] == 2 {
if playerEx.bonusStage != 1 {
this.OnPlayerSToCOp(s, p, playerEx.Pos, opcode, easterisland.OpResultCode_OPRC_Error, params)
return false
}
playerEx.bonusStage = 2
playerEx.bonusStartTime = time.Now().Unix()
} else if params[0] == 1 {
if params[1] < 0 {
this.OnPlayerSToCOp(s, p, playerEx.Pos, opcode, easterisland.OpResultCode_OPRC_Error, params)
return false
} else if playerEx.bonusGame != nil && len(playerEx.bonusOpRecord) >= len(playerEx.bonusGame.BonusData) {
this.OnPlayerSToCOp(s, p, playerEx.Pos, opcode, easterisland.OpResultCode_OPRC_Error, params)
return false
}
playerEx.bonusOpRecord = append(playerEx.bonusOpRecord, int32(params[1]))
}
this.OnPlayerSToCOp(s, p, playerEx.Pos, opcode, easterisland.OpResultCode_OPRC_Sucess, params)
}
return true
}
func (this *SceneStateEasterIslandStart) OnPlayerEvent(s *base.Scene, p *base.Player, evtcode int, params []int64) {
}
// 发送玩家操作情况
func (this *SceneStateEasterIslandStart) OnPlayerSToCOp(s *base.Scene, p *base.Player, pos int, opcode int,
opRetCode easterisland.OpResultCode, params []int64) {
pack := &easterisland.SCEasterIslandOp{
SnId: proto.Int32(p.SnId),
OpCode: proto.Int(opcode),
OpRetCode: opRetCode,
Params: params,
}
proto.SetDefaults(pack)
p.SendToClient(int(easterisland.EasterIslandPacketID_PACKET_SC_EASTERISLAND_PLAYEROP), pack)
}
var easterIslandBenchTest bool
var easterIslandBenchTestTimes int
func (this *SceneStateEasterIslandStart) BenchTest(s *base.Scene, p *base.Player) {
const BENCH_CNT = 10000
setting := base.CoinPoolMgr.GetCoinPoolSetting(s.Platform, s.GetGameFreeId(), s.GroupId)
oldPoolCoin := base.CoinPoolMgr.GetCoin(s.GetGameFreeId(), s.Platform, s.GroupId)
if easterIslandBenchTestTimes == 0 {
defaultVal := int64(setting.GetLowerLimit())
if oldPoolCoin != defaultVal {
base.CoinPoolMgr.PushCoin(s.GetGameFreeId(), s.GroupId, s.Platform, defaultVal-oldPoolCoin)
}
}
easterIslandBenchTestTimes++
fileName := fmt.Sprintf("easterisland-%v-%d.csv", p.SnId, easterIslandBenchTestTimes)
file, err := os.OpenFile(fileName, os.O_RDWR|os.O_CREATE|os.O_APPEND, os.ModePerm)
defer file.Close()
if err != nil {
file, err = os.Create(fileName)
if err != nil {
return
}
}
file.WriteString("玩家id,当前水位,之前余额,之后余额,投入,产出,税收,小游戏,中线倍数,中线数,剩余免费次数\r\n")
oldCoin := p.Coin
p.Coin = 100000000
if playerEx, ok := p.ExtraData.(*EasterIslandPlayerData); ok {
for i := 0; i < BENCH_CNT; i++ {
startCoin := p.Coin
freeTimes := playerEx.freeTimes
poolCoin := base.CoinPoolMgr.GetCoin(s.GetGameFreeId(), s.Platform, s.GroupId)
playerEx.UnmarkFlag(base.PlayerState_GameBreak)
suc := this.OnPlayerOp(s, p, EasterIslandPlayerOpStart, append([]int64{int64(playerEx.score)}, rule.AllBetLines...))
inCoin := int64(playerEx.RollGameType.BaseResult.TotalBet)
outCoin := playerEx.RollGameType.BaseResult.ChangeCoin + inCoin
taxCoin := playerEx.RollGameType.BaseResult.Tax
str := fmt.Sprintf("%v,%v,%v,%v,%v,%v,%v,%v,%v,%v,%v\r\n", p.SnId, poolCoin, startCoin, p.Coin, inCoin, outCoin, taxCoin,
playerEx.RollGameType.BaseResult.WinSmallGame, playerEx.RollGameType.BaseResult.WinRate, playerEx.RollGameType.BaseResult.AllWinNum, freeTimes)
file.WriteString(str)
if !suc {
break
}
if playerEx.totalPriceBonus > 0 {
this.OnPlayerOp(s, p, EasterIslandBonusGame, []int64{playerEx.spinID})
}
}
}
p.Coin = oldCoin
}
func (this *SceneStateEasterIslandStart) WinTargetBenchTest(s *base.Scene, p *base.Player) {
const BENCH_CNT = 10000
var once = sync.Once{}
once.Do(func() {
setting := base.CoinPoolMgr.GetCoinPoolSetting(s.Platform, s.GetGameFreeId(), s.GroupId)
oldPoolCoin := base.CoinPoolMgr.GetCoin(s.GetGameFreeId(), s.Platform, s.GroupId)
if easterIslandBenchTestTimes == 0 {
defaultVal := int64(setting.GetLowerLimit())
if oldPoolCoin != defaultVal {
base.CoinPoolMgr.PushCoin(s.GetGameFreeId(), s.GroupId, s.Platform, defaultVal-oldPoolCoin)
}
}
})
easterIslandBenchTestTimes++
fileName := fmt.Sprintf("easterisland-%v-%d.csv", p.SnId, easterIslandBenchTestTimes)
file, err := os.OpenFile(fileName, os.O_RDWR|os.O_CREATE|os.O_APPEND, os.ModePerm)
defer file.Close()
if err != nil {
file, err = os.Create(fileName)
if err != nil {
return
}
}
file.WriteString("玩家id,当前水位,之前余额,之后余额,投入,产出,税收,小游戏,中线倍数,中线数,剩余免费次数\r\n")
oldCoin := p.Coin
switch s.DbGameFree.GetSceneType() {
case 1:
p.Coin = 100000
case 2:
p.Coin = 500000
case 3:
p.Coin = 1000000
case 4:
p.Coin = 10000000
default:
p.Coin = 100000
}
var targetCoin = p.Coin + p.Coin/10
if playerEx, ok := p.ExtraData.(*EasterIslandPlayerData); ok {
for i := 0; p.Coin < targetCoin; i++ {
startCoin := p.Coin
freeTimes := playerEx.freeTimes
poolCoin := base.CoinPoolMgr.GetCoin(s.GetGameFreeId(), s.Platform, s.GroupId)
playerEx.UnmarkFlag(base.PlayerState_GameBreak)
suc := this.OnPlayerOp(s, p, EasterIslandPlayerOpStart, append([]int64{int64(playerEx.score)}, rule.AllBetLines...))
inCoin := int64(playerEx.RollGameType.BaseResult.TotalBet)
outCoin := playerEx.RollGameType.BaseResult.ChangeCoin + inCoin
taxCoin := playerEx.RollGameType.BaseResult.Tax
str := fmt.Sprintf("%v,%v,%v,%v,%v,%v,%v,%v,%v,%v,%v\r\n", p.SnId, poolCoin, startCoin, p.Coin, inCoin, outCoin, taxCoin,
playerEx.RollGameType.BaseResult.WinSmallGame, playerEx.RollGameType.BaseResult.WinRate, playerEx.RollGameType.BaseResult.AllWinNum, freeTimes)
file.WriteString(str)
if !suc {
break
}
if playerEx.totalPriceBonus > 0 {
this.OnPlayerOp(s, p, EasterIslandBonusGame, []int64{playerEx.spinID})
}
if i > BENCH_CNT {
break
}
}
}
p.Coin = oldCoin
}
func EasterIslandCheckAndSaveLog(sceneEx *EasterIslandSceneData, playerEx *EasterIslandPlayerData) {
//统计金币变动
//log1
logger.Logger.Trace("EasterIslandCheckAndSaveLog Save ", playerEx.SnId)
//changeCoin := playerEx.Coin - playerEx.StartCoin
changeCoin := playerEx.winCoin - playerEx.taxCoin - playerEx.CurrentBet
startCoin := playerEx.Coin - changeCoin
playerEx.SaveSceneCoinLog(startCoin, changeCoin,
playerEx.Coin, playerEx.CurrentBet, playerEx.taxCoin, playerEx.winCoin, playerEx.jackpotWinCoin, playerEx.smallGameWinCoin)
//log2
playerEx.RollGameType.BaseResult.ChangeCoin = changeCoin
playerEx.RollGameType.BaseResult.BasicBet = sceneEx.DbGameFree.GetBaseScore()
playerEx.RollGameType.BaseResult.RoomId = int32(sceneEx.SceneId)
playerEx.RollGameType.BaseResult.AfterCoin = playerEx.Coin
playerEx.RollGameType.BaseResult.BeforeCoin = startCoin
playerEx.RollGameType.BaseResult.IsFirst = sceneEx.IsPlayerFirst(playerEx.Player)
playerEx.RollGameType.BaseResult.PlayerSnid = playerEx.SnId
playerEx.RollGameType.BaseResult.TotalBet = int32(playerEx.CurrentBet)
playerEx.RollGameType.AllLine = int32(len(playerEx.betLines))
playerEx.RollGameType.BaseResult.FreeTimes = playerEx.freeTimes
playerEx.RollGameType.UserName = playerEx.Name
playerEx.RollGameType.BetLines = playerEx.betLines
playerEx.RollGameType.BaseResult.Tax = playerEx.taxCoin
playerEx.RollGameType.BaseResult.WBLevel = sceneEx.players[playerEx.SnId].WBLevel
if playerEx.score > 0 {
if !playerEx.IsRob {
info, err := model.MarshalGameNoteByROLL(playerEx.RollGameType)
if err == nil {
logid, _ := model.AutoIncGameLogId()
playerEx.currentLogId = logid
sceneEx.SaveGameDetailedLog(logid, info, &base.GameDetailedParam{})
totalin := int64(playerEx.RollGameType.BaseResult.TotalBet)
totalout := playerEx.RollGameType.BaseResult.ChangeCoin + playerEx.taxCoin + totalin
validFlow := totalin + totalout
validBet := common.AbsI64(totalin - totalout)
logParam := &base.SaveGamePlayerListLogParam{
Platform: playerEx.Platform,
Channel: playerEx.Channel,
Promoter: playerEx.BeUnderAgentCode,
PackageTag: playerEx.PackageID,
InviterId: playerEx.InviterId,
LogId: logid,
TotalIn: totalin,
TotalOut: totalout,
TaxCoin: playerEx.taxCoin,
BetAmount: int64(playerEx.RollGameType.BaseResult.TotalBet),
WinAmountNoAnyTax: playerEx.RollGameType.BaseResult.ChangeCoin,
ValidBet: validBet,
ValidFlow: validFlow,
IsFirstGame: sceneEx.IsPlayerFirst(playerEx.Player),
IsFree: playerEx.RollGameType.BaseResult.IsFree,
WinSmallGame: playerEx.RollGameType.BaseResult.WinSmallGame,
WinTotal: playerEx.RollGameType.BaseResult.WinTotal,
}
sceneEx.SaveGamePlayerListLog(playerEx.SnId, logParam)
}
}
}
//统计输下注金币数
if !sceneEx.Testing && !playerEx.IsRob {
playerBet := &server.PlayerData{
SnId: proto.Int32(playerEx.SnId),
Bet: proto.Int64(playerEx.CurrentBet),
Gain: proto.Int64(playerEx.RollGameType.BaseResult.ChangeCoin),
Tax: proto.Int64(playerEx.taxCoin),
Coin: proto.Int64(playerEx.GetCoin()),
GameCoinTs: proto.Int64(playerEx.GameCoinTs),
}
gwPlayerBet := &server.GWPlayerData{
SceneId: proto.Int(sceneEx.SceneId),
GameFreeId: proto.Int32(sceneEx.DbGameFree.GetId()),
}
gwPlayerBet.Datas = append(gwPlayerBet.Datas, playerBet)
sceneEx.SyncPlayerDatas(&base.PlayerDataParam{
HasRobotGaming: false,
Data: gwPlayerBet,
})
}
playerEx.taxCoin = 0
playerEx.winCoin = 0
playerEx.linesWinCoin = 0
playerEx.jackpotWinCoin = 0
playerEx.smallGameWinCoin = 0
if sceneEx.CheckNeedDestroy() && playerEx.freeTimes <= 0 {
sceneEx.PlayerLeave(playerEx.Player, common.PlayerLeaveReason_OnDestroy, true)
}
}
func init() {
ScenePolicyEasterIslandSington.RegisteSceneState(&SceneStateEasterIslandStart{})
core.RegisteHook(core.HOOK_BEFORE_START, func() error {
base.RegisteScenePolicy(common.GameId_EasterIsland, 0, ScenePolicyEasterIslandSington)
return nil
})
}

View File

@ -5,6 +5,8 @@ import (
"fmt" "fmt"
"math" "math"
"math/rand" "math/rand"
"time"
"mongo.games.com/game/common" "mongo.games.com/game/common"
"mongo.games.com/game/gamerule/fruits" "mongo.games.com/game/gamerule/fruits"
"mongo.games.com/game/gamesrv/base" "mongo.games.com/game/gamesrv/base"
@ -14,7 +16,6 @@ import (
"mongo.games.com/game/protocol/server" "mongo.games.com/game/protocol/server"
"mongo.games.com/game/srvdata" "mongo.games.com/game/srvdata"
"mongo.games.com/goserver/core/logger" "mongo.games.com/goserver/core/logger"
"time"
) )
type FruitsSceneData struct { type FruitsSceneData struct {
@ -92,7 +93,7 @@ func (s *FruitsSceneData) OnPlayerLeave(p *base.Player, reason int) {
//小玛丽 //小玛丽
playerEx.winCoin = playerEx.winOutMaryCoin + playerEx.winMidMaryCoin + playerEx.winFreeCoin playerEx.winCoin = playerEx.winOutMaryCoin + playerEx.winMidMaryCoin + playerEx.winFreeCoin
if playerEx.winCoin != 0 { if playerEx.winCoin != 0 {
//SysProfitCoinMgr.PushBetAndSysOut(s.sysProfitCoinKey, 0, playerEx.winCoin) //SysProfitCoinMgr.Add(s.sysProfitCoinKey, 0, playerEx.winCoin)
p.Statics(s.KeyGameId, s.KeyGamefreeId, playerEx.winCoin, false) p.Statics(s.KeyGameId, s.KeyGamefreeId, playerEx.winCoin, false)
//tax := int64(math.Ceil(float64(playerEx.winCoin) * float64(s.DbGameFree.GetTaxRate()) / 10000)) //tax := int64(math.Ceil(float64(playerEx.winCoin) * float64(s.DbGameFree.GetTaxRate()) / 10000))
//playerEx.taxCoin = tax //playerEx.taxCoin = tax
@ -137,7 +138,7 @@ func (s *FruitsSceneData) Win(p *FruitsPlayerData) {
} }
if isBilled && p.winCoin != 0 { if isBilled && p.winCoin != 0 {
p.noWinTimes = 0 p.noWinTimes = 0
//SysProfitCoinMgr.PushBetAndSysOut(s.sysProfitCoinKey, 0, p.winCoin) //SysProfitCoinMgr.Add(s.sysProfitCoinKey, 0, p.winCoin)
p.Statics(s.KeyGameId, s.KeyGamefreeId, p.winCoin, false) p.Statics(s.KeyGameId, s.KeyGamefreeId, p.winCoin, false)
//tax := int64(math.Ceil(float64(p.winCoin) * float64(s.DbGameFree.GetTaxRate()) / 10000)) //tax := int64(math.Ceil(float64(p.winCoin) * float64(s.DbGameFree.GetTaxRate()) / 10000))
//p.taxCoin = tax //p.taxCoin = tax
@ -364,23 +365,19 @@ func (s *FruitsSceneData) SendPlayerBet(p *FruitsPlayerData) {
if p.gameState != fruits.Normal { if p.gameState != fruits.Normal {
betCoin = 0 betCoin = 0
} }
playerBet := &server.PlayerData{
SnId: proto.Int32(p.SnId),
Bet: proto.Int64(betCoin),
Gain: proto.Int64(p.Coin - p.startCoin),
Tax: proto.Int64(p.taxCoin),
}
gwPlayerBet := &server.GWPlayerData{
GameFreeId: proto.Int32(s.DbGameFree.GetId()),
}
gwPlayerBet.Datas = append(gwPlayerBet.Datas, playerBet)
s.SyncPlayerDatas(&base.PlayerDataParam{ s.SyncPlayerDatas(&base.PlayerDataParam{
HasRobotGaming: false, HasRobotGaming: false,
Data: &server.GWPlayerData{ Data: gwPlayerBet,
Datas: []*server.PlayerData{
{
SnId: p.SnId,
Bet: betCoin,
Gain: p.Coin - p.startCoin,
Tax: p.taxCoin,
Coin: p.Coin,
GameCoinTs: p.GameCoinTs,
},
},
GameFreeId: s.GetGameFreeId(),
SceneId: int32(s.SceneId),
},
}) })
} }
} }
@ -443,7 +440,7 @@ func (s *FruitsSceneData) Regulation(p *FruitsPlayerData, n int) {
// } // }
// if regY == -1 { // if regY == -1 {
// if setting != nil { // if setting != nil {
// poolValue := base.CoinPoolMgr.GetCoin(s.GetGameFreeId(), s.Platform, s.GroupId) // poolValue := base.CoinPoolMgr.LoadCoin(s.GetGameFreeId(), s.Platform, s.GroupId)
// w := float64(s.slotRateWeight[0]) * (1 - float64(int32(poolValue)-setting.GetLowerLimit())/float64(setting.GetUpperLimit()-setting.GetLowerLimit()+1)) // w := float64(s.slotRateWeight[0]) * (1 - float64(int32(poolValue)-setting.GetLowerLimit())/float64(setting.GetUpperLimit()-setting.GetLowerLimit()+1))
// if w < 0 { // if w < 0 {
// regY = 0 // regY = 0

View File

@ -326,7 +326,7 @@ func (this *SceneBaseStateFruits) OnTick(s *base.Scene) {
// now := time.Now() // now := time.Now()
// sceneEx.mqLogTime = now.Add(-time.Second * time.Duration(now.Second())) // sceneEx.mqLogTime = now.Add(-time.Second * time.Duration(now.Second()))
// //
// waterVal := base.CoinPoolMgr.GetCoin(s.GetGameFreeId(), s.Platform, s.GroupId) // waterVal := base.CoinPoolMgr.LoadCoin(s.GetGameFreeId(), s.Platform, s.GroupId)
// waterVal = int64(math.Floor(float64(waterVal) / float64(fruits.NowByte))) // waterVal = int64(math.Floor(float64(waterVal) / float64(fruits.NowByte)))
// //
// jkVal1 := int64(math.Floor(float64(sceneEx.jackpot.GetTotalSmall()) / float64(fruits.NowByte))) // jkVal1 := int64(math.Floor(float64(sceneEx.jackpot.GetTotalSmall()) / float64(fruits.NowByte)))
@ -444,7 +444,7 @@ func (this *SceneStateStartFruits) OnPlayerOp(s *base.Scene, p *base.Player, opc
} }
playerEx.CurrentBet = playerEx.betCoin playerEx.CurrentBet = playerEx.betCoin
playerEx.CurrentTax = 0 playerEx.CurrentTax = 0
//SysProfitCoinMgr.PushBetAndSysOut(sceneEx.sysProfitCoinKey, playerEx.betCoin, -playerEx.betCoin) //SysProfitCoinMgr.Add(sceneEx.sysProfitCoinKey, playerEx.betCoin, -playerEx.betCoin)
//没有免费次数 扣钱 //没有免费次数 扣钱
p.Statics(s.KeyGameId, s.KeyGamefreeId, -playerEx.betCoin, false) p.Statics(s.KeyGameId, s.KeyGamefreeId, -playerEx.betCoin, false)
playerEx.AddCoin(-playerEx.betCoin, common.GainWay_HundredSceneLost, 0, "system", s.GetSceneName()) playerEx.AddCoin(-playerEx.betCoin, common.GainWay_HundredSceneLost, 0, "system", s.GetSceneName())

View File

@ -1,11 +1,12 @@
package iceage package iceage
import ( import (
"mongo.games.com/goserver/core/logger"
"mongo.games.com/goserver/core/netlib"
"mongo.games.com/game/common" "mongo.games.com/game/common"
"mongo.games.com/game/gamesrv/base" "mongo.games.com/game/gamesrv/base"
"mongo.games.com/game/protocol/iceage" "mongo.games.com/game/protocol/iceage"
"mongo.games.com/goserver/core/logger"
"mongo.games.com/goserver/core/netlib"
) )
// 冰河世纪的操作 // 冰河世纪的操作

View File

@ -2,8 +2,9 @@ package iceage
import ( import (
"encoding/json" "encoding/json"
"mongo.games.com/game/model"
"time" "time"
"mongo.games.com/game/model"
) )
// 玩家游戏数据索引 // 玩家游戏数据索引

View File

@ -3,13 +3,14 @@ package iceage
import ( import (
"encoding/json" "encoding/json"
"math/rand" "math/rand"
"strconv"
"mongo.games.com/goserver/core/timer"
rule "mongo.games.com/game/gamerule/iceage" rule "mongo.games.com/game/gamerule/iceage"
base "mongo.games.com/game/gamesrv/base" "mongo.games.com/game/gamesrv/base"
"mongo.games.com/game/model" "mongo.games.com/game/model"
"mongo.games.com/game/protocol/iceage" "mongo.games.com/game/protocol/iceage"
"mongo.games.com/goserver/core/timer"
"strconv"
//"mongo.games.com/game/common"
) )
type IceAgePlayerData struct { type IceAgePlayerData struct {

View File

@ -4,20 +4,21 @@ import (
"encoding/json" "encoding/json"
"math" "math"
"math/rand" "math/rand"
"time"
"mongo.games.com/goserver/core/basic"
"mongo.games.com/goserver/core/logger"
"mongo.games.com/goserver/core/task"
"mongo.games.com/game/common" "mongo.games.com/game/common"
rule "mongo.games.com/game/gamerule/iceage"
"mongo.games.com/game/gamesrv/base"
"mongo.games.com/game/model" "mongo.games.com/game/model"
"mongo.games.com/game/proto"
"mongo.games.com/game/protocol/gamehall" "mongo.games.com/game/protocol/gamehall"
"mongo.games.com/game/protocol/iceage" "mongo.games.com/game/protocol/iceage"
"mongo.games.com/game/protocol/server" "mongo.games.com/game/protocol/server"
"mongo.games.com/goserver/core/basic"
"mongo.games.com/goserver/core/task"
"time"
rule "mongo.games.com/game/gamerule/iceage"
"mongo.games.com/game/gamesrv/base"
"mongo.games.com/game/proto"
"mongo.games.com/game/srvdata" "mongo.games.com/game/srvdata"
"mongo.games.com/goserver/core/logger"
) )
type IceAgeJackpot struct { type IceAgeJackpot struct {
@ -323,14 +324,7 @@ func (this *IceAgeSceneData) AIAddJackPot() {
randT = rand.Intn(3) + 1 randT = rand.Intn(3) + 1
} }
this.lastJackPot = time.Now().Add(time.Second * time.Duration(randT)) this.lastJackPot = time.Now().Add(time.Second * time.Duration(randT))
//AI机器人 val := int64(math.Floor(float64(this.DbGameFree.GetBaseScore()) * float64(rule.LINENUM) * float64(500) / 10000))
setting := base.CoinPoolMgr.GetCoinPoolSetting(this.Platform, this.GetGameFreeId(), this.GroupId)
var ctroRate int32
if setting != nil {
ctroRate = 9800
}
var val int64
val = int64(math.Floor(float64(this.DbGameFree.GetBaseScore()) * float64(rule.LINENUM) * float64(ctroRate) / 10000))
this.jackpot.VirtualJK += val this.jackpot.VirtualJK += val
} }
} }

View File

@ -3,6 +3,17 @@ package iceage
import ( import (
"fmt" "fmt"
"math" "math"
"os"
"strconv"
"sync"
"time"
"mongo.games.com/goserver/core"
"mongo.games.com/goserver/core/basic"
"mongo.games.com/goserver/core/logger"
"mongo.games.com/goserver/core/task"
"mongo.games.com/goserver/core/timer"
"mongo.games.com/game/common" "mongo.games.com/game/common"
rule "mongo.games.com/game/gamerule/iceage" rule "mongo.games.com/game/gamerule/iceage"
"mongo.games.com/game/gamesrv/base" "mongo.games.com/game/gamesrv/base"
@ -10,15 +21,6 @@ import (
"mongo.games.com/game/proto" "mongo.games.com/game/proto"
"mongo.games.com/game/protocol/iceage" "mongo.games.com/game/protocol/iceage"
"mongo.games.com/game/protocol/server" "mongo.games.com/game/protocol/server"
"mongo.games.com/goserver/core"
"mongo.games.com/goserver/core/basic"
"mongo.games.com/goserver/core/logger"
"mongo.games.com/goserver/core/task"
"mongo.games.com/goserver/core/timer"
"os"
"strconv"
"sync"
"time"
) )
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -395,7 +397,7 @@ func (this *SceneStateIceAgeStart) OnPlayerOp(s *base.Scene, p *base.Player, opc
//水池设置 //水池设置
coinPoolSetting := base.GetCoinPoolMgr().GetCoinPoolSetting(sceneEx.GetPlatform(), sceneEx.GetGameFreeId(), sceneEx.GetGroupId()) coinPoolSetting := base.GetCoinPoolMgr().GetCoinPoolSetting(sceneEx.GetPlatform(), sceneEx.GetGameFreeId(), sceneEx.GetGroupId())
//baseRate := coinPoolSetting.GetBaseRate() //基础赔率 //baseRate := coinPoolSetting.GetBaseRate() //基础赔率
ctroRate := 9800 //调节赔率 暗税系数 ctroRate := 500 //调节赔率 暗税系数
//if baseRate >= 10000 || baseRate <= 0 || ctroRate < 0 || ctroRate >= 1000 || baseRate+ctroRate > 9900 { //if baseRate >= 10000 || baseRate <= 0 || ctroRate < 0 || ctroRate >= 1000 || baseRate+ctroRate > 9900 {
// logger.Logger.Warnf("IceAgeErrorBaseRate [%v][%v][%v][%v][%v]", sceneEx.GetGameFreeId(), playerEx.SnId, playerEx.spinID, baseRate, ctroRate) // logger.Logger.Warnf("IceAgeErrorBaseRate [%v][%v][%v][%v][%v]", sceneEx.GetGameFreeId(), playerEx.SnId, playerEx.spinID, baseRate, ctroRate)
// baseRate = 9700 // baseRate = 9700
@ -406,13 +408,13 @@ func (this *SceneStateIceAgeStart) OnPlayerOp(s *base.Scene, p *base.Player, opc
logger.Logger.Tracef("IceAgeRates [%v][%v][%v][%v][%v]", sceneEx.GetGameFreeId(), playerEx.SnId, playerEx.spinID, taxRate, ctroRate) logger.Logger.Tracef("IceAgeRates [%v][%v][%v][%v][%v]", sceneEx.GetGameFreeId(), playerEx.SnId, playerEx.spinID, taxRate, ctroRate)
playerEx.IsFNovice(sceneEx.KeyGameId) playerEx.IsFNovice(sceneEx.KeyGameId)
isFoolPlayer := playerEx.IsFoolPlayer[sceneEx.KeyGameId] isFoolPlayer := false
var gamePoolCoin int64 var gamePoolCoin int64
if isFoolPlayer { //if isFoolPlayer {
gamePoolCoin = base.CoinPoolMgr.GetNoviceCoin(sceneEx.GetGameFreeId(), sceneEx.Platform, sceneEx.GroupId) // 当前水池金额 // gamePoolCoin = base.CoinPoolMgr.GetNoviceCoinPool(sceneEx.GetGameFreeId(), sceneEx.Platform, sceneEx.GroupId) // 当前水池金额
} else { //} else {
gamePoolCoin = base.CoinPoolMgr.GetCoin(sceneEx.GetGameFreeId(), sceneEx.Platform, sceneEx.GroupId) // 当前水池金额 gamePoolCoin = base.CoinPoolMgr.GetCoin(sceneEx.GetGameFreeId(), sceneEx.Platform, sceneEx.GroupId) // 当前水池金额
} //}
prizeFund := gamePoolCoin - sceneEx.jackpot.VirtualJK // 除去奖池的水池剩余金额 prizeFund := gamePoolCoin - sceneEx.jackpot.VirtualJK // 除去奖池的水池剩余金额
var jackpotParam = sceneEx.GetDBGameFree().GetJackpot() // 奖池参数 var jackpotParam = sceneEx.GetDBGameFree().GetJackpot() // 奖池参数
@ -979,9 +981,10 @@ func IceAgeCheckAndSaveLog(sceneEx *IceAgeSceneData, playerEx *IceAgePlayerData)
GameFreeId: proto.Int32(sceneEx.GetDBGameFree().GetId()), GameFreeId: proto.Int32(sceneEx.GetDBGameFree().GetId()),
} }
gwPlayerBet.Datas = append(gwPlayerBet.Datas, playerBet) gwPlayerBet.Datas = append(gwPlayerBet.Datas, playerBet)
proto.SetDefaults(gwPlayerBet) sceneEx.SyncPlayerDatas(&base.PlayerDataParam{
sceneEx.SendToWorld(int(server.SSPacketID_PACKET_GW_PLAYERDATA), gwPlayerBet) HasRobotGaming: false,
logger.Logger.Trace("Send msg gwPlayerBet ===>", gwPlayerBet) Data: gwPlayerBet,
})
} }
playerEx.taxCoin = 0 playerEx.taxCoin = 0

View File

@ -20,8 +20,14 @@ import (
_ "mongo.games.com/game/gamesrv/thirteen" _ "mongo.games.com/game/gamesrv/thirteen"
_ "mongo.games.com/game/gamesrv/tienlen" _ "mongo.games.com/game/gamesrv/tienlen"
// 拉霸
_ "mongo.games.com/game/gamesrv/avengers"
_ "mongo.games.com/game/gamesrv/caishen"
_ "mongo.games.com/game/gamesrv/easterisland"
_ "mongo.games.com/game/gamesrv/fruits" _ "mongo.games.com/game/gamesrv/fruits"
_ "mongo.games.com/game/gamesrv/iceage" _ "mongo.games.com/game/gamesrv/iceage"
_ "mongo.games.com/game/gamesrv/richblessed"
_ "mongo.games.com/game/gamesrv/tamquoc"
) )
func main() { func main() {

View File

@ -0,0 +1,48 @@
package richblessed
import (
"mongo.games.com/goserver/core/logger"
"mongo.games.com/goserver/core/netlib"
"mongo.games.com/game/common"
"mongo.games.com/game/gamesrv/base"
"mongo.games.com/game/protocol/richblessed"
)
type CSRichBlessedOpPacketFactory struct {
}
type CSRichBlessedOpHandler struct {
}
func (this *CSRichBlessedOpPacketFactory) CreatePacket() interface{} {
pack := &richblessed.CSRichBlessedOp{}
return pack
}
func (this *CSRichBlessedOpHandler) Process(s *netlib.Session, packetid int, data interface{}, sid int64) error {
if op, ok := data.(*richblessed.CSRichBlessedOp); ok {
p := base.PlayerMgrSington.GetPlayer(sid)
if p == nil {
logger.Logger.Warn("CSRichBlessedOpHandler p == nil")
return nil
}
scene := p.GetScene()
if scene == nil {
logger.Logger.Warn("CSRichBlessedOpHandler p.scene == nil")
return nil
}
if !scene.HasPlayer(p) {
return nil
}
if scene.GetScenePolicy() != nil {
scene.GetScenePolicy().OnPlayerOp(scene, p, int(op.GetOpCode()), op.GetParams())
}
return nil
}
return nil
}
func init() {
//多财多福
common.RegisterHandler(int(richblessed.RBPID_PACKET_RICHBLESSED_CSRichBlessedOp), &CSRichBlessedOpHandler{})
netlib.RegisterFactory(int(richblessed.RBPID_PACKET_RICHBLESSED_CSRichBlessedOp), &CSRichBlessedOpPacketFactory{})
}

View File

@ -0,0 +1,112 @@
package richblessed
import (
"mongo.games.com/game/gamerule/richblessed"
"mongo.games.com/game/gamesrv/base"
"mongo.games.com/game/model"
)
var (
ElementsParams = [][]int32{} // 十三个元素
FreeElementsParams = [][]int32{}
FreeLeElementsParams = []int32{0, 0, 60, 50, 50, 60, 50, 0, 0, 0, 0, 0, 0}
JACKPOTElementsParams = []int32{20, 30, 100, 150}
)
// RichBlessed
type RichBlessedPlayerData struct {
*base.Player
roomid int32 //房间ID
result *richblessed.WinResult
betIdx int //下注索引
betCoin int64 //下注金额
maxbetCoin int64 //下注金额
oneBetCoin int64 //单注
cpCtx model.CoinPoolCtx //水池环境
leaveTime int32 //离开时间
winCoin int64 //本局输赢
startCoin int64 //本局开始金币
freewinCoin int64 //免费游戏总输赢
JackwinCoin int64 //Jack奖励
freeTimes int32 //免费游戏
addfreeTimes int32 //新增免费游戏
gameState int //当前游戏模式
taxCoin int64 //税收
noWinTimes int //没有中奖次数
isFWinJackpot bool //是否中奖
JackMidCards []int64 //掀开位置
///当局数值
nowFreeTimes int //当前第几轮免费游戏
winLineRate int64 //线倍率
JackPotRate int64 //获取奖池的百分比 5% 10% 15%
freeWinTotalRate int64 //免费游戏赢的倍率
// winNowJackPotCoin int64 //当局奖池爆奖
winNowAllRate int64 //当局赢得倍率
//测试
isFTest int
isTestIdx int
isJk bool
//
weightPos int32 //当局权重
}
func (p *RichBlessedPlayerData) init() {
p.roomid = 0
p.result = new(richblessed.WinResult)
}
func (p *RichBlessedPlayerData) Clear() {
p.gameState = richblessed.Normal
p.startCoin = p.Coin
p.winCoin = 0
p.taxCoin = 0
p.isFWinJackpot = false
p.addfreeTimes = 0
p.result.AllRate = 0
p.JackMidCards = p.JackMidCards[:0]
p.result.FreeNum = 0
p.result.JackpotEle = -1
p.result.JackpotRate = 0
if p.freeTimes == 0 {
p.freewinCoin = 0
p.nowFreeTimes = 0
}
p.isJk = false
p.weightPos = 0
}
// 正常游戏 免费游戏
func (p *RichBlessedPlayerData) TestCode(eleLineAppearRate [][]int32) {
if p.isFTest%5 == 0 && p.gameState == richblessed.Normal {
switch p.isTestIdx {
case 0:
//免费
p.result.EleValue = []int32{
1, 1, 1, 1, 1,
6, 2, 7, 7, 9,
9, 7, 4, 8, 7,
}
p.isTestIdx = 1
case 1:
//奖池
p.result.EleValue = []int32{
5, 0, 0, 0, 1,
6, 2, 7, 7, 9,
9, 1, 4, 8, 7,
}
p.isTestIdx = 0
p.isJk = true
}
} else {
p.result.CreateLine(eleLineAppearRate)
}
}
func (p *RichBlessedPlayerData) CreateLevResult(eleLineAppearRate [][]int32) {
p.result.CreateLevLine(eleLineAppearRate)
}
// 正常游戏 免费游戏
func (p *RichBlessedPlayerData) CreateJACKPOT(eleRate []int32) {
p.result.CreateJACKPOT(eleRate)
}

View File

@ -0,0 +1,457 @@
package richblessed
import (
"encoding/json"
"fmt"
"math"
"math/rand"
"time"
"mongo.games.com/goserver/core/logger"
"mongo.games.com/game/common"
"mongo.games.com/game/gamerule/richblessed"
"mongo.games.com/game/gamesrv/base"
"mongo.games.com/game/model"
"mongo.games.com/game/proto"
protocol "mongo.games.com/game/protocol/richblessed"
"mongo.games.com/game/protocol/server"
"mongo.games.com/game/srvdata"
)
type RichBlessedSceneData struct {
*base.Scene //场景
players map[int32]*RichBlessedPlayerData //玩家信息
jackpot *base.SlotJackpotPool //奖池
levelRate [][]int32 //调控概率区间
slotRateWeight []int32 //调控权重
sysProfitCoinKey string
mqLogTime time.Time
}
func NewRichBlessedSceneData(s *base.Scene) *RichBlessedSceneData {
sceneEx := &RichBlessedSceneData{
Scene: s,
players: make(map[int32]*RichBlessedPlayerData),
}
sceneEx.Init()
return sceneEx
}
func (s *RichBlessedSceneData) Init() {
s.LoadJackPotData()
//for _, data := range srvdata.PBDB_SlotRateMgr.Datas.Arr {
// if int(data.GetGameId()) == common.GameId_Fruits {
// s.levelRate = append(s.levelRate, data.RateSection)
// s.slotRateWeight = append(s.slotRateWeight, data.GetWeight())
// }
//}
s.sysProfitCoinKey = fmt.Sprintf("%v_%v", s.Platform, s.GetGameFreeId())
s.mqLogTime = time.Now()
}
func (s *RichBlessedSceneData) Clear() {
}
func (s *RichBlessedSceneData) SceneDestroy(force bool) {
//销毁房间
s.Scene.Destroy(force)
}
func (s *RichBlessedSceneData) AddPrizeCoin(playerEx *RichBlessedPlayerData) {
val := playerEx.betCoin
tax := int64(math.Ceil(float64(val) * float64(s.DbGameFree.GetTaxRate()) / 10000))
//playerEx.taxCoin = tax
//playerEx.AddServiceFee(tax)
val -= tax
addPrizeCoin := val * richblessed.NowByte * int64(s.DbGameFree.GetJackpotRatio()) //扩大10000倍
jk1 := int64(math.Floor(float64(addPrizeCoin) / 1000 / 4)) //千分之奖池比例 分四份
s.jackpot.AddToGrand(playerEx.IsRob, jk1)
s.jackpot.AddToBig(playerEx.IsRob, jk1)
s.jackpot.AddToMiddle(playerEx.IsRob, jk1)
s.jackpot.AddToSmall(playerEx.IsRob, jk1)
logger.Logger.Tracef("[Rich] 奖池增加...AddPrizeCoin... %f", float64(jk1*4)/float64(richblessed.NowByte))
base.SlotsPoolMgr.SetPool(s.GetGameFreeId(), s.Platform, s.jackpot)
if !s.Testing {
base.CoinPoolMgr.PushCoin(s.GetGameFreeId(), s.GroupId, s.Platform, val*richblessed.NowByte-jk1*4)
}
}
func (s *RichBlessedSceneData) DelPrizeCoin(isRob bool, win int64, jackpotEle int32) {
if win > 0 {
switch jackpotEle {
case richblessed.GoldBoy:
s.jackpot.AddToGrand(isRob, -win*richblessed.NowByte)
case richblessed.GoldGirl:
s.jackpot.AddToBig(isRob, -win*richblessed.NowByte)
case richblessed.BlueBoy:
s.jackpot.AddToMiddle(isRob, -win*richblessed.NowByte)
default:
s.jackpot.AddToSmall(isRob, -win*richblessed.NowByte)
}
logger.Logger.Tracef("[Rich] 奖池减少...DelPrizeCoin... %d", win)
base.SlotsPoolMgr.SetPool(s.GetGameFreeId(), s.Platform, s.jackpot)
}
}
func (s *RichBlessedSceneData) delPlayer(SnId int32) {
if _, exist := s.players[SnId]; exist {
delete(s.players, SnId)
}
}
func (s *RichBlessedSceneData) OnPlayerLeave(p *base.Player, reason int) {
if playerEx, ok := p.ExtraData.(*RichBlessedPlayerData); ok {
if playerEx.freeTimes > 0 || playerEx.isFWinJackpot {
if playerEx.isFWinJackpot { // 小游戏
s.JACKPOTWin(playerEx)
a1 := rand.Int63n(3)
a2 := rand.Int63n(3) + 3
a3 := rand.Int63n(2) + 6
playerEx.JackMidCards = append(playerEx.JackMidCards, a1, a2, a3)
//发送结算
//s.SendJACKPOTBilled(playerEx)
s.SaveLog(playerEx, 1)
playerEx.Clear()
}
//freenum := playerEx.freeTimes
//for i := int32(0); i < freenum; i++ {
// playerEx.Clear()
// gameRand, _ := s.GetFreeWeight()
// playerEx.CreateLevResult(gameRand) // 没有铜锣概率
// s.Win(playerEx)
// s.SaveLog(playerEx, 1)
//}
}
s.delPlayer(p.SnId)
}
}
// 是否中奖
func (s *RichBlessedSceneData) CanJACKPOT(p *RichBlessedPlayerData, bet int64, big int64, JACKRand []int32) bool {
ret := p.result.CanJACKPOT(bet, big)
logger.Logger.Tracef("RichBlessedSceneData CanJACKPOT %v %v", ret, p.result.EleValue)
if ret || p.isJk {
WinJackPot := int64(0)
ele := p.result.CreateJACKPOT(JACKRand)
if p.isJk {
ele = rand.Int31n(richblessed.JackMax)
p.result.JackpotEle = ele
}
switch ele {
case richblessed.GoldBoy:
WinJackPot = s.jackpot.GetTotalGrand()
case richblessed.GoldGirl:
WinJackPot = s.jackpot.GetTotalBig()
case richblessed.BlueBoy:
WinJackPot = s.jackpot.GetTotalMiddle()
case richblessed.BlueGirl:
WinJackPot = s.jackpot.GetTotalSmall()
}
if WinJackPot > 0 {
jkWin := int64(math.Floor(float64(WinJackPot) / float64(richblessed.NowByte)))
if jkWin > (richblessed.JkEleNumRate[int(ele)]*p.oneBetCoin) || p.isJk {
p.isFWinJackpot = true
return true
}
}
//不能中奖
p.result.JackpotEle = -1
p.result.JackpotRate = 0
}
return false
}
func (s *RichBlessedSceneData) Win(p *RichBlessedPlayerData) {
p.result.Win(p.betCoin, p.maxbetCoin)
if p.result.FreeNum != 0 {
p.addfreeTimes = p.result.FreeNum
p.freeTimes += p.addfreeTimes
}
p.winLineRate = p.result.AllRate
p.winCoin += p.oneBetCoin * p.winLineRate
if p.gameState == richblessed.FreeGame {
p.freewinCoin += p.winCoin
}
if p.winCoin != 0 {
p.noWinTimes = 0
//SysProfitCoinMgr.Add(s.sysProfitCoinKey, 0, p.winCoin)
p.Statics(s.KeyGameId, s.KeyGamefreeId, p.winCoin, false)
//tax := int64(math.Ceil(float64(p.winCoin) * float64(s.DbGameFree.GetTaxRate()) / 10000))
//p.taxCoin = tax
//p.winCoin -= tax
//p.AddServiceFee(tax)
p.AddCoin(p.winCoin, common.GainWay_HundredSceneWin, 0, "system", s.GetSceneName())
if !s.Testing && p.winCoin != 0 {
base.CoinPoolMgr.PushCoin(s.GetGameFreeId(), s.GroupId, s.Platform, -(p.winCoin)*richblessed.NowByte)
}
//p.isReportGameEvent = true
}
}
func (s *RichBlessedSceneData) JACKPOTWin(p *RichBlessedPlayerData) {
p.result.JACKPOTWin()
p.JackwinCoin = p.result.JackpotRate * p.oneBetCoin
if p.JackwinCoin > 0 {
s.DelPrizeCoin(p.IsRob, p.JackwinCoin, p.result.JackpotEle)
p.noWinTimes = 0
//SysProfitCoinMgr.Add(s.sysProfitCoinKey, 0, p.JackwinCoin)
p.Statics(s.KeyGameId, s.KeyGamefreeId, p.JackwinCoin, false)
//tax := int64(math.Ceil(float64(p.JackwinCoin) * float64(s.DbGameFree.GetTaxRate()) / 10000))
//p.taxCoin = tax
//p.JackwinCoin -= tax
//p.AddServiceFee(tax)
p.AddCoin(p.JackwinCoin, common.GainWay_HundredSceneWin, 0, "system", s.GetSceneName())
if !s.Testing && p.JackwinCoin != 0 {
base.CoinPoolMgr.PushCoin(s.GetGameFreeId(), s.GroupId, s.Platform, -(p.JackwinCoin)*richblessed.NowByte)
}
// p.JackpotEle = -1
//p.isReportGameEvent = true
}
}
func (s *RichBlessedSceneData) SendBilled(p *RichBlessedPlayerData) {
//正常游戏 免费游戏
pack := &protocol.SCRBBilled{
NowGameState: proto.Int(p.gameState),
BetIdx: proto.Int(p.betIdx),
Coin: proto.Int64(p.Coin),
Cards: p.result.EleValue,
FreeAllWin: proto.Int64(p.freewinCoin), //
//SmallJackpot: proto.Int64(s.jackpot.GetTotalSmall() / 10000),
//MiddleJackpot: proto.Int64(s.jackpot.GetTotalMiddle() / 10000),
//BigJackpot: proto.Int64(s.jackpot.GetTotalBig() / 10000),
//GrandJackpot: proto.Int64(s.jackpot.GetTotalGrand() / 10000),
WinEleCoin: proto.Int64(p.winCoin),
WinRate: proto.Int64(p.winLineRate),
FreeNum: proto.Int64(int64(p.freeTimes)),
AddFreeNum: proto.Int64(int64(p.addfreeTimes)),
JackpotEle: proto.Int32(p.result.JackpotEle),
WinFreeTimes: proto.Int32(int32(p.nowFreeTimes)),
}
var wl []*protocol.RichWinLine
for _, r := range p.result.WinLine {
wl = append(wl, &protocol.RichWinLine{
Poss: r.Poss,
})
}
pack.WinLines = wl
logger.Logger.Trace("SCRBBilled", pack)
p.SendToClient(int(protocol.RBPID_PACKET_RICHBLESSED_SCRBBilled), pack)
}
func (s *RichBlessedSceneData) SendJACKPOTBilled(p *RichBlessedPlayerData) {
pack := &protocol.SCRBBilled{
NowGameState: proto.Int(p.gameState),
BetIdx: proto.Int(p.betIdx),
Coin: proto.Int64(p.Coin),
//SmallJackpot: proto.Int64(s.jackpot.GetTotalSmall() / 10000),
//MiddleJackpot: proto.Int64(s.jackpot.GetTotalMiddle() / 10000),
//BigJackpot: proto.Int64(s.jackpot.GetTotalBig() / 10000),
//GrandJackpot: proto.Int64(s.jackpot.GetTotalGrand() / 10000),
WinJackpot: proto.Int64(p.JackwinCoin),
}
logger.Logger.Trace("SendJACKPOTBilled:", pack)
p.SendToClient(int(protocol.RBPID_PACKET_RICHBLESSED_SCRBJACKBilled), pack)
}
func (s *RichBlessedSceneData) LoadJackPotData() {
str := base.SlotsPoolMgr.GetPool(s.GetGameFreeId(), s.Platform)
if str != "" {
jackpot := &base.SlotJackpotPool{}
err := json.Unmarshal([]byte(str), jackpot)
if err == nil {
s.jackpot = jackpot
}
}
if s.jackpot != nil {
base.SlotsPoolMgr.SetPool(s.GetGameFreeId(), s.Platform, s.jackpot)
} else {
s.jackpot = &base.SlotJackpotPool{}
jp := s.DbGameFree.GetJackpot()
if len(jp) > 0 {
s.jackpot.Small += int64(jp[0] * 10000)
}
}
}
func (s *RichBlessedSceneData) SaveLog(p *RichBlessedPlayerData, isOffline int) {
if s.Testing {
return
}
s.SendPlayerBet(p)
var betCoin int64
var nowNRound int
var nowGetCoin int64
if p.gameState == richblessed.Normal {
betCoin = p.betCoin
nowGetCoin = p.winCoin
} else if p.gameState == richblessed.FreeGame {
nowNRound = p.nowFreeTimes
nowGetCoin = p.winCoin
} else {
nowGetCoin = p.JackwinCoin
}
RichBlessed := model.RichBlessedType{
RoomId: s.SceneId,
BasicScore: int32(p.oneBetCoin),
PlayerSnId: p.SnId,
BeforeCoin: p.startCoin,
AfterCoin: p.Coin,
ChangeCoin: p.Coin - p.startCoin,
TotalBetCoin: betCoin,
TotalLine: 9,
TotalWinCoin: nowGetCoin,
NowGameState: p.gameState,
NowNRound: nowNRound,
IsOffline: isOffline,
FirstFreeTimes: int(p.freeTimes),
TaxCoin: p.taxCoin,
WBLevel: p.WBLevel,
RealCtrl: s.RealCtrl,
WBState: p.WBState,
WeightKey: p.weightPos + 1,
}
var winLine []model.RichBlessedWinLine
if p.gameState == richblessed.JackGame { // jack小游戏
RichBlessed.JackEleValue = p.result.JackpotEle
RichBlessed.JackMidCards = append(RichBlessed.JackMidCards, p.JackMidCards...)
}
RichBlessed.Cards = p.result.EleValue
RichBlessed.WinLineNum = len(p.result.WinLine)
RichBlessed.WinLineRate = p.winLineRate
RichBlessed.WinLineCoin = p.winLineRate * p.oneBetCoin
for _, line := range p.result.WinLine {
if len(line.Lines) > 0 {
flag := line.Lines[0]
fw := model.RichBlessedWinLine{
Id: line.LineId,
Num: len(line.Lines),
EleValue: flag,
Rate: line.Rate,
WinCoin: line.Rate * p.oneBetCoin,
}
winLine = append(winLine, fw)
}
}
RichBlessed.WinLine = winLine
info, err := model.MarshalGameNoteByROLL(&RichBlessed)
if err == nil {
logId, _ := model.AutoIncGameLogId()
s.SaveGameDetailedLog(logId, info, &base.GameDetailedParam{})
//水池上下文环境s
s.CpCtx = p.cpCtx
var totalIn, totalOut int64
if betCoin > 0 {
totalIn = betCoin
}
if nowGetCoin > 0 {
totalOut = p.Coin - p.startCoin + betCoin /*+ p.taxCoin*/
}
s.SaveGamePlayerListLog(p.SnId,
&base.SaveGamePlayerListLogParam{
Platform: p.Platform,
Channel: p.Channel,
Promoter: p.BeUnderAgentCode,
PackageTag: p.PackageID,
InviterId: p.InviterId,
LogId: logId,
TotalIn: totalIn,
TotalOut: totalOut,
TaxCoin: p.taxCoin,
ClubPumpCoin: 0,
BetAmount: totalIn,
WinAmountNoAnyTax: p.Coin - p.startCoin,
IsFirstGame: s.IsPlayerFirst(p.Player),
})
}
s.GameNowTime = time.Now()
if s.CheckNeedDestroy() && p.freeTimes == 0 {
s.PlayerLeave(p.Player, common.PlayerLeaveReason_OnDestroy, true)
}
}
func (s *RichBlessedSceneData) GetEleWeight(needpos int32) (norms, frees [][]int32, jk []int32, key int32) {
if needpos < 0 || needpos > 7 || !s.RealCtrl {
needpos = 0
}
if needpos == 0 {
curCoin := base.CoinPoolMgr.GetCoin(s.GetGameFreeId(), s.Platform, s.GroupId)
curCoin = int64(math.Floor(float64(curCoin) / float64(richblessed.NowByte)))
for i := len(s.DbGameFree.BalanceLine) - 1; i >= 0; i-- {
balance := s.DbGameFree.BalanceLine[i]
if curCoin >= int64(balance) {
key = int32(i)
break
}
}
} else {
key = needpos - 1
}
for _, ele := range srvdata.PBDB_SlotRateWeightMgr.Datas.GetArr() {
if ele.GameFreeId == s.GetGameFreeId() && ele.Pos == key {
norms = append(norms, ele.NormCol1)
norms = append(norms, ele.NormCol2)
norms = append(norms, ele.NormCol3)
norms = append(norms, ele.NormCol4)
norms = append(norms, ele.NormCol5)
frees = append(frees, ele.FreeCol1)
frees = append(frees, ele.FreeCol2)
frees = append(frees, ele.FreeCol3)
frees = append(frees, ele.FreeCol4)
frees = append(frees, ele.FreeCol5)
jk = ele.JackPot
break
}
}
if norms == nil {
norms = richblessed.EleWeight[:5]
frees = richblessed.EleWeight[5:10]
jk = richblessed.EleWeight[10]
key = 0
}
return
}
func (s *RichBlessedSceneData) CreateResult(eleLineAppearRate [][]int32, playerEx *RichBlessedPlayerData) {
//if s.DbGameFree.GetId() == 3070004 {
// playerEx.TestCode(eleLineAppearRate)
//} else {
playerEx.result.CreateLine(eleLineAppearRate)
//}
}
func (s *RichBlessedSceneData) SendPlayerBet(p *RichBlessedPlayerData) {
//统计输下注金币数
if !p.IsRob && !s.Testing {
betCoin := p.betCoin
if p.gameState != richblessed.Normal {
betCoin = 0
}
playerBet := &server.PlayerData{
SnId: proto.Int32(p.SnId),
Bet: proto.Int64(betCoin),
Gain: proto.Int64(p.Coin - p.startCoin),
Tax: proto.Int64(p.taxCoin),
}
gwPlayerBet := &server.GWPlayerData{
GameFreeId: proto.Int32(s.DbGameFree.GetId()),
}
gwPlayerBet.Datas = append(gwPlayerBet.Datas, playerBet)
s.SyncPlayerDatas(&base.PlayerDataParam{
HasRobotGaming: false,
Data: gwPlayerBet,
})
}
}

View File

@ -0,0 +1,585 @@
package richblessed
import (
"time"
"mongo.games.com/goserver/core"
"mongo.games.com/goserver/core/logger"
"mongo.games.com/game/common"
"mongo.games.com/game/gamerule/richblessed"
"mongo.games.com/game/gamesrv/base"
"mongo.games.com/game/proto"
protocol "mongo.games.com/game/protocol/richblessed"
)
// ////////////////////////////////////////////////////////////
var ScenePolicyRichBlessedSington = &ScenePolicyRichBlessed{}
type ScenePolicyRichBlessed struct {
base.BaseScenePolicy
states [richblessed.RichBlessedStateMax]base.SceneState
}
// 创建场景扩展数据
func (this *ScenePolicyRichBlessed) CreateSceneExData(s *base.Scene) interface{} {
sceneEx := NewRichBlessedSceneData(s)
if sceneEx != nil {
if sceneEx.GetInit() {
s.SetExtraData(sceneEx)
}
}
return sceneEx
}
// 创建玩家扩展数据
func (this *ScenePolicyRichBlessed) CreatePlayerExData(s *base.Scene, p *base.Player) interface{} {
playerEx := &RichBlessedPlayerData{Player: p}
p.SetExtraData(playerEx)
return playerEx
}
// 场景开启事件
func (this *ScenePolicyRichBlessed) OnStart(s *base.Scene) {
logger.Logger.Trace("(this *ScenePolicyRichBlessed) OnStart, sceneId=", s.GetSceneId())
sceneEx := NewRichBlessedSceneData(s)
if sceneEx != nil {
if sceneEx.GetInit() {
s.SetExtraData(sceneEx)
s.ChangeSceneState(richblessed.RichBlessedStateStart)
}
}
}
// 场景关闭事件
func (this *ScenePolicyRichBlessed) OnStop(s *base.Scene) {
logger.Logger.Trace("(this *ScenePolicyRichBlessed) OnStop , sceneId=", s.GetSceneId())
}
// 场景心跳事件
func (this *ScenePolicyRichBlessed) OnTick(s *base.Scene) {
if s == nil {
return
}
if s.GetSceneState() != nil {
s.GetSceneState().OnTick(s)
}
}
// 玩家进入事件
func (this *ScenePolicyRichBlessed) OnPlayerEnter(s *base.Scene, p *base.Player) {
if s == nil || p == nil {
return
}
logger.Logger.Trace("(this *ScenePolicyRichBlessed) OnPlayerEnter, sceneId=", s.GetSceneId(), " player=", p.Name, "bet:", s.DbGameFree.GetOtherIntParams())
if sceneEx, ok := s.GetExtraData().(*RichBlessedSceneData); ok {
playerEx := &RichBlessedPlayerData{Player: p}
playerEx.init()
playerEx.Clear()
sceneEx.players[p.SnId] = playerEx
p.SetExtraData(playerEx)
RichBlessedSendRoomInfo(s, sceneEx, playerEx)
s.FirePlayerEvent(p, base.PlayerEventEnter, nil)
}
}
// 玩家离开事件
func (this *ScenePolicyRichBlessed) OnPlayerLeave(s *base.Scene, p *base.Player, reason int) {
if s == nil || p == nil {
return
}
logger.Logger.Trace("(this *ScenePolicyRichBlessed) OnPlayerLeave, sceneId=", s.GetSceneId(), " player=", p.SnId)
if sceneEx, ok := s.ExtraData.(*RichBlessedSceneData); ok {
s.FirePlayerEvent(p, base.PlayerEventLeave, nil)
sceneEx.OnPlayerLeave(p, reason)
}
}
// 玩家掉线
func (this *ScenePolicyRichBlessed) OnPlayerDropLine(s *base.Scene, p *base.Player) {
if s == nil || p == nil {
return
}
logger.Logger.Trace("(this *ScenePolicyRichBlessed) OnPlayerDropLine, sceneId=", s.GetSceneId(), " player=", p.SnId)
s.FirePlayerEvent(p, base.PlayerEventDropLine, nil)
}
// 玩家重连
func (this *ScenePolicyRichBlessed) OnPlayerRehold(s *base.Scene, p *base.Player) {
if s == nil || p == nil {
return
}
logger.Logger.Trace("(this *ScenePolicyRichBlessed) OnPlayerRehold, sceneId=", s.GetSceneId(), " player=", p.SnId)
if sceneEx, ok := s.GetExtraData().(*RichBlessedSceneData); ok {
if playerEx, ok := p.GetExtraData().(*RichBlessedPlayerData); ok {
RichBlessedSendRoomInfo(s, sceneEx, playerEx)
}
}
}
// 返回房间
func (this *ScenePolicyRichBlessed) OnPlayerReturn(s *base.Scene, p *base.Player) {
if s == nil || p == nil {
return
}
logger.Logger.Trace("(this *ScenePolicyRichBlessed) OnPlayerReturn, GetSceneId()=", s.GetSceneId(), " player=", p.Name)
if sceneEx, ok := s.GetExtraData().(*RichBlessedSceneData); ok {
if playerEx, ok := p.GetExtraData().(*RichBlessedPlayerData); ok {
//if p.IsMarkFlag(base.PlayerState_Auto) {
// p.UnmarkFlag(base.PlayerState_Auto)
// p.SyncFlag()
//}
//发送房间信息给自己
RichBlessedSendRoomInfo(s, sceneEx, playerEx)
s.FirePlayerEvent(p, base.PlayerEventReturn, nil)
}
}
}
func RichBlessedSendRoomInfo(s *base.Scene, sceneEx *RichBlessedSceneData, playerEx *RichBlessedPlayerData) {
pack := RichBlessedCreateRoomInfoPacket(s, sceneEx, playerEx)
logger.Logger.Trace("RoomInfo: ", pack)
playerEx.SendToClient(int(protocol.RBPID_PACKET_RICHBLESSED_SCRBRoomInfo), pack)
}
func RichBlessedCreateRoomInfoPacket(s *base.Scene, sceneEx *RichBlessedSceneData, playerEx *RichBlessedPlayerData) interface{} {
//房间信息
pack := &protocol.SCRBRoomInfo{
RoomId: proto.Int(s.SceneId),
GameId: proto.Int(s.GameId),
RoomMode: proto.Int(s.SceneMode),
SceneType: proto.Int(s.SceneType),
Params: s.Params,
NumOfGames: proto.Int(sceneEx.NumOfGames),
State: proto.Int(s.SceneState.GetState()),
ParamsEx: common.Int64ToInt32(s.DbGameFree.OtherIntParams), //s.GetParamsEx(),
//BetLimit: s.DbGameFree.BetLimit,
NowGameState: proto.Int(playerEx.gameState),
BetIdx: proto.Int(playerEx.betIdx),
FreeAllWin: proto.Int64(playerEx.freewinCoin),
SmallJackpot: proto.Int64(playerEx.oneBetCoin * richblessed.JkEleNumRate[richblessed.BlueGirl]),
MiddleJackpot: proto.Int64(playerEx.oneBetCoin * richblessed.JkEleNumRate[richblessed.BlueBoy]),
BigJackpot: proto.Int64(playerEx.oneBetCoin * richblessed.JkEleNumRate[richblessed.GoldGirl]),
GrandJackpot: proto.Int64(playerEx.oneBetCoin * richblessed.JkEleNumRate[richblessed.GoldBoy]),
WinEleCoin: proto.Int64(playerEx.winCoin),
WinRate: proto.Int64(playerEx.winLineRate),
FreeNum: proto.Int64(int64(playerEx.freeTimes)),
AddFreeNum: proto.Int64(int64(playerEx.addfreeTimes)),
WinFreeTimes: proto.Int32(int32(playerEx.nowFreeTimes)),
JackpotEle: proto.Int32(playerEx.result.JackpotEle),
WinJackpot: proto.Int64(playerEx.JackwinCoin),
GameFreeId: proto.Int32(s.DbGameFree.Id),
}
if playerEx.oneBetCoin == 0 && len(s.DbGameFree.GetOtherIntParams()) != 0 { // 初始化客户端jack显示
oneBetCoin := int64(s.DbGameFree.GetOtherIntParams()[0] / richblessed.LineNum)
pack.SmallJackpot = oneBetCoin * richblessed.JkEleNumRate[richblessed.BlueGirl]
pack.MiddleJackpot = oneBetCoin * richblessed.JkEleNumRate[richblessed.BlueBoy]
pack.BigJackpot = oneBetCoin * richblessed.JkEleNumRate[richblessed.GoldGirl]
pack.GrandJackpot = oneBetCoin * richblessed.JkEleNumRate[richblessed.GoldBoy]
}
//自己的信息
if playerEx != nil {
pd := &protocol.RBPlayerData{
SnId: proto.Int32(playerEx.SnId),
Name: proto.String(playerEx.Name),
Head: proto.Int32(playerEx.Head),
Sex: proto.Int32(playerEx.Sex),
Coin: proto.Int64(playerEx.Coin),
Pos: proto.Int(playerEx.Pos),
Flag: proto.Int(playerEx.GetFlag()),
City: proto.String(playerEx.City),
HeadOutLine: proto.Int32(playerEx.HeadOutLine),
VIP: proto.Int32(playerEx.VIP),
}
pack.Player = pd
}
if playerEx.result != nil {
pack.Cards = playerEx.result.EleValue
var wl []*protocol.RichWinLine
for _, r := range playerEx.result.WinLine {
wl = append(wl, &protocol.RichWinLine{
Poss: r.Poss,
})
}
pack.WinLines = wl
}
proto.SetDefaults(pack)
return pack
}
func (this *ScenePolicyRichBlessed) OnPlayerOp(s *base.Scene, p *base.Player, opcode int, params []int64) bool {
if s == nil || p == nil {
return false
}
logger.Logger.Trace("(this *ScenePolicyRichBlessed) OnPlayerOp, sceneId=", s.GetSceneId(), " player=", p.SnId, " opcode=", opcode, " params=", params)
if s.GetSceneState() != nil {
if s.GetSceneState().OnPlayerOp(s, p, opcode, params) {
p.SetLastOPTimer(time.Now())
return true
}
return false
}
return true
}
func (this *ScenePolicyRichBlessed) OnPlayerEvent(s *base.Scene, p *base.Player, evtcode int, params []int64) {
if s == nil || p == nil {
return
}
logger.Logger.Trace("(this *ScenePolicyRichBlessed) OnPlayerEvent, sceneId=", s.GetSceneId(), " player=", p.SnId, " eventcode=", evtcode, " params=", params)
if s.GetSceneState() != nil {
s.GetSceneState().OnPlayerEvent(s, p, evtcode, params)
}
}
// 当前状态能否换桌
func (this *ScenePolicyRichBlessed) 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 false
}
// 状态基类
type SceneBaseStateRichBlessed struct {
}
func (this *SceneBaseStateRichBlessed) GetTimeout(s *base.Scene) int {
if sceneEx, ok := s.GetExtraData().(*RichBlessedSceneData); ok {
return int(time.Now().Sub(sceneEx.GetStateStartTime()) / time.Second)
}
return 0
}
func (this *SceneBaseStateRichBlessed) CanChangeTo(s base.SceneState) bool {
return true
}
// 当前状态能否换桌
func (this *SceneBaseStateRichBlessed) CanChangeCoinScene(s *base.Scene, p *base.Player) bool {
return true
}
func (this *SceneBaseStateRichBlessed) OnEnter(s *base.Scene) {
if sceneEx, ok := s.GetExtraData().(*RichBlessedSceneData); ok {
sceneEx.SetStateStartTime(time.Now())
}
}
func (this *SceneBaseStateRichBlessed) OnLeave(s *base.Scene) {}
func (this *SceneBaseStateRichBlessed) OnTick(s *base.Scene) {
if time.Now().Sub(s.GameStartTime) > time.Second*3 {
if sceneEx, ok := s.ExtraData.(*RichBlessedSceneData); ok {
//pack := &protocol.SCRBPrize{
// PrizePool: proto.Int64(sceneEx.jackpot.GetTotalSmall() / 10000),
//}
//proto.SetDefaults(pack)
////logger.Logger.Trace("SCRBPrize: ", pack)
//s.Broadcast(int(protocol.RBPID_PACKET_RICHBLESSED_SCRBPrize), pack, 0)
for _, p := range sceneEx.players {
if p.IsOnLine() {
p.leaveTime = 0
continue
}
p.leaveTime++
if p.leaveTime < 60*2 {
continue
}
//踢出玩家
sceneEx.PlayerLeave(p.Player, common.PlayerLeaveReason_LongTimeNoOp, true)
}
}
s.GameStartTime = time.Now()
}
if sceneEx, ok := s.ExtraData.(*RichBlessedSceneData); ok {
//for _, p := range sceneEx.players {
// //游戏次数达到目标值
// todayGamefreeIDSceneData, _ := p.GetDaliyGameData(int(sceneEx.DbGameFree.GetId()))
// if !p.IsRob &&
// todayGamefreeIDSceneData != nil &&
// sceneEx.DbGameFree.GetPlayNumLimit() != 0 &&
// todayGamefreeIDSceneData.GameTimes >= int64(sceneEx.DbGameFree.GetPlayNumLimit()) {
// s.PlayerLeave(p.Player, common.PlayerLeaveReason_GameTimes, true)
// }
//}
if sceneEx.CheckNeedDestroy() {
for _, player := range sceneEx.players {
if !player.IsRob {
sceneEx.PlayerLeave(player.Player, common.PlayerLeaveReason_OnDestroy, true)
}
}
if s.GetRealPlayerCnt() == 0 {
sceneEx.SceneDestroy(true)
}
}
}
//if sceneEx, ok := s.GetExtraData().(*RichBlessedSceneData); ok {
// if time.Now().Sub(sceneEx.mqLogTime) >= time.Minute*1 {
// now := time.Now()
// sceneEx.mqLogTime = now.Add(-time.Second * time.Duration(now.Second()))
//
// waterVal := base.CoinPoolMgr.LoadCoin(s.GetGameFreeId(), s.Platform, s.GroupId)
// waterVal = int64(math.Floor(float64(waterVal) / float64(richblessed.NowByte)))
//
// jkVal1 := int64(math.Floor(float64(sceneEx.jackpot.GetTotalSmall()) / float64(richblessed.NowByte)))
// jkVal2 := int64(math.Floor(float64(sceneEx.jackpot.GetTotalMiddle()) / float64(richblessed.NowByte)))
// jkVal3 := int64(math.Floor(float64(sceneEx.jackpot.GetTotalBig()) / float64(richblessed.NowByte)))
// jkVal4 := int64(math.Floor(float64(sceneEx.jackpot.GetTotalGrand()) / float64(richblessed.NowByte)))
//
// base.JackPotMgr.WJackPotUpdate(sceneEx.GetGameFreeId(), sceneEx.Platform, waterVal, jkVal1, jkVal2, jkVal3, jkVal4)
// }
//}
}
func (this *SceneBaseStateRichBlessed) OnPlayerOp(s *base.Scene, p *base.Player, opcode int, params []int64) bool {
return false
}
func (this *SceneBaseStateRichBlessed) OnPlayerEvent(s *base.Scene, p *base.Player, evtcode int, params []int64) {
}
// ////////////////////////////////////////////////////////////
// 开始状态
// ////////////////////////////////////////////////////////////
type SceneStateStartRichBlessed struct {
SceneBaseStateRichBlessed
}
func (this *SceneStateStartRichBlessed) GetState() int {
return richblessed.RichBlessedStateStart
}
func (this *SceneStateStartRichBlessed) CanChangeTo(s base.SceneState) bool {
return false
}
// 当前状态能否换桌
func (this *SceneStateStartRichBlessed) CanChangeCoinScene(s *base.Scene, p *base.Player) bool {
if playerEx, ok := p.GetExtraData().(*RichBlessedPlayerData); ok {
if playerEx.IsOnLine() && playerEx.freeTimes > 0 {
return false
}
}
return true
}
func (this *SceneStateStartRichBlessed) GetTimeout(s *base.Scene) int {
return 0
}
func (this *SceneStateStartRichBlessed) OnEnter(s *base.Scene) {
this.SceneBaseStateRichBlessed.OnEnter(s)
if sceneEx, ok := s.GetExtraData().(*RichBlessedSceneData); ok {
sceneEx.SetGameNowTime(time.Now())
}
}
// 状态离开时
func (this *SceneStateStartRichBlessed) OnLeave(s *base.Scene) {
this.SceneBaseStateRichBlessed.OnLeave(s)
logger.Logger.Tracef("(this *SceneStateStartRichBlessed) OnLeave, sceneid=%v", s.GetSceneId())
}
// 玩家操作
func (this *SceneStateStartRichBlessed) OnPlayerOp(s *base.Scene, p *base.Player, opcode int, params []int64) bool {
logger.Logger.Tracef("(this *SceneStateStartRichBlessed) OnPlayerOp, sceneid=%v params=%v", s.GetSceneId(), params)
if this.SceneBaseStateRichBlessed.OnPlayerOp(s, p, opcode, params) {
return true
}
if sceneEx, ok := s.GetExtraData().(*RichBlessedSceneData); ok {
if playerEx, ok := p.GetExtraData().(*RichBlessedPlayerData); ok {
switch opcode {
case richblessed.RichBlessedPlayerOpStart:
playerEx.Clear()
if len(params) > 0 {
//只有开始算操作
p.LastOPTimer = time.Now()
idx := int(params[0])
if len(sceneEx.DbGameFree.GetOtherIntParams()) <= idx {
pack := &protocol.SCRichBlessedOp{
OpCode: proto.Int(opcode),
OpRetCode: proto.Int(3),
}
playerEx.SendToClient(int(protocol.RBPID_PACKET_RICHBLESSED_SCRichBlessedOp), pack)
return false
}
if playerEx.freeTimes > 0 {
playerEx.gameState = richblessed.FreeGame
playerEx.freeTimes--
playerEx.nowFreeTimes++
}
//水池上下文环境
playerEx.cpCtx = base.CoinPoolMgr.GetCoinPoolCtx(sceneEx.Platform, sceneEx.GetGameFreeId(), sceneEx.GroupId)
norms, frees, JACKRand, key := sceneEx.GetEleWeight(playerEx.WBState)
playerEx.weightPos = key
if playerEx.gameState == richblessed.Normal {
logger.Logger.Tracef("(this *SceneStateStartRichBlessed) OnPlayerOp, 下注 %v %v %v", playerEx.betCoin, playerEx.maxbetCoin, playerEx.oneBetCoin)
playerEx.betIdx = idx
playerEx.betCoin = int64(sceneEx.DbGameFree.GetOtherIntParams()[idx])
maxidx := len(sceneEx.DbGameFree.GetOtherIntParams()) - 1
playerEx.maxbetCoin = int64(sceneEx.DbGameFree.GetOtherIntParams()[maxidx])
playerEx.oneBetCoin = playerEx.betCoin / richblessed.LineNum // 单注
playerEx.noWinTimes++
if playerEx.Coin < int64(s.DbGameFree.GetBetLimit()) {
//押注限制(低于该值不能押注)
pack := &protocol.SCRichBlessedOp{
OpCode: proto.Int(opcode),
OpRetCode: proto.Int(2),
}
playerEx.SendToClient(int(protocol.RBPID_PACKET_RICHBLESSED_SCRichBlessedOp), pack)
return false
}
if playerEx.betCoin > playerEx.Coin {
//金币不足
pack := &protocol.SCRichBlessedOp{
OpCode: proto.Int(opcode),
OpRetCode: proto.Int(1),
}
playerEx.SendToClient(int(protocol.RBPID_PACKET_RICHBLESSED_SCRichBlessedOp), pack)
return false
}
playerEx.CurrentBet = playerEx.betCoin
playerEx.CurrentTax = 0
//SysProfitCoinMgr.Add(sceneEx.sysProfitCoinKey, playerEx.betCoin, -playerEx.betCoin)
//没有免费次数 扣钱
p.Statics(s.KeyGameId, s.KeyGamefreeId, -playerEx.betCoin, false)
playerEx.AddCoin(-playerEx.betCoin, common.GainWay_HundredSceneLost, 0, "system", s.GetSceneName())
sceneEx.AddPrizeCoin(playerEx) // 12%jack
sceneEx.CreateResult(norms, playerEx)
playerEx.isFTest++
if playerEx.isFTest >= 100000 {
playerEx.isFTest = 0
}
//if !playerEx.nottest {
// playerEx.result.EleValue = []int32{1, 0, 1, 0, 5, 6, 2, 7, 7, 9, 9, 7, 4, 8, 7} //三锣免费
//}
} else {
// 免费游戏
if playerEx.freeTimes >= 100 {
playerEx.CreateLevResult(frees) // 没有铜锣概率
playerEx.freeTimes = 0
} else {
sceneEx.CreateResult(frees, playerEx)
}
//if playerEx.freeTimes == 3 && !playerEx.nottest1 { // 免费在中一次
// playerEx.result.EleValue = []int32{1, 0, 1, 0, 5, 6, 2, 7, 7, 9, 9, 7, 4, 8, 7} //三锣免费
// playerEx.nottest1 = true
//}
}
sceneEx.Win(playerEx)
if sceneEx.CanJACKPOT(playerEx, playerEx.betCoin, playerEx.maxbetCoin, JACKRand) { // 中奖 包含CreateJACKPOT 下注不存在越界问题
playerEx.gameState = richblessed.JackGame
// sceneEx.JACKPOTWin(playerEx)
}
//发送结算
sceneEx.SendBilled(playerEx)
if !playerEx.isFWinJackpot {
sceneEx.SaveLog(playerEx, 0)
}
}
case richblessed.RichBlessedPlayerOpSwitch:
if len(params) > 0 && playerEx.freeTimes == 0 {
idx := int(params[0])
if len(sceneEx.DbGameFree.GetOtherIntParams()) > idx {
playerEx.betIdx = idx
playerEx.betCoin = int64(sceneEx.DbGameFree.GetOtherIntParams()[idx])
playerEx.oneBetCoin = playerEx.betCoin / richblessed.LineNum
pack := &protocol.SCRichBlessedOp{
OpCode: proto.Int(opcode),
OpRetCode: proto.Int(4),
}
for i := int32(0); i != richblessed.JackMax; i++ {
pack.Params = append(pack.Params, playerEx.oneBetCoin*richblessed.JkEleNumRate[i])
}
playerEx.SendToClient(int(protocol.RBPID_PACKET_RICHBLESSED_SCRichBlessedOp), pack)
logger.Logger.Tracef("(this *SceneStateStartRichBlessed) OnPlayerOp, sceneid=%v pack=%v", s.GetSceneId(), pack)
}
}
case richblessed.RichBlessedPlayerOpJack: // jack领奖 注意不要再次结算wincoin
if !playerEx.isFWinJackpot {
pack := &protocol.SCRichBlessedOp{
OpCode: proto.Int(opcode),
OpRetCode: proto.Int(3),
}
playerEx.SendToClient(int(protocol.RBPID_PACKET_RICHBLESSED_SCRichBlessedOp), pack)
return false
}
playerEx.JackMidCards = append(playerEx.JackMidCards, params...)
sceneEx.JACKPOTWin(playerEx)
//发送结算
sceneEx.SendJACKPOTBilled(playerEx)
sceneEx.SaveLog(playerEx, 0)
playerEx.Clear() // 小游戏模式结束
}
}
}
return true
}
// 玩家事件
func (this *SceneStateStartRichBlessed) OnPlayerEvent(s *base.Scene, p *base.Player, evtcode int, params []int64) {
logger.Logger.Trace("(this *SceneStateStartRichBlessed) OnPlayerEvent, sceneId=", s.GetSceneId(), " player=", p.SnId, " evtcode=", evtcode)
this.SceneBaseStateRichBlessed.OnPlayerEvent(s, p, evtcode, params)
if _, ok := s.GetExtraData().(*RichBlessedSceneData); ok {
switch evtcode {
case base.PlayerEventEnter:
/*
pack := &protocol.SCRBPrize{
PrizePool: proto.Int64(sceneEx.jackpot.GetTotalSmall() / 10000),
}
proto.SetDefaults(pack)
//logger.Logger.Trace("SCRBPrize: ", pack)
p.SendToClient(int(protocol.RBPID_PACKET_RICHBLESSED_SCRBPrize), pack)
*/
}
}
}
func (this *SceneStateStartRichBlessed) OnTick(s *base.Scene) {
this.SceneBaseStateRichBlessed.OnTick(s)
}
// //////////////////////////////////////////////////////////////////////////////
func (this *ScenePolicyRichBlessed) RegisteSceneState(state base.SceneState) {
if state == nil {
return
}
stateid := state.GetState()
if stateid < 0 || stateid >= richblessed.RichBlessedStateMax {
return
}
this.states[stateid] = state
}
func (this *ScenePolicyRichBlessed) GetSceneState(s *base.Scene, stateid int) base.SceneState {
if stateid >= 0 && stateid < richblessed.RichBlessedStateMax {
return this.states[stateid]
}
return nil
}
func init() {
//主状态
ScenePolicyRichBlessedSington.RegisteSceneState(&SceneStateStartRichBlessed{})
core.RegisteHook(core.HOOK_BEFORE_START, func() error {
base.RegisteScenePolicy(common.GameId_Richblessed, richblessed.RoomMode_Classic, ScenePolicyRichBlessedSington)
return nil
})
}

View File

@ -0,0 +1,55 @@
package tamquoc
import (
"mongo.games.com/goserver/core/logger"
"mongo.games.com/goserver/core/netlib"
"mongo.games.com/game/common"
"mongo.games.com/game/gamesrv/base"
"mongo.games.com/game/protocol/tamquoc"
)
// 百战成神的操作
type CSTamQuocOpPacketFactory struct {
}
type CSTamQuocOpHandler struct {
}
func (this *CSTamQuocOpPacketFactory) CreatePacket() interface{} {
pack := &tamquoc.CSTamQuocOp{}
return pack
}
func (this *CSTamQuocOpHandler) Process(s *netlib.Session, packetid int, data interface{}, sid int64) error {
logger.Logger.Trace("CSTamQuocOpHandler Process recv ", data)
if csTamQuocOp, ok := data.(*tamquoc.CSTamQuocOp); ok {
p := base.PlayerMgrSington.GetPlayer(sid)
if p == nil {
logger.Logger.Warn("CSTamQuocOpHandler p == nil")
return nil
}
scene := p.GetScene()
if scene == nil {
logger.Logger.Warn("CSTamQuocOpHandler p.scene == nil")
return nil
}
if scene.GameId != common.GameId_TamQuoc {
logger.Logger.Error("CSTamQuocOpHandler gameId Error ", scene.GameId)
return nil
}
if !scene.HasPlayer(p) {
return nil
}
sp := scene.GetScenePolicy()
if sp != nil {
sp.OnPlayerOp(scene, p, int(csTamQuocOp.GetOpCode()), csTamQuocOp.GetParams())
}
return nil
}
return nil
}
func init() {
// 百战成神的操作
common.RegisterHandler(int(tamquoc.TamQuocPacketID_PACKET_CS_TAMQUOC_PLAYEROP), &CSTamQuocOpHandler{})
netlib.RegisterFactory(int(tamquoc.TamQuocPacketID_PACKET_CS_TAMQUOC_PLAYEROP), &CSTamQuocOpPacketFactory{})
}

112
gamesrv/tamquoc/constant.go Normal file
View File

@ -0,0 +1,112 @@
package tamquoc
import (
"encoding/json"
"time"
"mongo.games.com/game/model"
)
// 玩家游戏数据索引
const (
TamQuocFreeTimes int = iota //0 当前剩余免费次数
TamQuocBonusTime //1 上一次小游戏的时间
TamQuocIndexMax
)
// 通知奖池变化的时间间隔
const jackpotNoticeInterval = time.Second
// 场景状态
const (
TamQuocSceneStateStart int = iota //开始游戏
TamQuocSceneStateMax
)
// 玩家操作
const (
TamQuocPlayerOpStart int = iota //游戏
TamQuocPlayerHistory // 游戏记录
TamQuocBurstHistory // 爆奖记录
TamQuocBonusGame // 小游戏
TamQuocBonusGameRecord // 小游戏重连
)
// 小游戏超时时间
const TamQuocBonusGameTimeout = time.Second * 60
// 小游戏操作时间
const TamQuocBonusGamePickTime = time.Second * 15
type GameResultLog struct {
BaseResult *model.SlotBaseResultType
AllLine int32 //线路数
UserName string //昵称
BetLines []int64 //下注的线
//Cards [][]int32 // 消除前后的牌消除前15张消除后15张...
WinLines []int // 赢分的线
}
// 百战成神解析的数据
type TamQuocGameNoteData struct {
Source int32
Data *GameResultLog
}
// 百战成神游戏记录
func UnMarshalTamQuocGameNote(data string) (roll interface{}, err error) {
gnd := &TamQuocGameNoteData{}
if err := json.Unmarshal([]byte(data), gnd); err != nil {
return nil, err
}
roll = gnd.Data
return
}
var DebugData = [][]int{
{
1, 1, 1, 5, 5,
1, 1, 1, 3, 4,
6, 7, 2, 3, 5,
},
{
1, 1, 1, 1, 5,
1, 1, 1, 1, 4,
6, 7, 2, 3, 5,
},
{
1, 1, 1, 1, 1,
1, 1, 1, 1, 1,
6, 7, 2, 3, 5,
},
{
2, 2, 2, 2, 2,
2, 2, 2, 2, 2,
2, 2, 2, 2, 2,
},
{
3, 3, 3, 3, 3,
3, 3, 3, 3, 3,
3, 3, 3, 3, 3,
},
{
4, 4, 4, 4, 4,
4, 4, 4, 4, 4,
4, 4, 4, 4, 4,
},
{
5, 5, 5, 5, 5,
5, 5, 5, 5, 5,
5, 5, 5, 5, 5,
},
{
6, 6, 6, 6, 6,
6, 6, 6, 6, 6,
6, 6, 6, 6, 6,
},
{
7, 7, 7, 7, 7,
7, 7, 7, 7, 7,
7, 7, 7, 7, 7,
},
}

View File

@ -0,0 +1,152 @@
package tamquoc
import (
"encoding/json"
"math/rand"
"time"
"mongo.games.com/goserver/core/timer"
rule "mongo.games.com/game/gamerule/tamquoc"
"mongo.games.com/game/gamesrv/base"
"mongo.games.com/game/model"
"mongo.games.com/game/protocol/tamquoc"
)
type TamQuocPlayerData struct {
*base.Player
spinID int64 //当前旋转ID
score int32 //单线押注数
freeTimes int32 //免费转动次数
cards []int32 //15张牌
totalPriceBonus int64 //小游戏奖金
bonusTimerHandle timer.TimerHandle //托管handle
//RollGameType *model.TamQuocType //记录信息
RollGameType *GameResultLog //记录信息
enterGameCoin int64 //玩家进入初始金币
betLines []int64 //下注的选线
taxCoin int64 //本局税收
winCoin int64 //本局收税前赢的钱
linesWinCoin int64 //本局中奖线赢得钱
jackpotWinCoin int64 //本局奖池赢的钱
smallGameWinCoin int64 //本局小游戏赢的钱
currentLogId string //爆奖玩家logid
leavetime int32 //用户离开时间
bonusGameTime int64 //上一次小游戏的时间
bonusGameStartTime time.Time // 小游戏开始时间
bonusGamePickPos []int32 // 小游戏位置
bonusGameCanPickNum int // 小游戏点击次数
bonusGame tamquoc.TamQuocBonusGameInfo
billedData *tamquoc.GameBilledData
DebugGame bool //测试
TestNum int
}
// 玩家初始化
func (this *TamQuocPlayerData) init(s *base.Scene) {
this.Clean()
this.score = 0
this.freeTimes = 0
//this.RollGameType = &model.TamQuocType{}
this.RollGameType = &GameResultLog{}
this.RollGameType.BaseResult = &model.SlotBaseResultType{}
this.enterGameCoin = this.Coin
this.currentLogId = ""
this.billedData = &tamquoc.GameBilledData{}
this.DebugGame = true
this.TestNum = 0
initCards := rule.GenerateSlotsData_v2(rule.SYMBOL2)
for _, card := range initCards {
this.cards = append(this.cards, int32(card))
}
// 加载玩家游戏数据
if this.GDatas == nil {
this.GDatas = make(map[string]*model.PlayerGameInfo)
}
if d, exist := this.GDatas[s.KeyGamefreeId]; exist {
gLen := len(d.Data)
if gLen < TamQuocIndexMax {
for i := gLen; i < TamQuocIndexMax; i++ {
d.Data = append(d.Data, 0)
}
}
} else {
pgd := &model.PlayerGameInfo{
Data: make([]int64, TamQuocIndexMax, TamQuocIndexMax),
}
this.GDatas[s.KeyGamefreeId] = pgd
}
this.LoadPlayerGameData(s.KeyGamefreeId)
//线条全选
if len(this.betLines) == 0 {
this.betLines = rule.AllBetLines
}
this.bonusGamePickPos = make([]int32, 2)
}
// 玩家清理数据
func (this *TamQuocPlayerData) Clean() {
for i := 0; i < len(this.cards); i++ {
this.cards[i] = -1
}
this.winCoin = 0
this.taxCoin = 0
this.linesWinCoin = 0
this.jackpotWinCoin = 0
this.smallGameWinCoin = 0
}
// 加载玩家游戏数据
func (this *TamQuocPlayerData) LoadPlayerGameData(gameFreeId string) {
if d, exist := this.GDatas[gameFreeId]; exist {
this.freeTimes = int32(d.Data[TamQuocFreeTimes])
this.bonusGameTime = d.Data[TamQuocBonusTime]
if this.freeTimes > 0 && len(d.DataEx) != 0 {
json.Unmarshal(d.DataEx, &this.betLines)
}
}
}
// 存储玩家游戏数据
func (this *TamQuocPlayerData) SavePlayerGameData(gameFreeId string) {
if d, exist := this.GDatas[gameFreeId]; exist {
d.Data[TamQuocFreeTimes] = int64(this.freeTimes)
d.Data[TamQuocBonusTime] = this.bonusGameTime
d.DataEx, _ = json.Marshal(this.betLines)
}
}
// 黑白名单的限制是否生效
func (this *TamQuocPlayerData) CheckBlackWriteList(isWin bool) bool {
if isWin && this.BlackLevel > 0 && this.BlackLevel <= 10 {
if rand.Int31n(100) < this.BlackLevel*10 {
return true
}
} else if !isWin && this.WhiteLevel > 0 && this.WhiteLevel <= 10 {
if rand.Int31n(100) < this.WhiteLevel*10 {
return true
}
}
return false
}
// 玩家是否是新手
func (this *TamQuocPlayerData) IsFNovice(keyGameId string) {
if f, ok := this.IsFoolPlayer[keyGameId]; ok {
if !f {
return
}
} else {
this.IsFoolPlayer[keyGameId] = true
return
}
if data, ok := this.GDatas[keyGameId]; ok {
if data.Statics.GameTimes < 100 && data.Statics.TotalOut-data.Statics.TotalIn <= 2000000 {
return
}
this.IsFoolPlayer[keyGameId] = false
}
}

View File

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

View File

@ -0,0 +1,843 @@
package tamquoc
import (
"math"
"strconv"
"time"
"mongo.games.com/goserver/core"
"mongo.games.com/goserver/core/basic"
"mongo.games.com/goserver/core/logger"
"mongo.games.com/goserver/core/task"
"mongo.games.com/goserver/core/timer"
"mongo.games.com/game/common"
rule "mongo.games.com/game/gamerule/tamquoc"
"mongo.games.com/game/gamesrv/base"
"mongo.games.com/game/model"
"mongo.games.com/game/proto"
"mongo.games.com/game/protocol/server"
"mongo.games.com/game/protocol/tamquoc"
)
////////////////////////////////////////////////////////////////////////////////
//百战成神
////////////////////////////////////////////////////////////////////////////////
// 房间内主要逻辑
var ScenePolicyTamQuocSington = &ScenePolicyTamQuoc{}
type ScenePolicyTamQuoc struct {
base.BaseScenePolicy
states [TamQuocSceneStateMax]base.SceneState
}
// 创建场景扩展数据
func (this *ScenePolicyTamQuoc) CreateSceneExData(s *base.Scene) interface{} {
sceneEx := NewTamQuocSceneData(s)
if sceneEx != nil {
if sceneEx.init() {
s.ExtraData = sceneEx
}
}
return sceneEx
}
// 创建玩家扩展数据
func (this *ScenePolicyTamQuoc) CreatePlayerExData(s *base.Scene, p *base.Player) interface{} {
playerEx := &TamQuocPlayerData{Player: p}
if playerEx != nil {
p.ExtraData = playerEx
}
return playerEx
}
// 场景开启事件
func (this *ScenePolicyTamQuoc) OnStart(s *base.Scene) {
logger.Logger.Trace("(this *ScenePolicyTamQuoc) OnStart, sceneId=", s.SceneId)
sceneEx := NewTamQuocSceneData(s)
if sceneEx != nil {
if sceneEx.init() {
s.ExtraData = sceneEx
s.ChangeSceneState(TamQuocSceneStateStart) //改变当前的玩家状态
}
}
}
// 场景关闭事件
func (this *ScenePolicyTamQuoc) OnStop(s *base.Scene) {
logger.Logger.Trace("(this *ScenePolicyTamQuoc) OnStop , sceneId=", s.SceneId)
if sceneEx, ok := s.ExtraData.(*TamQuocSceneData); ok {
sceneEx.SaveData(true)
}
}
// 场景心跳事件
func (this *ScenePolicyTamQuoc) OnTick(s *base.Scene) {
if s == nil {
return
}
if s.SceneState != nil {
s.SceneState.OnTick(s)
}
}
// 玩家进入事件
func (this *ScenePolicyTamQuoc) OnPlayerEnter(s *base.Scene, p *base.Player) {
if s == nil || p == nil {
return
}
logger.Logger.Trace("(this *ScenePolicyTamQuoc) OnPlayerEnter, sceneId=", s.SceneId, " player=", p.SnId)
if sceneEx, ok := s.ExtraData.(*TamQuocSceneData); ok {
playerEx := &TamQuocPlayerData{Player: p}
playerEx.init(s) // 玩家当前信息初始化
playerEx.score = sceneEx.DbGameFree.GetBaseScore() // 底注
sceneEx.players[p.SnId] = playerEx
p.ExtraData = playerEx
TamQuocSendRoomInfo(s, p, sceneEx, playerEx, nil)
s.FirePlayerEvent(p, base.PlayerEventEnter, nil) //回调会调取 onPlayerEvent事件
}
}
// 玩家离开事件
func (this *ScenePolicyTamQuoc) OnPlayerLeave(s *base.Scene, p *base.Player, reason int) {
if s == nil || p == nil {
return
}
logger.Logger.Trace("(this *ScenePolicyTamQuoc) OnPlayerLeave, sceneId=", s.SceneId, " player=", p.SnId)
if sceneEx, ok := s.ExtraData.(*TamQuocSceneData); ok {
if this.CanChangeCoinScene(s, p) {
if playerEx, ok := p.ExtraData.(*TamQuocPlayerData); ok {
playerEx.SavePlayerGameData(strconv.Itoa(int(s.GetGameFreeId())))
}
sceneEx.OnPlayerLeave(p, reason)
s.FirePlayerEvent(p, base.PlayerEventLeave, []int64{int64(reason)})
}
}
}
// 玩家掉线
func (this *ScenePolicyTamQuoc) OnPlayerDropLine(s *base.Scene, p *base.Player) {
if s == nil || p == nil {
return
}
logger.Logger.Trace("(this *ScenePolicyTamQuoc) OnPlayerDropLine, sceneId=", s.SceneId, " player=", p.SnId)
s.FirePlayerEvent(p, base.PlayerEventDropLine, nil)
if sceneEx, ok := s.ExtraData.(*TamQuocSceneData); ok {
if sceneEx.Gaming {
return
}
}
}
// 玩家重连
func (this *ScenePolicyTamQuoc) OnPlayerRehold(s *base.Scene, p *base.Player) {
if s == nil || p == nil {
return
}
logger.Logger.Trace("(this *ScenePolicyTamQuoc) OnPlayerRehold, sceneId=", s.SceneId, " player=", p.Name)
//if sceneEx, ok := s.ExtraData.(*TamQuocSceneData); ok {
// if playerEx, ok := p.ExtraData.(*TamQuocPlayerData); ok {
// //发送房间信息给自己
// TamQuocSendRoomInfo(s, p, sceneEx, playerEx)
s.FirePlayerEvent(p, base.PlayerEventRehold, nil)
// }
//}
}
// 玩家重连
func (this *ScenePolicyTamQuoc) OnPlayerReturn(s *base.Scene, p *base.Player) {
if s == nil || p == nil {
return
}
logger.Logger.Trace("(this *ScenePolicyTamQuoc) OnPlayerReturn, sceneId=", s.SceneId, " player=", p.Name)
if sceneEx, ok := s.ExtraData.(*TamQuocSceneData); ok {
if playerEx, ok := p.ExtraData.(*TamQuocPlayerData); ok {
//发送房间信息给自己
TamQuocSendRoomInfo(s, p, sceneEx, playerEx, playerEx.billedData)
s.FirePlayerEvent(p, base.PlayerEventReturn, nil)
}
}
}
// 玩家操作
func (this *ScenePolicyTamQuoc) OnPlayerOp(s *base.Scene, p *base.Player, opcode int, params []int64) bool {
if s == nil || p == nil {
return false
}
if s.SceneState != nil {
return s.SceneState.OnPlayerOp(s, p, opcode, params)
}
return true
}
// 玩家事件
func (this *ScenePolicyTamQuoc) OnPlayerEvent(s *base.Scene, p *base.Player, evtcode int, params []int64) {
if s == nil || p == nil {
return
}
if s.SceneState != nil {
s.SceneState.OnPlayerEvent(s, p, evtcode, params)
}
}
// 是否完成了整个牌局
func (this *ScenePolicyTamQuoc) IsCompleted(s *base.Scene) bool { return false }
// 是否可以强制开始
func (this *ScenePolicyTamQuoc) IsCanForceStart(s *base.Scene) bool { return true }
// 当前状态能否换桌
func (this *ScenePolicyTamQuoc) CanChangeCoinScene(s *base.Scene, p *base.Player) bool {
if s == nil || p == nil {
return true
}
if s.SceneState != nil {
return s.SceneState.CanChangeCoinScene(s, p)
}
return true
}
func (this *ScenePolicyTamQuoc) RegisteSceneState(state base.SceneState) {
if state == nil {
return
}
stateid := state.GetState()
if stateid < 0 || stateid >= TamQuocSceneStateMax {
return
}
this.states[stateid] = state
}
func (this *ScenePolicyTamQuoc) GetSceneState(s *base.Scene, stateid int) base.SceneState {
if stateid >= 0 && stateid < TamQuocSceneStateMax {
return ScenePolicyTamQuocSington.states[stateid]
}
return nil
}
func (this *ScenePolicyTamQuoc) GetJackPotVal(s *base.Scene) int64 {
if sceneEx, ok := s.ExtraData.(*TamQuocSceneData); ok {
if sceneEx.lastJackpotValue != sceneEx.jackpot.VirtualJK {
return sceneEx.jackpot.VirtualJK
}
}
return 0
}
func TamQuocSendRoomInfo(s *base.Scene, p *base.Player, sceneEx *TamQuocSceneData, playerEx *TamQuocPlayerData, data *tamquoc.GameBilledData) {
logger.Logger.Trace("-------------------发送房间消息 ", s.RoomId, p.SnId)
pack := &tamquoc.SCTamQuocRoomInfo{
RoomId: proto.Int(s.SceneId),
Creator: proto.Int32(s.Creator),
GameId: proto.Int(s.GameId),
RoomMode: proto.Int(s.GameMode),
Params: s.Params,
State: proto.Int(s.SceneState.GetState()),
Jackpot: proto.Int64(sceneEx.jackpot.VirtualJK),
GameFreeId: proto.Int32(s.GetDBGameFree().GetId()),
BilledData: data,
}
if playerEx != nil {
pd := &tamquoc.TamQuocPlayerData{
SnId: proto.Int32(playerEx.SnId),
Name: proto.String(playerEx.Name),
Head: proto.Int32(playerEx.Head),
Sex: proto.Int32(playerEx.Sex),
Coin: proto.Int64(playerEx.Coin),
HeadOutLine: proto.Int32(playerEx.HeadOutLine),
VIP: proto.Int32(playerEx.VIP),
}
pack.Players = append(pack.Players, pd)
//for _, value := range playerEx.cards {
// pack.Cards = append(pack.Cards, int32(value))
//}
pack.BetLines = playerEx.betLines
pack.FreeTimes = proto.Int32(playerEx.freeTimes)
pack.Chip = proto.Int32(s.DbGameFree.BaseScore)
pack.SpinID = proto.Int64(playerEx.spinID)
if playerEx.totalPriceBonus > 0 && playerEx.bonusGameStartTime.Add(TamQuocBonusGamePickTime).Before(time.Now()) {
playerEx.totalPriceBonus = 0
playerEx.bonusGamePickPos = make([]int32, 2)
// 取消定时器
if playerEx.bonusTimerHandle != timer.TimerHandle(0) {
timer.StopTimer(playerEx.bonusTimerHandle)
playerEx.bonusTimerHandle = timer.TimerHandle(0)
}
}
if playerEx.totalPriceBonus > 0 {
pack.TotalPriceBonus = proto.Int64(playerEx.totalPriceBonus)
playerEx.bonusGamePickPos[1] = int32(playerEx.bonusGameStartTime.Add(TamQuocBonusGamePickTime).Unix() - time.Now().Unix())
pack.ParamsEx = playerEx.bonusGamePickPos
pack.BonusGame = &playerEx.bonusGame
}
}
proto.SetDefaults(pack)
p.SendToClient(int(tamquoc.TamQuocPacketID_PACKET_SC_TAMQUOC_ROOMINFO), pack)
}
type SceneStateTamQuocStart struct {
}
// 获取当前场景状态
func (this *SceneStateTamQuocStart) GetState() int { return TamQuocSceneStateStart }
// 是否可以切换状态到
func (this *SceneStateTamQuocStart) CanChangeTo(s base.SceneState) bool { return true }
// 当前状态能否换桌
func (this *SceneStateTamQuocStart) CanChangeCoinScene(s *base.Scene, p *base.Player) bool {
if _, ok := p.ExtraData.(*TamQuocPlayerData); ok {
return true
}
return true
}
func (this *SceneStateTamQuocStart) GetTimeout(s *base.Scene) int { return 0 }
func (this *SceneStateTamQuocStart) OnEnter(s *base.Scene) {
if sceneEx, ok := s.ExtraData.(*TamQuocSceneData); ok {
logger.Logger.Tracef("(this *base.Scene) [%v] 场景状态进入 %v", s.SceneId, len(sceneEx.players))
sceneEx.StateStartTime = time.Now()
pack := &tamquoc.SCTamQuocRoomState{
State: proto.Int(this.GetState()),
}
proto.SetDefaults(pack)
s.Broadcast(int(tamquoc.TamQuocPacketID_PACKET_SC_TAMQUOC_ROOMSTATE), pack, 0)
}
}
func (this *SceneStateTamQuocStart) OnLeave(s *base.Scene) {}
func (this *SceneStateTamQuocStart) OnTick(s *base.Scene) {
if sceneEx, ok := s.ExtraData.(*TamQuocSceneData); ok {
sceneEx.AIAddJackPot()
sceneEx.AIBurstJackPot()
sceneEx.KickPlayerByTime()
}
}
func (this *SceneStateTamQuocStart) OnPlayerOp(s *base.Scene, p *base.Player, opcode int, params []int64) bool {
playerEx, ok := p.ExtraData.(*TamQuocPlayerData)
if !ok {
return false
}
sceneEx, ok := s.ExtraData.(*TamQuocSceneData)
if !ok {
return false
}
if sceneEx.CheckNeedDestroy() && playerEx.freeTimes <= 0 {
//离开有统计
sceneEx.PlayerLeave(playerEx.Player, common.PlayerLeaveReason_OnDestroy, true)
return false
}
switch opcode {
case TamQuocPlayerOpStart: //开始
//参数是否合法
//params 参数0底注后面跟客户端选择的线n条线(1<=n<=20)客户端线是从1开始算起1~20条线
if len(params) < 2 || len(params) > rule.LINENUM+1 {
this.OnPlayerSToCOp(s, p, playerEx.Pos, opcode, tamquoc.OpResultCode_OPRC_Error, params)
return false
}
//先做底注校验
if sceneEx.DbGameFree.GetBaseScore() != int32(params[0]) {
this.OnPlayerSToCOp(s, p, playerEx.Pos, opcode, tamquoc.OpResultCode_OPRC_Error, params)
return false
}
playerEx.score = int32(params[0]) // 单线押注数
// 小游戏未结束 不能进行下一次旋转
if playerEx.totalPriceBonus > 0 {
this.OnPlayerSToCOp(s, p, playerEx.Pos, opcode, tamquoc.OpResultCode_OPRC_Error, params)
return false
}
//判断线条是否重复,是否合法
lineFlag := make(map[int64]bool)
lineParams := make([]int64, 0)
for i := 1; i < len(params); i++ {
lineNum := params[i]
if lineNum >= 1 && lineNum <= int64(rule.LINENUM) && !lineFlag[lineNum] {
lineParams = append(lineParams, lineNum)
lineFlag[lineNum] = true
} else {
this.OnPlayerSToCOp(s, p, playerEx.Pos, opcode, tamquoc.OpResultCode_OPRC_Error, params)
return false
}
}
//没有选线参数
if len(lineParams) == 0 {
this.OnPlayerSToCOp(s, p, playerEx.Pos, opcode, tamquoc.OpResultCode_OPRC_Error, params)
return false
}
//获取总投注金额(所有线的总投注) | 校验玩家余额是否足够
totalBetValue := (int64(len(lineParams))) * params[0]
if playerEx.freeTimes <= 0 && totalBetValue > playerEx.Coin {
this.OnPlayerSToCOp(s, p, playerEx.Pos, opcode, tamquoc.OpResultCode_OPRC_CoinNotEnough, params)
return false
} else if playerEx.freeTimes <= 0 && int64(sceneEx.DbGameFree.GetBetLimit()) > playerEx.Coin { //押注限制
this.OnPlayerSToCOp(s, p, playerEx.Pos, opcode, tamquoc.OpResultCode_OPRC_CoinNotEnough, params)
return false
}
p.LastOPTimer = time.Now()
sceneEx.GameNowTime = time.Now()
sceneEx.NumOfGames++
p.GameTimes++
//playerEx.StartCoin = playerEx.Coin
//获取当前水池的上下文环境
sceneEx.CpCtx = base.CoinPoolMgr.GetCoinPoolCtx(sceneEx.Platform, sceneEx.GetGameFreeId(), sceneEx.GroupId)
//税收比例
taxRate := sceneEx.DbGameFree.GetTaxRate()
if taxRate < 0 || taxRate > 10000 {
logger.Logger.Tracef("TamQuocErrorTaxRate [%v][%v][%v][%v]", sceneEx.GetGameFreeId(), playerEx.SnId, playerEx.spinID, taxRate)
taxRate = 500
}
//水池设置
coinPoolSetting := base.CoinPoolMgr.GetCoinPoolSetting(sceneEx.Platform, sceneEx.GetGameFreeId(), sceneEx.GroupId)
ctroRate := 500 //调节赔率 暗税系数
jackpotRate := ctroRate //奖池系数
logger.Logger.Tracef("TamQuocRates [%v][%v][%v][%v][%v]", sceneEx.GetGameFreeId(), playerEx.SnId, playerEx.spinID, taxRate, ctroRate)
playerEx.IsFNovice(sceneEx.KeyGameId)
isFoolPlayer := false
var gamePoolCoin int64
//if isFoolPlayer {
// gamePoolCoin = base.CoinPoolMgr.GetNoviceCoinPool(sceneEx.GetGameFreeId(), sceneEx.Platform, sceneEx.GroupId) // 当前水池金额
//} else {
gamePoolCoin = base.CoinPoolMgr.GetCoin(sceneEx.GetGameFreeId(), sceneEx.Platform, sceneEx.GroupId) // 当前水池金额
//}
prizeFund := gamePoolCoin - sceneEx.jackpot.VirtualJK // 除去奖池的水池剩余金额
// 奖池参数
var jackpotParam = sceneEx.DbGameFree.GetJackpot()
var jackpotInit = int64(jackpotParam[rule.TAMQUOC_JACKPOT_InitJackpot] * sceneEx.DbGameFree.GetBaseScore()) //奖池初始值
var jackpotFundAdd, prizeFundAdd int64
if playerEx.freeTimes <= 0 { //正常模式才能记录用户的押注变化,免费模式不能改变押注
playerEx.betLines = lineParams // 选线记录
jackpotFundAdd = int64(math.Floor(float64(totalBetValue) * (float64(jackpotRate) / 10000.0))) //奖池要增加的金额
prizeFundAdd = totalBetValue - jackpotFundAdd
playerEx.TotalBet += totalBetValue //总下注额(从进房间开始,包含多局游戏的下注)
//扣除投注金币
p.AddCoin(-totalBetValue, common.GainWay_HundredSceneLost, base.SyncFlag_ToClient, "system", s.GetSceneName())
//p.Statics(sceneEx.KeyGameId, sceneEx.KeyGamefreeId, -totalBetValue, true)
if !p.IsRob && !sceneEx.Testing {
// 推送金币
sceneEx.PushCoinPool(prizeFundAdd, isFoolPlayer)
//base.CoinPoolMgr.PushCoin(sceneEx.GetGameFreeId(), sceneEx.GroupId, sceneEx.Platform, int64(float64(totalBetValue)*(float64(10000-ctroRate)/10000.0)))
}
//统计参与游戏次数
//if !sceneEx.Testing && !playerEx.IsRob {
// pack := &server.GWSceneEnd{
// GameFreeId: proto.Int32(sceneEx.DbGameFree.GetId()),
// Players: []*server.PlayerCtx{&server.PlayerCtx{SnId: proto.Int32(playerEx.SnId), Coin: proto.Int64(playerEx.Coin)}},
// }
// proto.SetDefaults(pack)
// sceneEx.SendToWorld(int(server.SSPacketID_PACKET_GW_SCENEEND), pack)
//}
} else { //免费次数时,不能改线改选线
totalBetValue = 0
}
var symbolType rule.Symbol
if gamePoolCoin <= int64(coinPoolSetting.GetLowerLimit()) { // 水池不足
symbolType = rule.SYMBOL1
} else {
symbolType = rule.SYMBOL2
}
writeBlackTryTimes := 0
WriteBlack:
slotData := make([]int, 0)
var spinRes TamQuocSpinResult
var slotDataIsOk bool
for i := 0; i < 3; i++ {
slotData = rule.GenerateSlotsData_v2(symbolType)
//if sceneEx.DbGameFree.GetSceneType() == 1 {
// slotData = []int{1, 1, 1, 1, 1, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7}
//}
spinRes = sceneEx.CalcLinePrize(slotData, playerEx.betLines, params[0])
//if sceneEx.DbGameFree.GetSceneType() == 1 {
// slotDataIsOk = true
// break
//}
if spinRes.AddFreeTimes > 0 && len(playerEx.betLines) < 15 {
continue
}
// 免费次数时 不允许爆奖
if playerEx.freeTimes > 0 && spinRes.IsJackpot {
continue
}
// 水池不足以支付玩家
if spinRes.IsJackpot {
if sceneEx.jackpot.Small < sceneEx.jackpot.VirtualJK {
continue
}
}
spinCondition := prizeFund + prizeFundAdd - (spinRes.TotalPrizeJackpot + spinRes.TotalPrizeLine + spinRes.BonusGame.GetTotalPrizeValue())
spinCondition += sceneEx.jackpot.VirtualJK - jackpotInit
win := spinRes.TotalPrizeJackpot + spinRes.TotalPrizeLine + spinRes.BonusGame.GetTotalPrizeValue()
if spinCondition < 0 && win > totalBetValue {
if !spinRes.IsJackpot {
writeBlackTryTimes = 999
}
continue
}
// 非爆奖时 大奖限制
var limitBigWin int64
if symbolType == rule.SYMBOL1 {
limitBigWin = int64(jackpotParam[rule.TAMQUOC_JACKPOT_LIMITWIN_PRIZELOW])
} else {
limitBigWin = int64(jackpotParam[rule.TAMQUOC_JACKPOT_LIMITWIN_PRIZEHIGH])
}
if totalBetValue > 0 && !spinRes.IsJackpot && spinRes.TotalPrizeLine > totalBetValue*limitBigWin {
continue
}
if spinRes.BonusGame.GetTotalPrizeValue() > 0 {
if len(playerEx.betLines) < 20 {
continue
}
// 小游戏最小时间间隔限制
lastBonusGameTimeInterval := time.Now().Unix() - playerEx.bonusGameTime
if symbolType == rule.SYMBOL1 && lastBonusGameTimeInterval < int64(jackpotParam[rule.TAMQUOC_JACKPOT_BonusMinTimeInterval_Low]) {
continue
} else if symbolType == rule.SYMBOL2 && lastBonusGameTimeInterval < int64(jackpotParam[rule.TAMQUOC_JACKPOT_BonusMinTimeInterval_High]) {
continue
}
}
slotDataIsOk = true
break
}
if !slotDataIsOk {
slotData = rule.GenerateSlotsData_v3(rule.DEFALUTROOMMODEL)
spinRes = sceneEx.CalcLinePrize(slotData, playerEx.betLines, params[0])
}
// 黑白名单调控 防止异常循环,添加上限次数
if writeBlackTryTimes < 100 && playerEx.CheckBlackWriteList(spinRes.TotalPrizeLine+spinRes.TotalPrizeJackpot+spinRes.BonusGame.GetTotalPrizeValue() > totalBetValue) {
writeBlackTryTimes++
goto WriteBlack
} else if writeBlackTryTimes >= 100 && writeBlackTryTimes != 999 {
logger.Logger.Warnf("TamquocWriteBlackTryTimesOver [%v][%v][%v][%v][%v]", sceneEx.GetGameFreeId(), playerEx.SnId, gamePoolCoin, playerEx.BlackLevel, playerEx.WhiteLevel)
}
// 奖池水池处理
if spinRes.IsJackpot {
sceneEx.jackpot.Small -= sceneEx.jackpot.VirtualJK
if sceneEx.jackpot.Small < 0 {
sceneEx.jackpot.Small = 0
}
sceneEx.jackpot.VirtualJK = jackpotInit
} else {
sceneEx.jackpot.Small += jackpotFundAdd
sceneEx.jackpot.VirtualJK += jackpotFundAdd
}
// 玩家赢钱
totalWinScore := spinRes.TotalPrizeLine + spinRes.TotalPrizeJackpot
if totalWinScore > 0 || spinRes.BonusGame.GetTotalPrizeValue() > 0 {
p.AddCoin(totalWinScore+spinRes.BonusGame.GetTotalPrizeValue(), common.GainWay_HundredSceneWin, 0, "system", s.GetSceneName())
//p.Statics(sceneEx.KeyGameId, sceneEx.KeyGamefreeId, totalWinScore+spinRes.BonusGame.GetTotalPrizeValue()+spinRes.TotalTaxScore, true)
if !p.IsRob && !sceneEx.Testing {
sceneEx.PopCoinPool(totalWinScore+spinRes.BonusGame.GetTotalPrizeValue()+spinRes.TotalTaxScore, isFoolPlayer)
//base.CoinPoolMgr.PopCoin(sceneEx.GetGameFreeId(), sceneEx.GroupId, sceneEx.Platform, totalWinScore+spinRes.BonusGame.GetTotalPrizeValue()+spinRes.TotalTaxScore)
}
playerEx.taxCoin = spinRes.TotalTaxScore
playerEx.AddServiceFee(playerEx.taxCoin)
}
p.StaticsLaba(sceneEx.KeyGameId, sceneEx.KeyGamefreeId, totalBetValue, totalWinScore+spinRes.BonusGame.GetTotalPrizeValue()+spinRes.TotalTaxScore)
this.OnPlayerSToCOp(s, p, playerEx.Pos, opcode, tamquoc.OpResultCode_OPRC_Sucess, append(params[:1], playerEx.betLines...))
//免费次数
var isFreeFlag bool
if playerEx.freeTimes > 0 {
playerEx.freeTimes--
isFreeFlag = true
}
playerEx.freeTimes += spinRes.AddFreeTimes
rule.SpinID++
playerEx.spinID = rule.SpinID
playerEx.cards = spinRes.SlotsData
playerEx.winCoin = spinRes.TotalPrizeLine + spinRes.TotalPrizeJackpot + spinRes.BonusGame.GetTotalPrizeValue() + playerEx.taxCoin
playerEx.linesWinCoin = spinRes.TotalPrizeLine
playerEx.jackpotWinCoin = spinRes.TotalPrizeJackpot
playerEx.smallGameWinCoin = spinRes.BonusGame.GetTotalPrizeValue()
playerEx.CurrentBet = totalBetValue
playerEx.CurrentTax = playerEx.taxCoin
// 小游戏超时处理
if spinRes.IsBonusGame {
playerEx.totalPriceBonus = spinRes.BonusGame.GetTotalPrizeValue()
playerEx.bonusGameTime = time.Now().Unix()
logger.Logger.Tracef("BonusGame Start [%v][%v][%v][%v]", sceneEx.GetGameFreeId(), playerEx.SnId, playerEx.spinID, playerEx.totalPriceBonus)
playerEx.bonusTimerHandle, _ = timer.StartTimer(timer.TimerActionWrapper(func(h timer.TimerHandle, ud interface{}) bool {
this.OnPlayerOp(s, p, TamQuocBonusGame, []int64{playerEx.spinID})
return true
}), nil, TamQuocBonusGameTimeout, 1)
playerEx.bonusGameCanPickNum = len(spinRes.BonusGame.BonusData)
playerEx.bonusGame = spinRes.BonusGame
}
playerEx.billedData = &tamquoc.GameBilledData{
SpinID: proto.Int64(playerEx.spinID),
SlotsData: spinRes.SlotsData,
AddFreeSpin: proto.Int32(spinRes.AddFreeTimes),
IsJackpot: proto.Bool(spinRes.IsJackpot),
PrizeLines: spinRes.LinesInfo,
TotalPrizeValue: proto.Int64(totalWinScore),
TotalPaylinePrizeValue: proto.Int64(spinRes.TotalPrizeLine),
TotalJackpotValue: proto.Int64(spinRes.TotalPrizeJackpot),
Balance: proto.Int64(playerEx.Coin - spinRes.BonusGame.GetTotalPrizeValue()),
FreeSpins: proto.Int32(playerEx.freeTimes),
Jackpot: proto.Int64(sceneEx.jackpot.VirtualJK),
BonusGame: &spinRes.BonusGame,
}
pack := &tamquoc.SCTamQuocGameBilled{
BilledData: playerEx.billedData,
}
proto.SetDefaults(pack)
logger.Logger.Infof("TamQuocPlayerOpStart %v", pack)
p.SendToClient(int(tamquoc.TamQuocPacketID_PACKET_SC_TAMQUOC_GAMEBILLED), pack)
// 记录本次操作this
playerEx.RollGameType.BaseResult.WinTotal = pack.BilledData.GetTotalPrizeValue() + pack.BilledData.GetBonusGame().GetTotalPrizeValue()
playerEx.RollGameType.BaseResult.IsFree = isFreeFlag
playerEx.RollGameType.BaseResult.WinSmallGame = pack.BilledData.BonusGame.GetTotalPrizeValue()
playerEx.RollGameType.BaseResult.AllWinNum = int32(len(pack.BilledData.PrizeLines))
playerEx.RollGameType.BaseResult.WinRate = spinRes.TotalWinRate
playerEx.RollGameType.BaseResult.Cards = pack.BilledData.GetSlotsData()
playerEx.RollGameType.WinLines = spinRes.WinLines
playerEx.RollGameType.BaseResult.WinJackpot = pack.BilledData.GetTotalJackpotValue()
playerEx.RollGameType.BaseResult.WinLineScore = pack.BilledData.TotalPaylinePrizeValue
playerEx.RollGameType.BaseResult.IsFoolPlayer = isFoolPlayer
TamQuocCheckAndSaveLog(sceneEx, playerEx)
// 广播奖池
if totalBetValue == 0 && !spinRes.IsJackpot { // 没改变奖池
return true
}
// 添加进开奖记录里面
if spinRes.IsJackpot {
sceneEx.RecordBurstLog(playerEx.Name, pack.BilledData.GetTotalJackpotValue(), playerEx.CurrentBet)
}
logger.Logger.Tracef("---tamquoc---当前奖池:真人[%v] 虚拟[%v]", sceneEx.jackpot.Small, sceneEx.jackpot.VirtualJK)
case TamQuocBurstHistory:
sceneEx.BurstHistory(playerEx)
case TamQuocPlayerHistory:
task.New(nil, task.CallableWrapper(func(o *basic.Object) interface{} {
spinid := strconv.FormatInt(int64(playerEx.SnId), 10)
gpl := model.GetPlayerListByHallEx(p.SnId, p.Platform, 0, 80, 0, 0, 0, s.DbGameFree.GetGameClass(), s.GameId)
pack := &tamquoc.SCTamQuocPlayerHistory{}
for _, v := range gpl.Data {
//if v.GameDetailedLogId == "" {
// logger.Logger.Error("TamQuocPlayerHistory GameDetailedLogId is nil")
// break
//}
//gdl := model.GetPlayerHistory(p.Platform, v.GameDetailedLogId)
//if gdl == nil {
// logger.Logger.Error("TamQuocPlayerHistory gdl is nil")
// continue
//}
//data, err := UnMarshalTamQuocGameNote(gdl.GameDetailedNote)
//if err != nil {
// logger.Logger.Errorf("UnMarshalTamQuoccGameNote error:%v", err)
//}
//gnd := data.(*GameResultLog)
player := &tamquoc.TamQuocPlayerHistoryInfo{
SpinID: proto.String(spinid),
CreatedTime: proto.Int64(int64(v.Ts)),
TotalBetValue: proto.Int64(v.BetAmount),
TotalPriceValue: proto.Int64(v.WinTotal),
IsFree: proto.Bool(v.IsFree),
TotalBonusValue: proto.Int64(v.WinSmallGame),
}
pack.PlayerHistory = append(pack.PlayerHistory, player)
}
proto.SetDefaults(pack)
logger.Logger.Info("TamQuocPlayerHistory: ", pack)
return pack
}), task.CompleteNotifyWrapper(func(data interface{}, t task.Task) {
if data == nil {
logger.Logger.Error("TamQuocPlayerHistory data is nil")
return
}
p.SendToClient(int(tamquoc.TamQuocPacketID_PACKET_SC_TAMQUOC_PLAYERHISTORY), data)
}), "CSGetTamQuocPlayerHistoryHandler").Start()
case TamQuocBonusGame:
//params 参数0 spinID
//参数是否合法
if len(params) < 1 {
this.OnPlayerSToCOp(s, p, playerEx.Pos, opcode, tamquoc.OpResultCode_OPRC_Error, params)
return false
}
if playerEx.spinID != params[0] || playerEx.totalPriceBonus <= 0 {
this.OnPlayerSToCOp(s, p, playerEx.Pos, opcode, tamquoc.OpResultCode_OPRC_Error, params)
return false
}
if playerEx.bonusTimerHandle != timer.TimerHandle(0) {
timer.StopTimer(playerEx.bonusTimerHandle)
playerEx.bonusTimerHandle = timer.TimerHandle(0)
}
logger.Logger.Tracef("BonusGame Start [%v][%v][%v][%v]", sceneEx.GetGameFreeId(), playerEx.SnId, playerEx.spinID, playerEx.totalPriceBonus)
this.OnPlayerSToCOp(s, p, playerEx.Pos, opcode, tamquoc.OpResultCode_OPRC_Sucess, []int64{playerEx.totalPriceBonus, playerEx.Coin})
playerEx.totalPriceBonus = 0
playerEx.bonusGamePickPos = make([]int32, 2)
case TamQuocBonusGameRecord:
// params
// 参数下标0 0表示进小游戏 1表示选图标界面
// 参数下标1 玩家当前点击位置
if (len(params) == 1 && params[0] != 0) ||
(len(params) == 2 && (params[0] != 1 || params[1] < 1 || params[1] > 24)) {
logger.Logger.Errorf("Invalid parameter")
this.OnPlayerSToCOp(s, p, playerEx.Pos, opcode, tamquoc.OpResultCode_OPRC_Error, params)
return true
}
switch params[0] {
case 0:
if playerEx.bonusGamePickPos[0] < 1 {
// 记录进入小游戏时间
playerEx.bonusGameStartTime = time.Now()
playerEx.bonusGamePickPos[0] = 1
}
case 1:
if len(playerEx.bonusGamePickPos) > playerEx.bonusGameCanPickNum {
logger.Logger.Errorf("too many pickPos")
this.OnPlayerSToCOp(s, p, playerEx.Pos, opcode, tamquoc.OpResultCode_OPRC_Error, params)
return true
}
playerEx.bonusGamePickPos = append(playerEx.bonusGamePickPos, int32(params[1]))
default:
logger.Logger.Errorf("Invalid parameter, params[0]")
}
}
return true
}
func (this *SceneStateTamQuocStart) OnPlayerEvent(s *base.Scene, p *base.Player, evtcode int, params []int64) {
}
// 发送玩家操作情况
func (this *SceneStateTamQuocStart) OnPlayerSToCOp(s *base.Scene, p *base.Player, pos int, opcode int,
opRetCode tamquoc.OpResultCode, params []int64) {
pack := &tamquoc.SCTamQuocOp{
SnId: proto.Int32(p.SnId),
OpCode: proto.Int(opcode),
OpRetCode: opRetCode,
Params: params,
}
proto.SetDefaults(pack)
p.SendToClient(int(tamquoc.TamQuocPacketID_PACKET_SC_TAMQUOC_PLAYEROP), pack)
}
func TamQuocCheckAndSaveLog(sceneEx *TamQuocSceneData, playerEx *TamQuocPlayerData) {
//统计金币变动
//log1
logger.Logger.Trace("TamQuocCheckAndSaveLog Save ", playerEx.SnId)
//changeCoin := playerEx.Coin - playerEx.StartCoin
changeCoin := playerEx.winCoin - playerEx.taxCoin - playerEx.CurrentBet
startCoin := playerEx.Coin - changeCoin
playerEx.SaveSceneCoinLog(startCoin, changeCoin,
playerEx.Coin, playerEx.CurrentBet, playerEx.taxCoin, playerEx.winCoin, playerEx.jackpotWinCoin, playerEx.smallGameWinCoin)
//log2
playerEx.RollGameType.BaseResult.ChangeCoin = changeCoin
playerEx.RollGameType.BaseResult.BasicBet = sceneEx.DbGameFree.GetBaseScore()
playerEx.RollGameType.BaseResult.RoomId = int32(sceneEx.SceneId)
playerEx.RollGameType.BaseResult.AfterCoin = playerEx.Coin
playerEx.RollGameType.BaseResult.BeforeCoin = startCoin
playerEx.RollGameType.BaseResult.IsFirst = sceneEx.IsPlayerFirst(playerEx.Player)
playerEx.RollGameType.BaseResult.PlayerSnid = playerEx.SnId
playerEx.RollGameType.BaseResult.TotalBet = int32(playerEx.CurrentBet)
playerEx.RollGameType.AllLine = int32(len(playerEx.betLines))
playerEx.RollGameType.BaseResult.FreeTimes = playerEx.freeTimes
playerEx.RollGameType.UserName = playerEx.Name
playerEx.RollGameType.BetLines = playerEx.betLines
playerEx.RollGameType.BaseResult.Tax = playerEx.taxCoin
playerEx.RollGameType.BaseResult.WBLevel = sceneEx.players[playerEx.SnId].WBLevel
if playerEx.score > 0 {
if !playerEx.IsRob {
info, err := model.MarshalGameNoteByROLL(playerEx.RollGameType)
if err == nil {
logid, _ := model.AutoIncGameLogId()
playerEx.currentLogId = logid
sceneEx.SaveGameDetailedLog(logid, info, &base.GameDetailedParam{})
totalin := int64(playerEx.RollGameType.BaseResult.TotalBet)
totalout := playerEx.RollGameType.BaseResult.ChangeCoin + playerEx.taxCoin + totalin
validFlow := totalin + totalout
validBet := common.AbsI64(totalin - totalout)
logParam := &base.SaveGamePlayerListLogParam{
Platform: playerEx.Platform,
Channel: playerEx.Channel,
Promoter: playerEx.BeUnderAgentCode,
PackageTag: playerEx.PackageID,
InviterId: playerEx.InviterId,
LogId: logid,
TotalIn: totalin,
TotalOut: totalout,
TaxCoin: playerEx.taxCoin,
BetAmount: int64(playerEx.RollGameType.BaseResult.TotalBet),
WinAmountNoAnyTax: playerEx.RollGameType.BaseResult.ChangeCoin,
ValidBet: validBet,
ValidFlow: validFlow,
IsFirstGame: sceneEx.IsPlayerFirst(playerEx.Player),
IsFree: playerEx.RollGameType.BaseResult.IsFree,
WinSmallGame: playerEx.RollGameType.BaseResult.WinSmallGame,
WinTotal: playerEx.RollGameType.BaseResult.WinTotal,
}
sceneEx.SaveGamePlayerListLog(playerEx.SnId, logParam)
}
}
}
//统计输下注金币数
if !sceneEx.Testing && !playerEx.IsRob {
playerBet := &server.PlayerData{
SnId: proto.Int32(playerEx.SnId),
Bet: proto.Int64(playerEx.CurrentBet),
Gain: proto.Int64(playerEx.RollGameType.BaseResult.ChangeCoin),
Tax: proto.Int64(playerEx.taxCoin),
Coin: proto.Int64(playerEx.GetCoin()),
GameCoinTs: proto.Int64(playerEx.GameCoinTs),
}
gwPlayerBet := &server.GWPlayerData{
SceneId: proto.Int(sceneEx.SceneId),
GameFreeId: proto.Int32(sceneEx.DbGameFree.GetId()),
}
gwPlayerBet.Datas = append(gwPlayerBet.Datas, playerBet)
sceneEx.SyncPlayerDatas(&base.PlayerDataParam{
HasRobotGaming: false,
Data: gwPlayerBet,
})
}
playerEx.taxCoin = 0
playerEx.winCoin = 0
playerEx.linesWinCoin = 0
playerEx.jackpotWinCoin = 0
playerEx.smallGameWinCoin = 0
if sceneEx.CheckNeedDestroy() && playerEx.freeTimes <= 0 {
sceneEx.PlayerLeave(playerEx.Player, common.PlayerLeaveReason_OnDestroy, true)
}
}
func init() {
ScenePolicyTamQuocSington.RegisteSceneState(&SceneStateTamQuocStart{})
core.RegisteHook(core.HOOK_BEFORE_START, func() error {
base.RegisteScenePolicy(common.GameId_TamQuoc, 0, ScenePolicyTamQuocSington)
return nil
})
}

Binary file not shown.

Binary file not shown.