game_sync/gamesrv/fruits/scenedata_fruits.go

648 lines
19 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package fruits
import (
"encoding/json"
"fmt"
"math"
"math/rand"
"time"
"mongo.games.com/game/common"
"mongo.games.com/game/gamerule/fruits"
"mongo.games.com/game/gamesrv/base"
"mongo.games.com/game/model"
"mongo.games.com/game/proto"
protocol "mongo.games.com/game/protocol/fruits"
"mongo.games.com/game/protocol/server"
"mongo.games.com/game/srvdata"
"mongo.games.com/goserver/core/logger"
)
type FruitsSceneData struct {
*base.Scene //场景
players map[int32]*FruitsPlayerData //玩家信息
jackpot *base.SlotJackpotPool //奖池
levelRate [][]int32 //调控概率区间
//slotRateWeight []int32 //调控权重
//slotRateWeightTotal [][]int32 //总调控权重
sysProfitCoinKey string
mqLogTime time.Time
}
func NewFruitsSceneData(s *base.Scene) *FruitsSceneData {
sceneEx := &FruitsSceneData{
Scene: s,
players: make(map[int32]*FruitsPlayerData),
}
sceneEx.Init()
return sceneEx
}
func (s *FruitsSceneData) Init() {
s.LoadJackPotData()
//for _, data := range srvdata.PBDB_SlotRateWeightMgr.Datas.Arr {
// if data.Id == s.GetDBGameFree().Id {
// //s.levelRate = append(s.levelRate, data.EleWeight1)
// //s.slotRateWeightTotal = append(s.slotRateWeightTotal, data.EleWeight1, data.EleWeight2, data.EleWeight3, data.EleWeight4, data.EleWeight5)
// }
//}
s.sysProfitCoinKey = fmt.Sprintf("%v_%v", s.Platform, s.GetGameFreeId())
s.mqLogTime = time.Now()
}
func (s *FruitsSceneData) Clear() {
//应该是水池变一次就判断修改一次
//s.slotRateWeight = s.slotRateWeightTotal[0]
}
func (s *FruitsSceneData) SceneDestroy(force bool) {
//销毁房间
s.Scene.Destroy(force)
}
func (s *FruitsSceneData) AddPrizeCoin(playerEx *FruitsPlayerData) {
val := playerEx.betCoin
tax := int64(math.Ceil(float64(val) * float64(s.GetDBGameFree().GetTaxRate()) / 10000))
//playerEx.taxCoin = tax
//playerEx.AddServiceFee(tax)
val -= tax
addPrizeCoin := int64(math.Floor(float64(val*fruits.NowByte*int64(s.GetDBGameFree().GetJackpotRatio())) / 1000)) //扩大10000倍
s.jackpot.AddToSmall(playerEx.IsRob, addPrizeCoin)
logger.Logger.Tracef("奖池增加...AddPrizeCoin... %f", float64(addPrizeCoin)/float64(fruits.NowByte))
base.SlotsPoolMgr.SetPool(s.GetGameFreeId(), s.Platform, s.jackpot)
if !s.Testing {
base.CoinPoolMgr.PushCoin(s.GetGameFreeId(), s.GroupId, s.Platform, val*fruits.NowByte-addPrizeCoin)
}
}
func (s *FruitsSceneData) DelPrizeCoin(isRob bool, win int64) {
if win > 0 {
s.jackpot.AddToSmall(isRob, -win*fruits.NowByte)
logger.Logger.Tracef("奖池减少...AddPrizeCoin... %d", win)
base.SlotsPoolMgr.SetPool(s.GetGameFreeId(), s.Platform, s.jackpot)
}
}
func (s *FruitsSceneData) delPlayer(SnId int32) {
if _, exist := s.players[SnId]; exist {
delete(s.players, SnId)
}
}
func (s *FruitsSceneData) OnPlayerLeave(p *base.Player, reason int) {
if playerEx, ok := p.ExtraData.(*FruitsPlayerData); ok {
if playerEx.freeTimes > 0 || playerEx.maryFreeTimes > 0 {
//免费
playerEx.winFreeCoin = playerEx.winLineCoin + playerEx.winJackPotCoin + playerEx.winEle777Coin
//小玛丽
playerEx.winCoin = playerEx.winOutMaryCoin + playerEx.winMidMaryCoin + playerEx.winFreeCoin
if playerEx.winCoin != 0 {
//SysProfitCoinMgr.Add(s.sysProfitCoinKey, 0, playerEx.winCoin)
p.Statics(s.KeyGameId, s.KeyGamefreeId, playerEx.winCoin, false)
//tax := int64(math.Ceil(float64(playerEx.winCoin) * float64(s.GetDBGameFree().GetTaxRate()) / 10000))
//playerEx.taxCoin = tax
//playerEx.winCoin -= tax
//p.AddServiceFee(tax)
p.AddCoin(playerEx.winCoin, common.GainWay_HundredSceneWin, 0, "system", s.GetSceneName())
if !s.Testing {
base.CoinPoolMgr.PushCoin(s.GetGameFreeId(), s.GroupId, s.Platform, -(playerEx.winCoin)*fruits.NowByte)
}
//p.isReportGameEvent = true
//p.ReportGameEventParam()
s.SaveLog(playerEx, 1)
}
}
}
s.delPlayer(p.SnId)
}
func (s *FruitsSceneData) Win(p *FruitsPlayerData) {
if p.gameState != fruits.MaryGame && p.JackPotRate > 0 {
//奖池
s.DelPrizeCoin(p.IsRob, p.winNowJackPotCoin)
p.winJackPotCoin += p.winNowJackPotCoin
}
isBilled := false
if p.gameState == fruits.Normal {
isBilled = true
p.winCoin = p.winLineCoin + p.winJackPotCoin + p.winEle777Coin
p.winNowAllRate = p.winLineRate + p.JackPot7Rate
} else if p.gameState == fruits.FreeGame {
p.winFreeCoin = p.winLineCoin + p.winJackPotCoin + p.winEle777Coin
p.winNowAllRate = p.winLineRate + p.JackPot7Rate
if p.freeTimes == 0 {
isBilled = true
p.winCoin = p.winFreeCoin
}
} else {
p.winNowAllRate = p.maryWinTotalRate
if p.maryFreeTimes == 0 {
isBilled = true
p.winCoin = p.winOutMaryCoin + p.winMidMaryCoin
}
}
if isBilled && 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.GetDBGameFree().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)*fruits.NowByte)
}
//p.isReportGameEvent = true
}
//p.ReportGameEventParam()
}
func (s *FruitsSceneData) SendBilled(p *FruitsPlayerData) {
if p.gameState != fruits.MaryGame {
//正常游戏 免费游戏
var wl []*protocol.FruitsWinLine
for _, r := range p.result.WinLine {
wl = append(wl, &protocol.FruitsWinLine{
Poss: r.Poss,
LineId: proto.Int(r.LineId),
})
}
pack := &protocol.SCFruitsBilled{
NowGameState: proto.Int(p.gameState),
BetIdx: proto.Int(p.betIdx),
Coin: proto.Int64(p.Coin),
FreeTotalWin: proto.Int64(p.winFreeCoin),
Jackpot: proto.Int64(s.jackpot.GetTotalSmall() / 10000),
WinJackpot: proto.Int64(p.winNowJackPotCoin),
WinEle777Coin: proto.Int64(p.oneBetCoin * p.JackPot7Rate),
WinRate: proto.Int64(p.winLineRate + p.JackPot7Rate),
Cards: p.result.EleValue,
WinLines: wl,
FreeTimes: proto.Int(p.freeTimes),
MaryFreeTimes: proto.Int(p.maryFreeTimes),
WinFreeTimes: proto.Int(p.winFreeTimes),
WinLineCoin: proto.Int64(p.oneBetCoin * p.winLineRate),
}
logger.Logger.Trace("SCFruitsBilled", pack)
p.SendToClient(int(protocol.FruitsPID_PACKET_FRUITS_SCFruitsBilled), pack)
} else {
//玛丽游戏
pack := &protocol.SCFruitsMaryBilled{
Coin: proto.Int64(p.Coin),
FreeTotalWin: proto.Int64(p.winFreeCoin),
MaryOutTotalWin: proto.Int64(p.winOutMaryCoin),
MaryMidTotalWin: proto.Int64(p.winMidMaryCoin),
MaryWinCoin: proto.Int64(p.oneBetCoin * p.maryWinTotalRate),
MaryWinId: proto.Int32(p.result.MaryOutSide),
MaryCards: p.result.MaryMidArray,
MaryFreeTimes: proto.Int(p.maryFreeTimes),
}
logger.Logger.Trace("SCFruitsMaryBilled", pack)
p.SendToClient(int(protocol.FruitsPID_PACKET_FRUITS_SCFruitsMaryBilled), pack)
}
}
func (s *FruitsSceneData) 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.GetDBGameFree().GetJackpot()
if len(jp) > 0 {
s.jackpot.Small += int64(jp[0] * 10000)
}
}
}
func (s *FruitsSceneData) SaveLog(p *FruitsPlayerData, isOffline int) {
if s.Testing {
return
}
s.SendPlayerBet(p)
var betCoin int64
var nowNRound int
var nowGetCoin int64
var isF bool
if p.gameState == fruits.Normal {
betCoin = p.betCoin
nowGetCoin = p.winCoin
isF = true
} else if p.gameState == fruits.FreeGame {
nowNRound = p.nowFreeTimes
nowGetCoin = p.winFreeCoin
if p.freeTimes == 0 {
isF = true
}
} else {
nowNRound = p.nowMaryTimes
nowGetCoin = p.winOutMaryCoin + p.winMidMaryCoin
if p.maryFreeTimes == 0 {
isF = true
}
}
FruitsType := model.FruitsType{
RoomId: int(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: p.freeTimes,
MaryFreeTimes: p.maryFreeTimes,
//WhiteLevel: p.WhiteLevel,
//BlackLevel: p.BlackLevel,
TaxCoin: p.taxCoin,
WBLevel: p.WBLevel,
RealCtrl: s.RealCtrl,
WBState: p.WBState,
WeightKey: p.weightPos + 1,
}
//if p.result.JackPotNum >= 3 {
//Classic777Type.JackPotNum = p.result.JackPotNum
FruitsType.JackPotWinCoin = p.oneBetCoin * p.JackPot7Rate
//}
var winLine []model.FruitsWinLine
if p.gameState == fruits.MaryGame {
FruitsType.MaryOutSide = fruits.MaryEleArray[p.result.MaryOutSide]
FruitsType.MaryMidCards = p.result.MaryMidArray
winLine = append(winLine, model.FruitsWinLine{
Id: -1,
EleValue: FruitsType.MaryOutSide,
Num: p.maryInNum,
Rate: p.maryWinTotalRate,
WinCoin: p.oneBetCoin * p.maryWinTotalRate,
WinFreeGame: -1,
})
} else {
FruitsType.Cards = p.result.EleValue
FruitsType.HitPrizePool = p.winNowJackPotCoin
n := 0
for _, v := range p.result.WinLine {
if v.Rate == 0 {
n++
}
}
FruitsType.WinLineNum = len(p.result.WinLine) - n
FruitsType.WinLineRate = p.winLineRate
FruitsType.WinLineCoin = p.winLineRate * p.oneBetCoin
for _, line := range p.result.WinLine {
if line.LineId > 9 {
continue
}
flag := line.Lines[0]
if flag == fruits.Wild {
for _, v := range line.Lines {
if flag != v {
flag = v
break
}
}
} else if flag == fruits.Bonus {
continue
}
fw := model.FruitsWinLine{
Id: line.LineId,
EleValue: flag,
Num: len(line.Lines),
Rate: line.Rate,
WinCoin: line.Rate * p.oneBetCoin,
WinFreeGame: -1,
}
winLine = append(winLine, fw)
}
}
winLine = append(winLine, p.wl...)
FruitsType.WinLine = winLine
info, err := model.MarshalGameNoteByROLL(&FruitsType)
if err == nil {
logId, _ := model.AutoIncGameLogId()
s.SaveGameDetailedLog(&base.SaveGameDetailedParam{
LogId: logId,
Detail: info,
GameTime: 1,
})
//水池上下文环境s
s.CpCtx = p.cpCtx
var totalIn, totalOut int64
if betCoin > 0 {
totalIn = betCoin
}
if nowGetCoin > 0 && isF {
totalOut = p.Coin - p.startCoin + betCoin /*+ p.taxCoin*/
}
s.SaveGamePlayerListLog(&base.SaveGamePlayerListLogParam{
LogId: logId,
Platform: p.Platform,
Snid: p.SnId,
PlayerName: p.Name,
Channel: p.Channel,
ChannelId: p.ChannelId,
TotalIn: totalIn,
TotalOut: totalOut,
TaxCoin: p.taxCoin,
BetAmount: totalIn,
WinAmountNoAnyTax: p.Coin - p.startCoin,
IsFirstGame: s.IsPlayerFirst(p.Player),
IsFree: totalIn == 0,
GameTime: 1,
})
}
s.GameNowTime = time.Now()
if s.CheckNeedDestroy() && p.freeTimes == 0 && p.maryFreeTimes == 0 {
s.PlayerLeave(p.Player, common.PlayerLeaveReason_OnDestroy, true)
}
}
func (s *FruitsSceneData) SendPlayerBet(p *FruitsPlayerData) {
//统计输下注金币数
if !p.IsRob && !s.Testing {
betCoin := p.betCoin
if p.gameState != fruits.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.GetDBGameFree().GetId()),
}
gwPlayerBet.Datas = append(gwPlayerBet.Datas, playerBet)
s.SyncPlayerDatas(&base.PlayerDataParam{
HasRobotGaming: false,
Data: gwPlayerBet,
})
}
}
func (s *FruitsSceneData) Regulation(p *FruitsPlayerData, n int) {
//if len(s.levelRate) == 0 || len(s.slotRateWeight) == 0 {
// return
//}
//if p.gameState != fruits.Normal {
// state, _ := base.CoinPoolMgr.GetCoinPoolStatus2(s.Platform, s.GetGameFreeId(), s.GroupId, -p.preWinRate*p.oneBetCoin)
// var isLow bool
// if state == base.CoinPoolStatus_Low {
// isLow = true
// if p.preWinRate > 9 {
// p.preWinRate = rand.Int63n(9) + 1
// }
// }
// s.InFreeGame(p, isLow)
// return
//}
//setting := base.CoinPoolMgr.GetCoinPoolSetting(s.Platform, s.GetGameFreeId(), s.GroupId)
//state, _ := base.CoinPoolMgr.GetCoinPoolStatus(s.Platform, s.GetGameFreeId(), s.GroupId)
//isLow := false
//if state == base.CoinPoolStatus_Low {
// //test code
// isLow = true
//}
//var levelMaxOut = -1
//var level = -1
//if setting != nil {
// for k, v := range s.levelRate {
// if setting.GetMaxOutValue() != 0 && int64(v[1]) <= int64(setting.GetMaxOutValue())/p.oneBetCoin {
// levelMaxOut = k
// }
// if isLow {
// if int64(v[1]) <= 9 {
// level = k
// }
// }
// }
//}
//if !isLow && levelMaxOut > level {
// level = levelMaxOut
//}
////调控Y值
//var regY int32 = -1
//if p.WhiteLevel > 0 || p.BlackLevel > 0 {
// if p.WhiteLevel > 0 {
// regY = s.slotRateWeight[0] * (10 - p.WhiteLevel)
// } else if p.BlackLevel > 0 {
// regY = s.slotRateWeight[0] * (10 + p.BlackLevel*5) / 10
// }
//} else {
// if d, exist := p.GDatas[s.KeyGameId]; exist {
// if d.Statics.TotalIn < 20000 {
// regY = s.slotRateWeight[0] * 50 / 100
// }
// if d.Statics.TotalIn != 0 && d.Statics.TotalOut*100/d.Statics.TotalIn >= 150 && regY == -1 {
// regY = s.slotRateWeight[0] * 4
// }
// }
// if regY == -1 {
// if setting != nil {
// 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))
// if w < 0 {
// regY = 0
// } else {
// regY = int32(w)
// }
// }
// }
// if p.noWinTimes > 0 && regY == -1 {
// if rand.Intn(100) < 10*p.noWinTimes {
// //要中奖
// regY = s.slotRateWeight[0] * (10 - int32(p.noWinTimes)) * 10 / 100
// }
// }
//}
//if regY == -1 {
// regY = s.slotRateWeight[0]
//}
//slotRateWeight := make([]int32, level+1)
//copy(slotRateWeight, s.slotRateWeight[:level+1])
//slotRateWeight[0] = regY
//rIdx := fruits.RandSliceInt32IndexByWightN(slotRateWeight)
//parsec := s.levelRate[rIdx]
//var needRate int32
//if rIdx != 0 {
// needRate = rand.Int31n(parsec[1]-parsec[0]) + parsec[0]
//}
//state, _ = base.CoinPoolMgr.GetCoinPoolStatus2(s.Platform, s.GetGameFreeId(), s.GroupId, -int64(needRate)*p.oneBetCoin)
//if n >= 5 {
// needRate = rand.Int31n(9)
//}
////test code
////if state == base.CoinPoolStatus_Low && needRate > 9 {
//// s.Regulation(p, n+1)
//// return
////}
//p.preWinRate = int64(needRate)
//p.preNeedRate = int64(needRate)
//if p.preNeedRate > 1000 {
// p.pre30WinRate = int64(needRate) * 30 / 100
//}
//s.ShowGameState(int64(needRate), p, isLow)
}
func (s *FruitsSceneData) InMaryGame(p *FruitsPlayerData) {
ele := []int32{fruits.Watermelon, fruits.Grape, fruits.Lemon, fruits.Cherry, fruits.Banana, fruits.Bonus, fruits.Pineapple}
var eleVal int32 = -1
var lianxuEle = 0
if p.preWinRate > 550*9 {
//四连
rate := []int64{700 * 9, 600 * 9, 570 * 9, 550 * 9, 520 * 9, 510 * 9, 505 * 9}
for k, v := range rate {
if p.preWinRate > v {
ele = ele[k:]
break
}
}
lianxuEle = 4
} else if p.preWinRate > 80*9 {
//三连
rate := []int64{220 * 9, 120 * 9, 90 * 9, 70 * 9, 40 * 9, 30 * 9, 25 * 9}
for k, v := range rate {
if p.preWinRate > v {
ele = ele[k:]
break
}
}
lianxuEle = 3
} else if p.preWinRate > 5*9 {
//单个
rate := []int64{200 * 9, 100 * 9, 70 * 9, 50 * 9, 20 * 9, 10 * 9, 5 * 9}
for k, v := range rate {
if p.preWinRate > v {
ele = ele[k:]
break
}
}
lianxuEle = 1
}
p.preMaryMidArray = make([]int32, 4)
MaryMidEleRate := make([]int32, len(fruits.MaryMidEleRate))
copy(MaryMidEleRate, fruits.MaryMidEleRate)
for i := 0; i < 4; i++ {
eler := fruits.RandSliceInt32IndexByWightN(MaryMidEleRate)
p.preMaryMidArray[i] = eler
}
if lianxuEle > 0 {
//需要中奖
idx := rand.Intn(len(ele))
eleVal = ele[idx]
ele = append(ele[:idx], ele[idx+1:]...)
for k, v := range p.preMaryMidArray {
if v == eleVal {
p.preMaryMidArray[k] = ele[rand.Intn(len(ele))]
}
}
if lianxuEle > 1 {
for i := 0; i < lianxuEle; i++ {
p.preMaryMidArray[i] = eleVal
}
} else {
for k := range p.preMaryMidArray {
if rand.Intn(300) <= (k+1)*100 {
p.preMaryMidArray[k] = eleVal
break
}
}
}
for k, v := range fruits.MaryEleArray {
if v == eleVal && rand.Intn(300) <= (k+1)*100 {
p.preMaryOutSide = int32(k)
break
}
}
var rate int32
switch eleVal {
case fruits.Cherry:
rate += 50
case fruits.Pineapple:
rate += 5
case fruits.Grape:
rate += 100
case fruits.Lemon:
rate += 70
case fruits.Watermelon:
rate += 200
case fruits.Banana:
rate += 20
case fruits.Apple:
rate += 10
}
if lianxuEle == 3 {
rate += 20
} else if lianxuEle == 4 {
rate += 500
}
p.preWinRate -= int64(rate) * 9
} else {
//不需要中
for _, v := range p.preMaryMidArray {
for m, n := range ele {
if n == v {
ele = append(ele[:m], ele[m+1:]...)
break
}
}
}
idxEle := ele[rand.Intn(len(ele))]
for k, v := range fruits.MaryEleArray {
if v == idxEle && rand.Intn(100) > 50 {
p.preMaryOutSide = int32(k)
break
}
}
}
}
func (s *FruitsSceneData) GetEleWeight(needpos int32) (norms, frees, marys [][]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(fruits.NowByte)))
for i := len(s.GetDBGameFree().BalanceLine) - 1; i >= 0; i-- {
balance := s.GetDBGameFree().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)
marys = append(marys, ele.MaryOut)
marys = append(marys, ele.MaryMid)
break
}
}
if norms == nil {
norms = fruits.EleWeight[:5]
frees = fruits.EleWeight[5:10]
marys = fruits.EleWeight[10:]
key = 0
}
return
}