go_dreamfactory/modules/hero/api_drawCard.go
2024-01-11 17:39:45 +08:00

478 lines
15 KiB
Go

package hero
import (
"crypto/rand"
"fmt"
"go_dreamfactory/comm"
"go_dreamfactory/pb"
"go_dreamfactory/sys/configure"
cfg "go_dreamfactory/sys/configure/structs"
"math/big"
)
func (this *apiComp) DrawCardCheck(session comm.IUserSession, req *pb.HeroDrawCardReq) (errdata *pb.ErrorData) {
if req.DrawType < 0 || (req.DrawCount != 1 && req.DrawCount != 10) { // 只能是单抽或10抽
errdata = &pb.ErrorData{
Code: pb.ErrorCode_ReqParameterError,
Title: pb.ErrorCode_ReqParameterError.ToString(),
}
}
return
}
//抽卡
func (this *apiComp) DrawCard(session comm.IUserSession, req *pb.HeroDrawCardReq) (errdata *pb.ErrorData) {
var (
szCards []string // 最终抽到的卡牌
drawCount int32 // 抽卡次数
szStar []int32 //星级
costRes []*cfg.Gameatn // 消耗
star4Count int32 // 10连抽4星数量
star5Count int32 // 10连抽5星数量
cfgGlobal *cfg.GameGlobalData // 全局配置
heroRecord *pb.DBHeroRecord
strPool []string // 10连跨多个卡池情况
update map[string]interface{}
drawConf *cfg.GameDrawPoolData
err error
atno []*pb.UserAtno
IsBaodiPool bool // 是否是保底卡池
appointmap map[int32]string // 指定次数抽卡到指定卡池
reward []*cfg.Gameatn // 许愿石奖励
)
update = make(map[string]interface{})
appointmap = make(map[int32]string)
szCards = make([]string, 0)
if heroRecord, err = this.module.modelRecord.GetHeroRecord(session.GetUserId()); err != nil {
errdata = &pb.ErrorData{
Code: pb.ErrorCode_DBError,
Title: pb.ErrorCode_DBError.ToString(),
Message: err.Error(),
}
return
}
cfgGlobal = this.module.ModuleTools.GetGlobalConf() // 读取抽卡配置文件
if cfgGlobal == nil {
return
}
if req.DrawType == 1 { // 新手抽卡校验
if heroRecord.Newcomplete {
errdata = &pb.ErrorData{
Code: pb.ErrorCode_HeroSelectDrawComplete,
Title: pb.ErrorCode_HeroSelectDrawComplete.ToString(),
}
return
}
if cfgGlobal.NewDrawcardAttemptsNums <= heroRecord.Selectcount { // 次数校验
errdata = &pb.ErrorData{
Code: pb.ErrorCode_HeroSelectMaxCount,
Title: pb.ErrorCode_HeroSelectMaxCount.ToString(),
}
return
}
}
rsp := &pb.HeroDrawCardResp{
Data: []*pb.AtnoData{},
Wish: &pb.UserAtno{},
Record: heroRecord,
}
// 校验是否是心愿招募
if req.DrawType == comm.DrawCardType6 && req.DrawCount == 1 {
errdata = this.wishDrawCard(session, heroRecord)
return
}
// 准备数据
/////////////////////////////////////
drawConf, err = this.module.configure.GetHeroDrawConfigByType(req.DrawType) // 获取新的抽卡配置
if err != nil {
errdata = &pb.ErrorData{
Code: pb.ErrorCode_ReqParameterError,
Title: pb.ErrorCode_ReqParameterError.ToString(),
Message: err.Error(),
}
return
}
for _, v := range drawConf.RecruitmentType {
appointmap[v.K] = v.S // 指定次抽数据
}
////////////////////////////////////////////////////////
// 每日抽卡上限校验
if cfgGlobal.DrawToplimit < heroRecord.Daycount+req.DrawCount {
errdata = &pb.ErrorData{
Code: pb.ErrorCode_HeroDayDrwaMax,
Title: pb.ErrorCode_HeroDayDrwaMax.ToString(),
Message: fmt.Sprintf("单日抽卡达到上限,抽卡次数:%d", cfgGlobal.DrawToplimit),
}
return
}
if errdata = this.DrawCardCheck(session, req); errdata != nil {
return
}
drawCount = heroRecord.Count[req.DrawType] // 获取当前阵容抽卡次数
if true { // 普通卡池抽卡
////// 获取消耗
if costRes, errdata = this.module.modelHero.CheckDrawCardRes(session, drawConf, req.Consume, req.DrawCount); errdata != nil {
return
}
// 校验是否达到保底卡池
if drawConf.Protect >= drawCount && drawConf.Protect != 0 {
IsBaodiPool = true
}
///// 获取消耗 end
for i := 1; i <= int(req.DrawCount); i++ { // 一张一张的抽
heroRecord.Race[req.DrawType] += 1
drawCount++
heroRecord.Baodi5[req.DrawType]++
heroRecord.Baodi4[req.DrawType]++
if v, ok := appointmap[drawCount]; ok { // 优先校验是否是指定抽
strPool = append(strPool, v) //找到了
continue
}
Is5Star := false
starWeight := []int32{drawConf.Star3w, drawConf.Star4w, drawConf.Star5w} // 随机获取三星
if drawConf.Permission != -1 && heroRecord.Baodi5[req.DrawType] > 0 { // 橙权递增
starWeight[2] += this.module.configure.GetHeroDrawWeightConfigById(drawConf.Permission, heroRecord.Baodi5[req.DrawType])
}
starIndex := comm.GetRandW(starWeight) // 3 4 5 星索引
if IsBaodiPool {
if starIndex == 0 {
strPool = append(strPool, drawConf.P3pool)
} else if starIndex == 1 {
star4Count++
heroRecord.Baodi4[req.DrawType] = 0
strPool = append(strPool, drawConf.P4pool)
} else if starIndex == 2 {
star5Count++
heroRecord.Baodi5[req.DrawType] = 0
strPool = append(strPool, drawConf.P5pool)
Is5Star = true
}
} else {
if starIndex == 0 {
strPool = append(strPool, drawConf.N3pool)
} else if starIndex == 1 {
star4Count++
heroRecord.Baodi4[req.DrawType] = 0
strPool = append(strPool, drawConf.N4pool)
} else if starIndex == 2 {
star5Count++
heroRecord.Baodi5[req.DrawType] = 0
strPool = append(strPool, drawConf.N5pool)
Is5Star = true
}
}
// 判断是否必出5星
if heroRecord.Baodi5[req.DrawType] >= drawConf.Baidi5 && !Is5Star {
heroRecord.Baodi5[req.DrawType] = 0
star5Count++
if IsBaodiPool {
strPool[len(strPool)-1] = drawConf.P5pool
} else {
strPool[len(strPool)-1] = drawConf.N5pool
}
Is5Star = true
continue
}
// 判断是否必出4星
if heroRecord.Baodi4[req.DrawType] >= drawConf.Baodi4 {
heroRecord.Baodi4[req.DrawType] = 0
star4Count++
if IsBaodiPool {
strPool[len(strPool)-1] = drawConf.P4pool
} else {
strPool[len(strPool)-1] = drawConf.N4pool
}
continue
}
if req.DrawCount == 10 {
if star4Count >= cfgGlobal.Draw10Star4Max { // 10连抽最大4星数量
if IsBaodiPool {
strPool[len(strPool)-1] = drawConf.P3pool
} else {
strPool[len(strPool)-1] = drawConf.N3pool
}
}
if star5Count >= cfgGlobal.Draw10Star5Max { // 10连抽最大5星数量
if IsBaodiPool {
strPool[len(strPool)-1] = drawConf.P3pool
} else {
strPool[len(strPool)-1] = drawConf.N3pool
}
}
}
}
}
// 通过卡池获得最终的英雄
for _, v := range strPool {
card, err := this.module.configure.GetHeroByPool(v)
if err != nil {
errdata = &pb.ErrorData{
Code: pb.ErrorCode_ConfigNoFound,
Title: pb.ErrorCode_ConfigNoFound.ToString(),
Message: err.Error(),
}
return
}
szCards = append(szCards, card)
}
// 消耗道具
if req.DrawType == 1 && heroRecord.Selectcount > 0 { // 新手抽 非第一次不消耗
costRes = nil
}
if errdata = this.module.ConsumeRes(session, costRes, true); errdata != nil {
return
}
heroRecord.Totalcount += req.DrawCount
heroRecord.Daycount += req.DrawCount
heroRecord.Count[req.DrawType] = drawCount
update["drawcount"] = drawCount
update["count"] = heroRecord.Count
update["totalcount"] = heroRecord.Totalcount
update["race"] = heroRecord.Race
update["daycount"] = heroRecord.Daycount
update["baodi4"] = heroRecord.Baodi4
update["baodi5"] = heroRecord.Baodi5
var tmp4 *cfg.Gameatn
tmp4 = this.module.ModuleTools.GetGlobalConf().RewardStar4
var tmp5 *cfg.Gameatn
tmp5 = this.module.ModuleTools.GetGlobalConf().RewardStar5
for i, heroId := range szCards {
if HeroConf, err := this.module.configure.GetHeroConfig(heroId); err != nil {
errdata = &pb.ErrorData{
Code: pb.ErrorCode_ConfigNoFound,
Message: err.Error(),
}
return
} else {
szStar = append(szStar, HeroConf.Star) // 获得许愿石
if HeroConf.Star == 4 {
if rsp.Wish == nil {
rsp.Wish = &pb.UserAtno{A: tmp4.A, T: tmp4.T, N: tmp4.N}
} else {
rsp.Wish.N += tmp4.N
}
reward = append(reward, tmp4)
} else if HeroConf.Star == 5 {
if rsp.Wish == nil {
rsp.Wish = &pb.UserAtno{A: tmp5.A, T: tmp5.T, N: tmp5.N}
} else {
rsp.Wish.N += tmp5.N
}
reward = append(reward, tmp5)
if card := this.drawLimitHero(req.DrawType, heroRecord, drawConf, update); card != "" {
szCards[i] = card
}
}
}
}
var (
res [][]*cfg.Gameatn
add []*pb.DBHero
allres []*cfg.Gameatn
bImitate bool
)
if req.DrawType == 1 {
bImitate = true
} else {
bImitate = false
}
if res, add, err = this.module.modelHero.ImitateHeros(session, szCards, bImitate); err == nil {
for _, v := range res {
var atno []*pb.UserAtno
for _, v1 := range v {
if v1.A != "hero" { // 不发英雄
allres = append(allres, v1)
}
atno = append(atno, &pb.UserAtno{
A: v1.A,
T: v1.T,
N: v1.N,
})
}
rsp.Data = append(rsp.Data, &pb.AtnoData{Atno: atno})
}
}
if req.DrawType == 1 {
heroRecord.Selectcount += 1 // 抽卡次数+1
heroRecord.Cur = szCards
update["selectcount"] = heroRecord.Selectcount
update["cur"] = heroRecord.Cur
} else {
allres = append(allres, reward...)
if errdata, atno = this.module.DispenseAtno(session, allres, true); errdata != nil { //同意发送奖励
return
}
}
this.module.modelRecord.ChangeHeroRecord(session.GetUserId(), update)
session.SendMsg(string(this.module.GetType()), DrawCard, rsp)
if req.DrawType != 1 {
// 任务统计
go this.module.AsynHandleSession(session.Clone(), func(session comm.IUserSession) {
this.module.modelDrawRecode.AddDrawRecord(session, req.DrawType, szCards)
var szHero []*pb.DBHero
for _, hero := range add { // 奖励一次性发放
if user, err := this.module.GetUserForSession(session); err == nil { // 广播 首次获得英雄
HeroConf, _ := this.module.configure.GetHeroConfig(hero.HeroID)
this.chat.SendSysChatToWorld(session, comm.ChatSystem13, hero, HeroConf.Star, 0, user.Name, hero.HeroID)
}
szHero = append(szHero, hero)
}
this.module.HeroLibrary(session, szCards, szHero)
this.module.SendTaskMsg(session, szStar, req.DrawCount, req.DrawType, szCards)
this.module.WriteUserLog(session.GetUserId(), req, comm.GMResAddType, "HeroDrawCardReq", atno)
this.module.WriteUserLog(session.GetUserId(), req, comm.GMResDelType, "HeroDrawCardReq", costRes)
})
} else {
go this.module.AsynHandleSession(session.Clone(), func(session comm.IUserSession) {
this.module.WriteUserLog(session.GetUserId(), req, comm.GMResDelType, "HeroDrawCardReq", costRes)
})
}
return
}
func (this *apiComp) drawLimitHero(dtype int32, heroRecord *pb.DBHeroRecord, drawConf *cfg.GameDrawPoolData, update map[string]interface{}) (card string) {
if dtype != comm.DrawCardType5 { // 限时招募
return
}
if heroRecord.LimitHero == "" { // 选默认的
if conf := this.module.configure.GetApportHeroReplaceConfig(); conf != nil {
heroRecord.LimitHero = conf.InitHero
}
}
// 新账号 一定替换
if !heroRecord.Uphero {
heroRecord.Uphero = true
update["uphero"] = heroRecord.Uphero
update["limitHero"] = heroRecord.LimitHero
card = heroRecord.LimitHero // 替换成心愿英雄
} else {
bingo := false
if heroRecord.Upherocount == 0 { // 概率替换
if drawConf.Upweight >= 1000 {
bingo = true
} else {
n, _ := rand.Int(rand.Reader, big.NewInt(1000))
if int32(n.Int64()) <= drawConf.Upweight {
bingo = true
} else {
heroRecord.Upherocount++
update["upherocount"] = heroRecord.Upherocount
}
}
} else {
bingo = true
heroRecord.Upherocount = 0 // 清理保底
update["upherocount"] = heroRecord.Upherocount
}
if bingo {
update["limitHero"] = heroRecord.LimitHero
card = heroRecord.LimitHero // 替换成心愿英雄
}
}
return card
}
func (this *apiComp) wishDrawCard(session comm.IUserSession, heroRecord *pb.DBHeroRecord) (errdata *pb.ErrorData) {
var (
cd int64
drcount int32
costRes []*cfg.Gameatn
atno []*pb.UserAtno
update map[string]interface{}
rsp *pb.HeroDrawCardResp
)
rsp = &pb.HeroDrawCardResp{}
update = make(map[string]interface{})
if conf := this.module.configure.GetWishHeroReplaceConfig(); conf != nil {
if heroRecord.WishHero == "" { // 如果当前许愿英雄是空 则读取 默认许愿英雄
heroRecord.WishHero = conf.InitHero
}
cd = int64(conf.Cond[heroRecord.WishHero].cd)
drcount = conf.Cond[heroRecord.WishHero].num
// 校验该抽卡是否在CD 中
if outTime, ok := heroRecord.Wish[heroRecord.WishHero]; ok {
if outTime > configure.Now().Unix() {
errdata = &pb.ErrorData{
Code: pb.ErrorCode_HeroDrawCD,
}
return
} else { // 时间到了
heroRecord.Wish[heroRecord.WishHero] = 0 // 时间清0
}
}
costRes = append(costRes, conf.Cond[heroRecord.WishHero].buyCos)
if errdata = this.module.CheckRes(session, costRes); errdata != nil {
return
}
} else { // 配置错误
errdata = &pb.ErrorData{
Code: pb.ErrorCode_ConfigNoFound,
Title: pb.ErrorCode_ConfigNoFound.ToString(),
Message: fmt.Sprintf("GetWishHeroReplaceConfig is nil"),
}
return
}
// 校验 解锁所需抽奖次数
if drcount > heroRecord.Race[comm.DrawCardType0] {
errdata = &pb.ErrorData{
Code: pb.ErrorCode_HeroDrawCountErr,
}
return
}
var hero *pb.DBHero
if hero, atno, errdata = this.module.CreateOneHero(session, heroRecord.WishHero); errdata == nil {
rsp.Data = append(rsp.Data, &pb.AtnoData{Atno: atno})
}
if errdata = this.module.ConsumeRes(session, costRes, true); errdata != nil {
return
}
// 修改recode 数据
if cd != 0 {
heroRecord.Wish[heroRecord.WishHero] = configure.Now().Unix() + cd
update["wish"] = heroRecord.Wish
this.module.modelRecord.ChangeHeroRecord(session.GetUserId(), update)
}
rsp.Record = heroRecord
session.SendMsg(string(this.module.GetType()), DrawCard, rsp)
go this.module.AsynHandleSession(session.Clone(), func(session comm.IUserSession) {
if user, err := this.module.GetUserForSession(session); err == nil { // 广播 首次获得英雄
for _, v := range atno {
if v.A == "hero" && v.T == heroRecord.WishHero && v.N == 1 {
if HeroConf, err := this.module.configure.GetHeroConfig(heroRecord.WishHero); err == nil {
this.chat.SendSysChatToWorld(session, comm.ChatSystem13, hero, HeroConf.Star, 0, user.Name, v.T)
} else {
this.module.Errorln(err)
}
}
}
} else {
this.module.Errorln(err)
}
this.module.WriteUserLog(session.GetUserId(), heroRecord.WishHero, comm.GMResAddType, "HeroDrawCardReq", atno)
this.module.WriteUserLog(session.GetUserId(), heroRecord.WishHero, comm.GMResDelType, "HeroDrawCardReq", costRes)
})
return
}