package hero import ( "crypto/rand" "go_dreamfactory/comm" "go_dreamfactory/pb" cfg "go_dreamfactory/sys/configure/structs" "math/big" ) func (this *apiComp) DrawCardCheck(session comm.IUserSession, req *pb.HeroDrawCardReq) (code pb.ErrorCode) { if req.DrawType < 0 && (req.DrawCount == 1 || req.DrawCount == 10) { // 只能是单抽或10抽 code = pb.ErrorCode_ReqParameterError } return } //抽卡 func (this *apiComp) DrawCard(session comm.IUserSession, req *pb.HeroDrawCardReq) (code pb.ErrorCode, data *pb.ErrorData) { var ( szCards []string // 最终抽到的卡牌 drawCount int32 // 抽卡次数 szStar []int32 //星级 costRes []*cfg.Gameatn // 消耗 star4Max int32 // 10连抽最大4星数量 star5Max int32 // 10连抽最大5星数量 cfgDraw *cfg.GameGlobalData costAtn *cfg.Gameatn heroRecord *pb.DBHeroRecord pool string // 当前抽对应的卡池 strPool []string // 10连跨多个卡池情况 update map[string]interface{} normalDraw bool // 是否是普通抽 ) update = make(map[string]interface{}) cfgDraw = this.module.ModuleTools.GetGlobalConf() // 读取抽卡配置文件 if cfgDraw == nil { return } code = this.DrawCardCheck(session, req) if code != pb.ErrorCode_Success { return } szCards = make([]string, 0) heroRecord, _ = this.module.modelRecord.GetHeroRecord(session.GetUserId()) drawCount = heroRecord.Drawcount if req.DrawType == 0 { // 普通卡池抽卡 normalDraw = true // 获取普通抽卡池 if req.DrawCount == 1 { costAtn = cfgDraw.BasePoolCost } else { costAtn = cfgDraw.BasePool10cost } costRes = append(costRes, costAtn) code = this.module.CheckRes(session, costRes) if code != pb.ErrorCode_Success { // 消耗数量不足直接返回 return } for i := 0; i < int(req.DrawCount); i++ { drawCount += 1 pool = this.module.modelHero.CheckPool(drawCount, cfgDraw) strPool = append(strPool, pool) ret := this.module.CheckCondition(session.GetUserId()) if ret == true { // 命中插入5星英雄 szStar = append(szStar, 5) heroRecord.Star5 = 0 // 重置保底 star5Max++ // 记录当前 5星数量 continue } // 3,4,5 星权重 starWeight := []int32{cfgDraw.BasePoolStar3, cfgDraw.BasePoolStar4, cfgDraw.BasePoolStar5} starIndex := this.module.modelHero.GetRandW(starWeight) // 3 4 5 星索引 // 特殊规则 DrawCard_5StarsInRange 第2-30次抽奖必出一个5星英雄(普通卡池) inRangeConf := this.module.ModuleTools.GetGlobalConf().DrawCard5StarsInRange if len(inRangeConf) == 3 { iStart := inRangeConf[0] // 抽卡开始 iEnd := inRangeConf[1] // 抽卡结束 star := inRangeConf[2] if star >= 3 { // 保底必须三星+ if heroRecord.Inevitable == 0 && heroRecord.Drawcount > iStart && heroRecord.Drawcount < iEnd && iEnd >= iStart { n, _ := rand.Int(rand.Reader, big.NewInt(int64(iEnd-iStart))) if n.Int64() < 1 { // 抽中 starIndex = star - 3 heroRecord.Inevitable = heroRecord.Drawcount update["inevitable"] = heroRecord.Drawcount szStar = append(szStar, star) if star == 4 { heroRecord.Star4 = 0 star4Max++ } else if star == 5 { star5Max++ heroRecord.Star5 = 0 } continue } } // 保底情况 if heroRecord.Drawcount == iEnd && heroRecord.Inevitable == 0 { starIndex = star - 3 heroRecord.Inevitable = heroRecord.Drawcount update["inevitable"] = heroRecord.Drawcount szStar = append(szStar, star) if star == 4 { heroRecord.Star4 = 0 star4Max++ } else if star == 5 { star5Max++ heroRecord.Star5 = 0 } continue } } } inRangeConf1 := this.module.ModuleTools.GetGlobalConf().DrawCard5StarsInRange1 if len(inRangeConf1) == 3 { iStart := inRangeConf1[0] // 抽卡开始 iEnd := inRangeConf1[1] // 抽卡结束 star := inRangeConf1[2] if star >= 3 { // 保底必须三星+ if heroRecord.Inevitable == 0 && heroRecord.Drawcount > iStart && heroRecord.Drawcount < iEnd && iEnd >= iStart { n, _ := rand.Int(rand.Reader, big.NewInt(int64(iEnd-iStart))) if n.Int64() < 1 { // 抽中 starIndex = star - 3 heroRecord.Inevitable = heroRecord.Drawcount update["inevitable1"] = heroRecord.Drawcount szStar = append(szStar, star) if star == 4 { heroRecord.Star4 = 0 star4Max++ } else if star == 5 { star5Max++ heroRecord.Star5 = 0 } // 修改卡池 newPoll := this.module.ModuleTools.GetGlobalConf().DrawCard5StarsInRange1Pool if newPoll != "" { strPool[len(strPool)-1] = newPoll } continue } } // 保底情况 if heroRecord.Drawcount == iEnd && heroRecord.Inevitable == 0 { starIndex = star - 3 heroRecord.Inevitable1 = heroRecord.Drawcount update["inevitable1"] = heroRecord.Drawcount szStar = append(szStar, star) if star == 4 { heroRecord.Star4 = 0 star4Max++ } else if star == 5 { star5Max++ heroRecord.Star5 = 0 } // 修改卡池 newPoll := this.module.ModuleTools.GetGlobalConf().DrawCard5StarsInRange1Pool if newPoll != "" { strPool[len(strPool)-1] = newPoll } continue } } } heroRecord.Star4++ // 4星保底数量+1 heroRecord.Star5++ // 5星保底数量+1 if starIndex == 1 { heroRecord.Star4 = 0 star4Max++ } else if starIndex == 2 { star5Max++ heroRecord.Star5 = 0 } if star4Max >= cfgDraw.Draw10Star4Max || star5Max >= cfgDraw.Draw10Star5Max { // 达到10连抽最大(4,5星)数量 直接给三星 starIndex = 0 } else { // 普通卡池保底 if cfgDraw.DrawFloorStar4 <= heroRecord.Star4 { heroRecord.Star4 = 0 starIndex = 1 } if cfgDraw.DrawFloorStar5 <= heroRecord.Star5 { heroRecord.Star5 = 0 starIndex = 2 } } szStar = append(szStar, starIndex+3) if len(szStar) >= int(req.DrawCount) { break } } } else { // 所有阵营抽卡都走这里 drawCount += req.DrawCount if req.DrawCount == 1 { switch req.DrawType { case 1: pool = cfgDraw.Camp1Pool1 costAtn = cfgDraw.Camp1PoolCost case 2: pool = cfgDraw.Camp2Pool1 costAtn = cfgDraw.Camp2PoolCost case 3: pool = cfgDraw.Camp3Pool1 costAtn = cfgDraw.Camp3PoolCost case 4: pool = cfgDraw.Camp4Pool1 costAtn = cfgDraw.Camp4PoolCost } strPool = append(strPool, pool) } else { costAtn = cfgDraw.Camp1PoolCost switch req.DrawType { case 1: pool = cfgDraw.Camp1Pool1 costAtn = cfgDraw.Camp1Pool10cost case 2: pool = cfgDraw.Camp2Pool1 costAtn = cfgDraw.Camp2Pool10cost case 3: pool = cfgDraw.Camp3Pool1 costAtn = cfgDraw.Camp3Pool10cost case 4: pool = cfgDraw.Camp4Pool1 costAtn = cfgDraw.Camp4Pool10cost } for i := 0; i < int(req.DrawCount); i++ { strPool = append(strPool, pool) } } costRes = append(costRes, costAtn) //阵营消耗 code = this.module.CheckRes(session, costRes) if code != pb.ErrorCode_Success { // 消耗数量不足直接返回 return } for { starWeight := []int32{cfgDraw.CampPoolStar3, cfgDraw.CampPoolStar4, cfgDraw.CampPoolStar5} starIndex := this.module.modelHero.GetRandW(starWeight) if starIndex == 1 { star4Max++ } else if starIndex == 2 { star5Max++ } if star4Max >= cfgDraw.Draw10Star4Max || star5Max >= cfgDraw.Draw10Star5Max { starIndex = 0 } szStar = append(szStar, starIndex) if len(szStar) >= int(req.DrawCount) { break } } } for index, star := range szStar { _data, err := this.module.configure.GetPollByType(strPool[index]) if err != nil { code = pb.ErrorCode_ConfigNoFound data.Message = err.Error() return } sz := make([]int32, 0) for _, v := range _data[int32(star)] { sz = append(sz, v.Weight) } randomIndex := this.module.modelHero.GetRandW(sz) if v, ok := _data[int32(star)]; ok { if int32(len(v)) > randomIndex { cardId := v[randomIndex].Id if star == 5 { // 抽出5星英雄后A次抽奖内不会再抽到5星英雄(普通卡池+阵营卡池) curDrawCount := drawCount - req.DrawCount if drawCount <= 10 { // 前10次不计算(连续抽卡最多连续出A个相同阵营的英雄) szCards = append(szCards, cardId) continue } newID := this.module.ContinuousRestriction(session.GetUserId(), cardId, curDrawCount+int32(index+1), strPool[index]) szCards = append(szCards, newID) continue } szCards = append(szCards, cardId) // 普通卡池 最多连续出A个相同阵营的英雄 if req.DrawType == 0 { newId := this.module.DrawCardContinuousRestrictionCamp(cardId, heroRecord.Race, sz, v) if cardId != newId { szCards[len(szCards)-1] = newId } } } } } // 消耗道具 code = this.module.ConsumeRes(session, costRes, true) if code != pb.ErrorCode_Success { return } heroRecord.Totalcount += req.DrawCount heroRecord.Daycount += req.DrawCount update["star4"] = heroRecord.Star4 update["star5"] = heroRecord.Star5 update["drawcount"] = drawCount update["totalcount"] = heroRecord.Totalcount update["daycount"] = heroRecord.Daycount this.module.modelRecord.ChangeHeroRecord(session.GetUserId(), update) rsp := &pb.HeroDrawCardResp{ Data: []*pb.AtnoData{}, } for _, heroId := range szCards { res := &cfg.Gameatn{ A: "hero", T: heroId, N: 1, } if code, atno := this.module.DispenseAtno(session, []*cfg.Gameatn{res}, true); code == pb.ErrorCode_Success { rsp.Data = append(rsp.Data, &pb.AtnoData{ Atno: atno, }) for _, v := range atno { if v.A == "hero" && v.N == 1 { if user := this.module.ModuleUser.GetUser(session.GetUserId()); user != nil { // 广播 首次获得英雄 this.chat.SendSysChatToWorld(comm.ChatSystem13, nil, 0, 0, user.Name, v.T) } } } } } session.SendMsg(string(this.module.GetType()), DrawCard, rsp) // 任务统计 this.module.SendTaskMsg(session, szStar, req.DrawCount, normalDraw) return }