package main import ( "slices" "sort" "time" "mongo.games.com/goserver/core/logger" "mongo.games.com/goserver/core/netlib" "mongo.games.com/game/common" "mongo.games.com/game/model" "mongo.games.com/game/protocol/activity" "mongo.games.com/game/protocol/webapi" "mongo.games.com/game/srvdata" ) const ( PowerMax = 134000 PowerInit = 400000 ) var PushCoinItemValue = map[int32]int64{ common.ItemIDBigCoin: 50000, common.ItemIDVCard: 10000, common.ItemIDPlum: 30000, common.ItemIDCoin1: 5000, common.ItemIDCoin2: 10000, common.ItemIDCoin3: 15000, common.ItemIDDiamond: 100000, } func init() { // 推币机活动信息 common.Register(int(activity.PushCoinPacketID_PACKET_CSPushCoinInfo), activity.CSPushCoinInfo{}, CSPushCoinInfo) // 推币机玩家操作 common.Register(int(activity.PushCoinPacketID_PACKET_CSPushCoinPlayerOp), activity.CSPushCoinPlayerOp{}, CSPushCoinPlayerOp) } func CSPushCoinInfo(s *netlib.Session, packetid int, data interface{}, sid int64) error { _, ok := data.(*activity.CSPushCoinInfo) if !ok { return nil } p := PlayerMgrSington.GetOnlinePlayer(sid) if p == nil { logger.Logger.Warn("CSPushCoinInfo p == nil") return nil } if p.WelfData == nil { logger.Logger.Warn("CSPushCoinInfo p.WelfData == nil") return nil } if p.WelfData.PushCoin == nil || len(p.WelfData.PushCoin.Turn) == 0 { InitPlayerPushCoin(p) } pack := &activity.SCPushCoinInfo{ ShakeTimes: p.WelfData.PushCoin.Shake, PowerLine: p.WelfData.PushCoin.Power, PowerLineMax: PowerMax, RefreshTimes: p.WelfData.PushCoin.Refresh, } for k, v := range p.WelfData.PushCoin.Items { pack.Items = append(pack.Items, &activity.ItemInfo{ ItemId: k, ItemNum: v, }) } for _, v := range srvdata.PBDB_PropExchangeMgr.Datas.Arr { if v.GetGroup() == 2 { info := &activity.ExchangeInfo{ Id: v.GetId(), TotalTimes: int64(v.GetTimes()), } for kk, vv := range v.GetCost() { info.Cost = append(info.Cost, &activity.ItemInfo{ ItemId: int32(kk), ItemNum: vv, }) } sort.Slice(info.Cost, func(i, j int) bool { return info.Cost[i].ItemId < info.Cost[j].ItemId }) for kk, vv := range v.GetGain() { info.Gain = append(info.Gain, &activity.ItemInfo{ ItemId: int32(kk), ItemNum: vv, }) } sort.Slice(info.Gain, func(i, j int) bool { return info.Gain[i].ItemId < info.Gain[j].ItemId }) info.Times = int64(v.GetTimes() - p.WelfData.PushCoin.Exchange[v.Id]) if v.GetTimes() == 0 { info.Times = -1 info.TotalTimes = -1 } pack.ExchangeList = append(pack.ExchangeList, info) } } pack.DrawList = make([]*activity.DrawInfo, len(p.WelfData.PushCoin.Turn)) for k, v := range p.WelfData.PushCoin.Turn { info := &activity.DrawInfo{ Id: int32(k), } // 默认奖励 if slices.Contains(NormaIndex, k) { d := srvdata.PBDB_ACTPushCoinMgr.GetData(v) if d != nil { for kk, vv := range d.GetGain() { info.ItemId = int32(kk) info.ItemNum = vv break } pack.DrawList[k] = info } continue } // 奖池 if slices.Contains(PoolIndex, k) { ii := slices.Index(PoolIndex, k) if v == -1 { // 从奖池中随机 var element *webapi.PushCoinPoolElement var index int32 cfg := WelfareMgrSington.GetConfig(p.Platform).PushCoinConfig if ii == 0 { element, index = PushCoinPoolRandom(cfg.GetPool1().GetPool()) } else if ii == 1 { element, index = PushCoinPoolRandom(cfg.GetPool2().GetPool()) } else if ii == 2 { element, index = PushCoinPoolRandom(cfg.GetPool3().GetPool()) } if index >= 0 && element != nil { p.WelfData.PushCoin.Turn[k] = index for _, v := range element.GetAward() { info.ItemId = v.GetItemId() info.ItemNum = v.GetItemNum() break } pack.DrawList[k] = info } } else { // 随机过了 f := func(index int, pool []*webapi.PushCoinPoolElement) { if index < len(pool) { for _, v := range pool[index].GetAward() { info.ItemId = v.GetItemId() info.ItemNum = v.GetItemNum() break } pack.DrawList[k] = info } } cfg := WelfareMgrSington.GetConfig(p.Platform).PushCoinConfig if cfg != nil { if ii == 0 { f(int(v), cfg.GetPool1().GetPool()) } else if ii == 1 { f(int(v), cfg.GetPool2().GetPool()) } else if ii == 2 { f(int(v), cfg.GetPool3().GetPool()) } } } } } p.SendToClient(int(activity.PushCoinPacketID_PACKET_SCPushCoinInfo), pack) logger.Logger.Trace("SCPushCoinInfo: ", pack) return nil } func CSPushCoinPlayerOp(s *netlib.Session, packetid int, data interface{}, sid int64) error { logger.Logger.Trace("CSPushCoinPlayerOpHandler Process recv ", data) msg, ok := data.(*activity.CSPushCoinPlayerOp) if !ok { return nil } p := PlayerMgrSington.GetOnlinePlayer(sid) if p == nil { logger.Logger.Warn("CSPushCoinPlayerOp p == nil") return nil } if p.scene != nil { logger.Logger.Warn("CSPushCoinPlayerOp p.scene != nil") return nil } if p.WelfData == nil { logger.Logger.Warn("CSPushCoinPlayerOp p.WelfData == nil") return nil } if p.WelfData.PushCoin == nil { logger.Logger.Warn("CSPushCoinPlayerOp p.WelfData.PushCoin == nil") return nil } // 活动时间检测 now := time.Now() cfg := WelfareMgrSington.GetConfig(p.Platform).PushCoinConfig if cfg == nil { logger.Logger.Warn("CSPushCoinPlayerOp cfg == nil") return nil } if cfg.GetOn() != common.On || now.Unix() < common.StrTimeToTs(cfg.GetStartTime()) || now.Unix() >= common.StrTimeToTs(cfg.GetEndTime()) { logger.Logger.Warn("CSPushCoinPlayerOp cfg.GetOn() == common.Off or end") return nil } pack := &activity.SCPushCoinPlayerOp{ OpRetCode: activity.OpResultPushCoinCode_OPRC_PushCoin_Error, OpCode: msg.GetOpCode(), } switch msg.GetOpCode() { case activity.OpCodes_OP_Bet: if msg.GetOpParam() != common.ItemIDCoin1 && msg.GetOpParam() != common.ItemIDCoin2 && msg.GetOpParam() != common.ItemIDCoin3 { goto here } item := srvdata.GameItemMgr.Get(p.Platform, int32(msg.GetOpParam())) if item == nil { goto here } if p.GetCoin() < item.GetNum() { pack.OpRetCode = activity.OpResultPushCoinCode_OPRC_PushCoin_BetNotEnough goto here } pack.BetId = int32(msg.GetOpParam()) p.AddCoin(-item.GetNum(), 0, common.GainWayPushCoinCost, "system", "推币机下注") // 增加桌面道具 PushCoinAddValue(p, map[int32]int64{ int32(msg.GetOpParam()): 1, }) // 增加水池 PushCoinPoolMangerInstance.Add(p.Platform, item.GetNum()) case activity.OpCodes_OP_Gain: if msg.GetOpParam() == 1 { // 有效区 for _, v := range msg.GetOpItem() { id := v.GetItemId() val := v.GetItemNum() if p.WelfData.PushCoin.Items[id] < val { logger.Logger.Errorf("获得道具太多: %d, %d", p.WelfData.PushCoin.Items[id], val) // 刷新桌面余额 //UpdatePlayerPushCoin(p) goto here } switch v.GetItemId() { case common.ItemIDBigCoin, common.ItemIDCoin1, common.ItemIDCoin2, common.ItemIDCoin3: val *= srvdata.GameItemMgr.Get(p.Platform, id).GetNum() id = common.ItemIDCoin } BagMgrSingleton.AddItems(&model.AddItemParam{ Platform: p.Platform, SnId: p.SnId, Change: []*model.Item{{ItemId: id, ItemNum: val}}, GainWay: common.GainWayPushCoinGain, Operator: "system", Remark: "推币机掉落获得", }) } } else { // 无效区 for _, v := range msg.GetOpItem() { id := v.GetItemId() val := v.GetItemNum() if p.WelfData.PushCoin.Items[id] < val { logger.Logger.Errorf("获得道具太多,无效区: %d, %d", p.WelfData.PushCoin.Items[id], val) goto here } } } for _, v := range msg.GetOpItem() { // 增加能量条 val := GetPushCoinValue(p.Platform, v.GetItemId()) if val <= 0 { logger.Logger.Errorf("推币机价值查询bug itemId:%v", v.GetItemId()) } if msg.GetOpParam() != 1 { PushCoinAddPower(p, val*v.GetItemNum()) } logger.Logger.Debugf("推币机,掉落 ItemId:%v ItemNum:%v Value:%v", v.GetItemId(), v.GetItemNum(), val) // 减少桌面道具 PushCoinAddValue(p, map[int32]int64{v.GetItemId(): -v.GetItemNum()}) } case activity.OpCodes_OP_Shake: if p.WelfData.PushCoin.Shake < int32(msg.GetOpParam()) { pack.OpRetCode = activity.OpResultPushCoinCode_OPRC_PushCoin_ShakeNotEnough goto here } p.WelfData.PushCoin.Shake -= int32(msg.GetOpParam()) case activity.OpCodes_OP_Refresh: //if p.WelfData.PushCoin.Refresh <= 0 { // InitPlayerPushCoin(p) //} else { // UpdatePlayerPushCoin(p) //} case activity.OpCodes_OP_Exchange: d := srvdata.PBDB_PropExchangeMgr.GetData(int32(msg.GetOpParam())) if d == nil { goto here } // 兑换次数 if d.GetTimes() > 0 && p.WelfData.PushCoin.Exchange[d.Id] >= d.GetTimes() { pack.OpRetCode = activity.OpResultPushCoinCode_OPRC_PushCoin_ExchangeNotEnough goto here } pack.Exchange = &activity.ExchangeInfo{ Id: d.Id, } var cost, gain []*model.Item for k, v := range d.GetCost() { pack.Exchange.Cost = append(pack.Exchange.Cost, &activity.ItemInfo{ ItemId: int32(k), ItemNum: v, }) if k == common.ItemIDCoin && p.GetCoin() < v { pack.OpRetCode = activity.OpResultPushCoinCode_OPRC_PushCoin_ItemNotEnough goto here } cost = append(cost, &model.Item{ ItemId: int32(k), ItemNum: -v, }) } _, _, ok := BagMgrSingleton.AddItems(&model.AddItemParam{ Platform: p.Platform, SnId: p.SnId, Change: cost, Add: 0, GainWay: common.GainWayPushCoinExchangeCost, Operator: "system", Remark: "推币机活动兑换消耗", }) if !ok { pack.OpRetCode = activity.OpResultPushCoinCode_OPRC_PushCoin_ItemNotEnough goto here } for k, v := range d.GetGain() { pack.Exchange.Gain = append(pack.Exchange.Gain, &activity.ItemInfo{ ItemId: int32(k), ItemNum: v, }) if k == common.ItemIDShake { p.WelfData.PushCoin.Shake += int32(v) } gain = append(gain, &model.Item{ ItemId: int32(k), ItemNum: v, }) } for _, v := range cost { if v.ItemNum < 0 { v.ItemNum = -v.ItemNum } } BagMgrSingleton.AddItems(&model.AddItemParam{ Platform: p.Platform, SnId: p.SnId, Change: gain, Cost: cost, Add: 0, GainWay: common.GainWatPushCoinExchangeGain, Operator: "system", Remark: "推币机活动兑换获得", }) if p.WelfData.PushCoin.Exchange == nil { p.WelfData.PushCoin.Exchange = make(map[int32]int32) } p.WelfData.PushCoin.Exchange[d.Id]++ default: return nil } pack.OpRetCode = activity.OpResultPushCoinCode_OPRC_PushCoin_Success here: p.SendToClient(int(activity.PushCoinPacketID_PACKET_SCPushCoinPlayerOp), pack) logger.Logger.Trace("SCPushCoinPlayerOp: ", pack) return nil } func InitPlayerPushCoin(p *Player) { // 初始化 p.WelfData.PushCoin = &model.PushCoinData{ Power: PowerInit, Exchange: make(map[int32]int32), Items: map[int32]int64{ common.ItemIDVCard: 1, common.ItemIDCoin1: 50, common.ItemIDPlum: 1, }, Turn: []int32{ // 转盘表数据id 1, 4, -1, 3, -1, 2, -1, 5, 9, }, Next: -1, PoolV: []int64{-1, -1, -1}, } } // PushCoinAddPower 增加能量条 func PushCoinAddPower(p *Player, value int64) { if value < 0 { return } p.WelfData.PushCoin.Power += value if p.WelfData.PushCoin.Power > PowerMax { p.WelfData.PushCoin.Power = PowerMax } pack := &activity.NotifyPowerLine{ PowerLine: p.WelfData.PushCoin.Power, PowerLineMax: PowerMax, } p.SendToClient(int(activity.PushCoinPacketID_PACKET_NotifyPowerLine), pack) logger.Logger.Tracef("刷新能量条: %v", pack) if value <= 0 { return } // 抽奖 PushCoinDraw(p) } // PushCoinDraw 抽奖 func PushCoinDraw(p *Player) { if p.WelfData.PushCoin.Power < PowerMax { return } p.WelfData.PushCoin.Power = 0 var draw *activity.DrawInfo var draw1 []*activity.DrawInfo // 奖池返奖 f1 := func() bool { pool := PushCoinPoolMangerInstance.PlatformConfig[p.Platform] if pool == nil { return false } // fp 奖池返奖,返回是否成功 fp := func(i int, poolInfo *model.PushCoinPoolInfo) bool { // 是否返奖 if poolInfo == nil || poolInfo.Remain <= 0 { return false } // 玩家奖池没有返过奖 if len(p.WelfData.PushCoin.PoolV) > i && p.WelfData.PushCoin.PoolV[i] < poolInfo.Version { cfg := WelfareMgrSington.GetConfig(p.Platform).PushCoinConfig poolIndex := p.WelfData.PushCoin.Turn[PoolIndex[i]] value := int64(0) // 奖品价值 if int(poolIndex) < len(cfg.GetPool1().GetPool()) { e := cfg.GetPool1().GetPool()[poolIndex] if e != nil { for _, v := range e.GetAward() { iv, ok := PushCoinItemValue[v.GetItemId()] if ok { value = v.GetItemNum() * iv } else { value = v.GetItemNum() * e.GetValue() // 目前只有实物是自定义的价值 } break } } } if value > 0 { // 价值是否足够 if poolInfo.Remain-value < 0 { return false } // 扣除价值 poolInfo.Remain -= value // 刷新玩家奖池版本 p.WelfData.PushCoin.PoolV[i] = poolInfo.Version // 下次中奖位置 p.WelfData.PushCoin.Next = int32(PoolIndex[i]) logger.Logger.Tracef("下次中奖池:%+v", p.WelfData.PushCoin) return true } } return false } // 奖池1 if fp(0, pool.Pool1) { return true } // 奖池2 if fp(1, pool.Pool2) { return true } // 奖池3 if fp(2, pool.Pool3) { return true } return false } switch p.WelfData.PushCoin.Dram { case 0: // 必中大金币 draw = PushCoinNormalRandom(common.ItemIDBigCoin) draw.Id = 0 // 查表 // 下次必中v卡 p.WelfData.PushCoin.Next = 5 // 查表 default: // 使用预生成结果 if p.WelfData.PushCoin.Next >= 0 { k := p.WelfData.PushCoin.Next val := p.WelfData.PushCoin.Turn[p.WelfData.PushCoin.Next] if slices.Contains(NormaIndex, int(k)) { // 普通奖品 for kk, vv := range srvdata.PBDB_ACTPushCoinMgr.GetData(val).GetGain() { draw = &activity.DrawInfo{ Id: k, ItemId: int32(kk), ItemNum: vv, } logger.Logger.Tracef("中奖普通奖品:%v", draw) } } if slices.Contains(PoolIndex, int(k)) { f := func(i int, list []*webapi.PushCoinPoolElement) { // 本次奖品 if i < len(list) { for _, v := range list[i].GetAward() { draw = &activity.DrawInfo{ Id: k, ItemId: v.GetItemId(), ItemNum: v.GetItemNum(), } logger.Logger.Tracef("中奖奖池奖品:%v", draw) break } } else { logger.Logger.Errorf("奖池抽奖bug: %d, %d, %d", k, i, len(list)) } // 刷新奖池 e, index := PushCoinPoolRandom(list) if e != nil { p.WelfData.PushCoin.Turn[k] = index for _, v := range e.GetAward() { draw1 = append(draw1, &activity.DrawInfo{ Id: k, ItemId: v.GetItemId(), ItemNum: v.GetItemNum(), }) logger.Logger.Tracef("刷新奖池奖品:%v", draw1) break } } else { logger.Logger.Errorf("奖池刷新bug: %d, %d, %d", k, i, len(list)) } } // 水池奖品 var poolElements []*webapi.PushCoinPoolElement switch slices.Index(PoolIndex, int(k)) { case 0: poolElements = WelfareMgrSington.GetConfig(p.Platform).PushCoinConfig.GetPool1().GetPool() case 1: poolElements = WelfareMgrSington.GetConfig(p.Platform).PushCoinConfig.GetPool2().GetPool() case 2: poolElements = WelfareMgrSington.GetConfig(p.Platform).PushCoinConfig.GetPool3().GetPool() } f(int(val), poolElements) } } // 下次中奖位置 // 奖池返奖 或 普通抽奖 if !f1() { // 普通抽奖 curIndex := p.WelfData.PushCoin.Next index := int(p.WelfData.PushCoin.Next) // 奖品位置 e := PushCoinNormalRandom(0) e1 := PushCoinNormalRandom(0) if e != nil { var has bool for k, v := range p.WelfData.PushCoin.Turn { if slices.Contains(NormaIndex, k) && v == e.GetId() { has = true index = k break } } if !has { // 替换 if slices.Contains(PoolIndex, index) { // 找一个普通奖品位置 index = NormaIndex[common.RandInt(len(NormaIndex[:len(NormaIndex)-1]))] } draw1 = append(draw1, &activity.DrawInfo{ Id: int32(index), ItemId: e.GetItemId(), ItemNum: e.GetItemNum(), }) p.WelfData.PushCoin.Turn[index] = e.GetId() } else { p.WelfData.PushCoin.Turn[curIndex] = e1.GetId() draw1 = append(draw1, &activity.DrawInfo{ Id: curIndex, ItemId: e1.GetItemId(), ItemNum: e1.GetItemNum(), }) } p.WelfData.PushCoin.Next = int32(index) logger.Logger.Tracef("下次中普通奖品:index:%v ItemId:%v Num:%v", index, e.GetItemId(), e.GetItemNum()) } } } p.WelfData.PushCoin.Dram++ if draw != nil { pack := &activity.NotifyDrawInfo{ Draw: draw, } if len(draw1) > 0 { pack.Info = draw1 } PushCoinAddValue(p, map[int32]int64{draw.GetItemId(): draw.GetItemNum()}) p.SendToClient(int(activity.PushCoinPacketID_PACKET_NotifyDrawInfo), pack) logger.Logger.Trace("NotifyDrawInfo: ", pack) if slices.Contains(PoolIndex, int(draw.GetId())) { pk := &activity.NotifyAward{ Draw: draw, Name: p.GetName(), } // 广播抽奖信息 PlatformMgrSingleton.Broadcast(int(activity.PushCoinPacketID_PACKET_NotifyAward), pk, nil, 0) logger.Logger.Trace("Broadcast NotifyAward: ", pk) } // 刷新能量条 PushCoinAddPower(p, 0) } } // PushCoinAddValue 增加桌面道具 func PushCoinAddValue(p *Player, item map[int32]int64) { if item == nil { return } if p.WelfData != nil && p.WelfData.PushCoin != nil { if p.WelfData.PushCoin.Items == nil { p.WelfData.PushCoin.Items = make(map[int32]int64) } for k, v := range item { p.WelfData.PushCoin.Items[k] += v logger.Logger.Tracef("桌面数据 ItemId:%v Change:%v Num:%v", k, v, p.WelfData.PushCoin.Items[k]) } } } func PushCoinPoolRandom(pool []*webapi.PushCoinPoolElement) (*webapi.PushCoinPoolElement, int32) { var total int32 for _, v := range pool { if v.GetOn() == common.On { total += v.GetWeight() } } if total <= 0 { return nil, -1 } var n int32 rn := int32(common.RandInt(int(total))) for k, v := range pool { if v.GetOn() == common.On { n += v.GetWeight() if rn < n { return v, int32(k) } } } return nil, -1 } func PushCoinNormalRandom(itemId int64) *activity.DrawInfo { var total int32 var index = int32(-1) // 随机id var n int32 if itemId == 0 { // 随机抽奖 for _, vv := range srvdata.PBDB_ACTPushCoinMgr.Datas.GetArr() { total += vv.GetRate() } rn := int32(common.RandInt(int(total))) for _, vv := range srvdata.PBDB_ACTPushCoinMgr.Datas.GetArr() { n += vv.GetRate() if rn < n { index = vv.GetId() break } } if index >= 0 { for kk, vv := range srvdata.PBDB_ACTPushCoinMgr.GetData(index).GetGain() { draw := &activity.DrawInfo{ Id: index, ItemId: int32(kk), ItemNum: vv, } return draw } } return nil } // 前两次必中 for _, v := range srvdata.PBDB_ACTPushCoinMgr.Datas.GetArr() { for kk, vv := range v.GetGain() { if kk == itemId { draw := &activity.DrawInfo{ ItemId: int32(kk), ItemNum: vv, } return draw } } } return nil } // GetPushCoinValue 查询物品价值,没有的是后台配置的价值 func GetPushCoinValue(plt string, itemId int32) int64 { val, ok := PushCoinItemValue[itemId] if ok { return val } cfg := WelfareMgrSington.GetConfig(plt).PushCoinConfig if cfg != nil { f := func(list []*webapi.PushCoinPoolElement) bool { for _, vv := range list { for _, vvv := range vv.GetAward() { if vvv.GetItemId() == itemId { val = vv.GetValue() return true } } } return false } for { if f(cfg.GetPool1().GetPool()) { break } if f(cfg.GetPool2().GetPool()) { break } if f(cfg.GetPool3().GetPool()) { break } break } } return val }