game_sync/gamesrv/iceage/scenedata_iceage.go

384 lines
12 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 iceage
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/iceage"
"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/iceage"
"mongo.games.com/game/protocol/server"
"mongo.games.com/game/srvdata"
)
type IceAgeJackpot struct {
createdTime time.Time
userName string
priceValue int64
roomID int64
spinID string
}
type IceAgeSceneData struct {
*base.Scene //房间信息
players map[int32]*IceAgePlayerData //玩家信息
jackpot *base.SlotJackpotPool //奖池
lastJackpotValue int64 //上一次奖池变化时的值
lastJackPot time.Time //增加奖池时间
lastBurstJackPot map[int32]time.Time //爆池时间
}
func NewIceAgeSceneData(s *base.Scene) *IceAgeSceneData {
return &IceAgeSceneData{
Scene: s,
players: make(map[int32]*IceAgePlayerData),
}
}
func (this *IceAgeSceneData) SaveData(force bool) {
}
func (this *IceAgeSceneData) OnPlayerLeave(p *base.Player, reason int) {
if p, exist := this.players[p.SnId]; exist {
delete(this.players, p.SnId)
}
}
func (this *IceAgeSceneData) SceneDestroy(force bool) {
//销毁房间
this.Scene.Destroy(force)
}
func (this *IceAgeSceneData) init() bool {
if this.GetDBGameFree() == nil {
return false
}
params := this.GetDBGameFree().GetJackpot()
this.jackpot = &base.SlotJackpotPool{}
if this.jackpot.Small <= 0 {
this.jackpot.Small = 0
this.jackpot.VirtualJK = int64(params[rule.ICEAGE_JACKPOT_InitJackpot]) * int64(this.GetDBGameFree().GetBaseScore())
}
str := base.SlotsPoolMgr.GetPool(this.GetGameFreeId(), this.GetPlatform())
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.GetPlatform(), this.jackpot)
}
this.lastJackPot = time.Now()
this.lastBurstJackPot = make(map[int32]time.Time)
this.SetLastBurstJackPot()
return true
}
const (
SlotsData = "SlotsData"
SlotsData_V2 = "SlotsData_V2"
BonusData = "BonusData"
BonusData_V2 = "BonusData_V2"
DefaultData = "DefaultData"
DefaultData_v1 = "DefaultData_v1"
)
func getElementDistributionByName(name string) *server.DB_IceAgeElementRate {
for i := range srvdata.PBDB_IceAgeElementRateMgr.Datas.Arr {
item := srvdata.PBDB_IceAgeElementRateMgr.GetData(int32(i + 1))
if item.GetModeName() == name {
return item
}
}
return nil
}
func getSlotsDataByElementDistribution(data []int32) []int {
var t = make([]int, rule.ELEMENT_TOTAL)
for i, _ := range t {
t[i] = int(data[rand.Intn(len(data))])
}
return t
}
func getSlotsDataByGroupName(name string) []int {
cardLib := rule.MissData[name]
if len(cardLib) > 0 {
return cardLib[rand.Intn(len(cardLib))]
}
return nil
}
type SpinResult struct {
LinesInfo []*iceage.IceAgeLinesInfo
SlotsData []*iceage.IceAgeCards
TotalPrizeLine int64 // 线条总金额+爆奖
TotalPrizeBonus int64 // 小游戏总金额
BonusGameCnt int32 // 小游戏次数
TotalPrizeJackpot int64 // 爆奖总金额
JackpotCnt int // 爆奖的次数
AddFreeTimes int32 // 新增免费次数
IsJackpot bool // 是否爆奖
TotalWinRate int32 // 中奖总倍率
TotalTaxScore int64 // 税收
WinLines [][]int // 赢分的线
}
func (this *IceAgeSceneData) CalcSpinsPrize(cards []int, betLines []int64, distributionData []int32, bonusParams []int32, betValue int64, taxRate int32) (spinRes SpinResult) {
tmpCards := make([]int, len(cards))
copy(tmpCards, cards)
calcTaxScore := func(score int64, taxScore *int64) int64 {
tmpTaxScore := int64(float64(score) * float64(taxRate) / 10000.0)
*taxScore += tmpTaxScore
return score - tmpTaxScore
}
for loopIndex := 0; loopIndex < 99; loopIndex++ { // 避免死循环
var winLines []int
slotData := &iceage.IceAgeCards{}
for _, card := range tmpCards {
slotData.Card = append(slotData.Card, int32(card))
}
spinRes.SlotsData = append(spinRes.SlotsData, slotData)
lineCount := 0
for _, lineNum := range betLines {
lineTemplate := rule.AllLineArray[int(lineNum)-1]
edata := []int{}
epos := []int32{}
for _, pos := range lineTemplate {
edata = append(edata, tmpCards[pos])
epos = append(epos, int32(pos)+1)
}
head, count := rule.IsLine(edata)
if head == 0 || count <= 0 {
continue
}
var spinFree, prizeJackpot, bonus int64
var prizesBonus = make([]int64, 0)
if head == rule.Element_FREESPIN {
spinFree = int64(rule.FreeSpinTimesRate[count-1])
} else if head == rule.Element_JACKPOT && count == 5 {
spinRes.IsJackpot = true
spinRes.JackpotCnt++
if spinRes.TotalPrizeJackpot == 0 { // 第一个爆奖 获取当前奖池所有
prizeJackpot = this.jackpot.VirtualJK
} else { // 之后的爆奖 奖励为奖池初值
prizeJackpot = int64(this.GetDBGameFree().GetJackpot()[rule.ICEAGE_JACKPOT_InitJackpot]) * int64(this.GetDBGameFree().GetBaseScore())
}
prizeJackpot = calcTaxScore(prizeJackpot, &spinRes.TotalTaxScore)
spinRes.TotalPrizeJackpot += prizeJackpot
} else if head == rule.Element_BONUS && count >= 3 {
bonus = betValue * int64(len(betLines)) * int64(bonusParams[rand.Intn(len(bonusParams))])
bonus = calcTaxScore(bonus, &spinRes.TotalTaxScore)
prizesBonus = []int64{bonus, bonus, bonus} // len大于0即可
spinRes.BonusGameCnt++
}
curScore := int64(rule.LineScore[head][count-1]) * betValue
curScore = calcTaxScore(curScore, &spinRes.TotalTaxScore)
spinRes.TotalWinRate += int32(rule.LineScore[head][count-1])
spinRes.TotalPrizeLine += curScore + prizeJackpot
spinRes.TotalPrizeBonus += bonus
spinRes.AddFreeTimes += int32(spinFree)
line := &iceage.IceAgeLinesInfo{
LineID: proto.Int32(int32(lineNum)),
Turn: proto.Int32(int32(loopIndex + 1)),
PrizeValue: proto.Int64(curScore + prizeJackpot),
PrizesFreespin: proto.Int64(spinFree),
PrizesJackport: proto.Int64(prizeJackpot),
PrizesBonus: prizesBonus,
Items: epos[:count],
RoleID: proto.Int32(int32(head)),
}
spinRes.LinesInfo = append(spinRes.LinesInfo, line)
winLines = append(winLines, int(line.GetLineID()))
lineCount++
}
if winLines != nil {
spinRes.WinLines = append(spinRes.WinLines, winLines)
}
if loopIndex == 98 {
logger.Logger.Error("IceAgeSpinTimes99", cards, betLines, distributionData, bonusParams, betValue, taxRate)
}
// 没有匹配的线条 不用消除处理
if lineCount == 0 {
break
}
// 获取消除后的新线
tmpCards = rule.MakePlan(tmpCards, distributionData, betLines)
if len(tmpCards) == 0 {
break
}
}
return
}
func (this *IceAgeSceneData) 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.GetDBGameFree().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 *IceAgeSceneData) 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 *IceAgeSceneData) 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 *IceAgeSceneData) RecordBurstLog(name string, wincoin, totalbet int64) {
log := model.NewBurstJackpotLog(this.Platform, this.GetDBGameFree().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 *IceAgeSceneData) BurstHistory(player *IceAgePlayerData) {
task.New(nil, task.CallableWrapper(func(o *basic.Object) interface{} {
return model.GetBurstJackpotLog(this.Platform, this.GetDBGameFree().GameId)
}), task.CompleteNotifyWrapper(func(data interface{}, t task.Task) {
var logsp []*iceage.IceAgeBurstHistoryInfo
if data != nil {
logs := data.([]model.BurstJackpotLog)
if len(logs) > 0 {
for _, log := range logs {
logsp = append(logsp, &iceage.IceAgeBurstHistoryInfo{
UserName: log.Name,
PriceValue: log.WinCoin,
TotalBet: log.TotalBet,
Ts: log.Ts,
})
}
}
}
pack := &iceage.SCIceAgeBurstHistoryInfo{
BurstLog: logsp,
}
logger.Logger.Trace("SCIceAgeBurstHistoryInfo:", pack)
player.SendToClient(int(iceage.IceAgePacketID_PACKET_SC_ICEAGE_BURSTHISTORY), pack)
}), "BurstHistory").Start()
}
func (this *IceAgeSceneData) GetLastBurstJackPot() time.Time {
return this.lastBurstJackPot[this.GetGameFreeId()]
}
func (this *IceAgeSceneData) SetLastBurstJackPot() {
var randT = rand.Intn(25200-7200+1) + 7200
switch this.GetDBGameFree().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 *IceAgeSceneData) AIAddJackPot() {
if time.Now().Sub(this.lastJackPot) > 0 {
var randT = rand.Intn(3) + 1
switch this.GetDBGameFree().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.GetDBGameFree().GetBaseScore()) * float64(rule.LINENUM) * float64(500) / 10000))
this.jackpot.VirtualJK += val
}
}
func (this *IceAgeSceneData) AIBurstJackPot() {
if time.Now().Sub(this.GetLastBurstJackPot()) > 0 {
this.SetLastBurstJackPot()
jackpotParams := this.GetDBGameFree().GetJackpot()
var jackpotInit = int64(jackpotParams[rule.ICEAGE_JACKPOT_InitJackpot]) * int64(this.GetDBGameFree().GetBaseScore()) //奖池初始值
//AI机器人爆奖
val := this.jackpot.VirtualJK
this.jackpot.VirtualJK = jackpotInit
bet := int64(this.GetDBGameFree().GetBaseScore()) * int64(rule.LINENUM)
this.RecordBurstLog(this.RandNickName(), val, bet)
}
}
func (this *IceAgeSceneData) 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.GetDBGameFree().GetId()))
// if !p.IsRob &&
// todayGamefreeIDSceneData != nil &&
// this.GetDBGameFree().GetPlayNumLimit() != 0 &&
// todayGamefreeIDSceneData.GameTimes >= int64(this.GetDBGameFree().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)
}
}
}
}