390 lines
12 KiB
Go
390 lines
12 KiB
Go
package iceage
|
||
|
||
import (
|
||
"encoding/json"
|
||
"math"
|
||
"math/rand"
|
||
"mongo.games.com/game/common"
|
||
"mongo.games.com/game/model"
|
||
"mongo.games.com/game/protocol/gamehall"
|
||
"mongo.games.com/game/protocol/iceage"
|
||
"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/goserver/core/logger"
|
||
)
|
||
|
||
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] * this.DbGameFree.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] * 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.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 *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.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 *IceAgeSceneData) BurstHistory(player *IceAgePlayerData) {
|
||
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 []*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.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 *IceAgeSceneData) 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))
|
||
//AI机器人
|
||
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
|
||
}
|
||
}
|
||
func (this *IceAgeSceneData) AIBurstJackPot() {
|
||
if time.Now().Sub(this.GetLastBurstJackPot()) > 0 {
|
||
this.SetLastBurstJackPot()
|
||
jackpotParams := this.DbGameFree.GetJackpot()
|
||
var jackpotInit = int64(jackpotParams[rule.ICEAGE_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 *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.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)
|
||
}
|
||
}
|
||
}
|
||
}
|