353 lines
10 KiB
Go
353 lines
10 KiB
Go
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 = &pb.ErrorData{
|
||
Title: pb.GetErrorCodeMsg(code),
|
||
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
|
||
}
|