Files
GaCy-GO/internal/gameserver/limited_gacha.go
T

99 lines
2.9 KiB
Go
Raw Normal View History

2026-10-28 18:54:43 +07:00
package gameserver
import (
"fmt"
"gac-hkrpg-go/internal/common"
pb "gac-hkrpg-go/protocol/proto"
)
func drawLimitedAvatar(s *Session, req *pb.DoGachaCsReq, rsp *pb.DoGachaScRsp, banner common.LimitedGachaBanner) error {
rsp.Retcode = uint32(pb.Retcode_RET_GACHA_NOT_SUPPORT)
if _, active := CURRENT_BATTLE.Load(s.Token); active {
return nil
}
player := s.JSON()
if player == nil {
return nil
}
_, policy, err := common.LoadBrowsableGachaBanners()
if err != nil {
return err
}
allowed := false
for _, n := range policy.DrawCounts {
allowed = allowed || n == req.GachaNum
}
if !allowed {
rsp.Retcode = uint32(pb.Retcode_RET_GACHA_NUM_INVALID)
return nil
}
resources, err := loadEidolonResources()
if err != nil {
return err
}
costs := map[uint32]map[uint32]uint32{}
for _, id := range append([]uint32{banner.AvatarID}, banner.FourStarIDs...) {
avatar, ok := resources.Avatars[id]
if !ok {
return fmt.Errorf("missing limited avatar Eidolon resource %d", id)
}
first := map[uint32]uint32{}
for _, rank := range avatar.Ranks {
if rank.Rank != 1 {
continue
}
for _, cost := range rank.Cost {
next := uint64(first[cost.ItemID]) + uint64(cost.ItemNum)
if cost.ItemID == 0 || cost.ItemNum == 0 || next > uint64(^uint32(0)) {
return fmt.Errorf("invalid limited duplicate cost")
}
first[cost.ItemID] = uint32(next)
}
}
if len(first) == 0 {
return fmt.Errorf("missing first-rank duplicate cost %d", id)
}
costs[id] = first
}
bag, err := bagMaterials(player)
if err != nil {
return err
}
baseline := map[uint32]uint32{}
for _, item := range bag {
baseline[item.Tid] = item.Num
}
result, err := common.DrawLimitedGacha(req.GachaId, req.GachaNum, costs, baseline)
if err != nil {
PacketLog("LIMITED_GACHA rejected: " + err.Error())
return nil
}
if player.Materials == nil {
player.Materials = map[uint32]uint32{}
}
sync := &pb.PlayerSyncScNotify{}
for id, count := range result.Materials {
player.Materials[id] = count
sync.MaterialList = append(sync.MaterialList, &pb.Material{Tid: id, Num: count})
}
for _, reward := range result.Rewards {
item := &pb.Item{ItemId: reward.ItemID, Num: 1}
if reward.Lightcone != nil {
player.Lightcones = append(player.Lightcones, *reward.Lightcone)
sync.EquipmentList = append(sync.EquipmentList, reward.Lightcone.ToProtoEquipment())
item.UniqueId = reward.Lightcone.UniqueID()
}
transfer := &pb.ItemList{}
for id, count := range reward.Materials {
transfer.ItemList = append(transfer.ItemList, &pb.Item{ItemId: id, Num: count})
}
rsp.GachaItemList = append(rsp.GachaItemList, &pb.GachaItem{GachaItem: item, TokenItem: &pb.ItemList{}, TransferItemList: transfer})
}
if err = s.Send(sync); err != nil {
return err
}
rsp.Retcode = 0
rsp.GachaNum = req.GachaNum
PacketLog(fmt.Sprintf("LIMITED_GACHA banner=%d draws=%d pity5=%d pity4=%d", req.GachaId, req.GachaNum, result.Pity.SinceFiveStar, result.Pity.SinceFourStar))
return nil
}