package gameserver import ( "fmt" "slices" "sort" "gac-hkrpg-go/internal/common" pb "gac-hkrpg-go/protocol/proto" ) const benchFirstPos uint32 = 14 func cwCalculateBoardTraits(catalog *common.CurrencyWarsCatalog, run *pb.MPIMAEMCEFH) []*pb.FBNGHMHHHLL { if catalog == nil || run == nil { return nil } traitsCatalog, err := common.LoadCurrencyWarsTraits(catalog) if err != nil { return nil } _, team, _ := cwComponents(run) if team == nil { return nil } tallies := make(map[uint32]uint32) members := make(map[uint32][]uint32) for _, role := range team.GridGameRoleList { if role == nil || role.Pos >= benchFirstPos { continue } variant, err := catalog.CapturedRoleVariant(role.Id, role.RoleStar) if err == nil { for _, tid := range variant.Config.TraitList { tallies[tid]++ if !slices.Contains(members[tid], role.UniqueId) { members[tid] = append(members[tid], role.UniqueId) } } } } bag := cwEquipmentBag(run) if bag != nil && len(bag.GridFightEquipmentList) > 0 { equipMap, _ := common.LoadCurrencyWarsEquipment(catalog) if equipMap != nil { for _, role := range team.GridGameRoleList { if role == nil || role.Pos >= benchFirstPos { continue } for _, uid := range role.PNJIPHJJONG { for _, e := range bag.GridFightEquipmentList { if e != nil && e.UniqueId == uid { if info, ok := equipMap[e.GridFightEquipmentId]; ok { if (info.EquipFunc == 10 || info.EquipFunc == 11) && len(info.AbilityParamList) > 0 { var tid uint32 if _, scanErr := fmt.Sscanf(info.AbilityParamList[0], "%d", &tid); scanErr == nil && tid != 0 { tallies[tid]++ if !slices.Contains(members[tid], role.UniqueId) { members[tid] = append(members[tid], role.UniqueId) } } } } } } } } } } var tids []uint32 for tid := range tallies { tids = append(tids, tid) } sort.Slice(tids, func(i, j int) bool { return tids[i] < tids[j] }) var result []*pb.FBNGHMHHHLL for _, tid := range tids { count := tallies[tid] layer := traitsCatalog.ActiveLayer(tid, count) result = append(result, &pb.FBNGHMHHHLL{ TraitId: tid, KOJFHFAKKFO: layer, OLPPMEAMFFO: members[tid], }) } return result } // cwSyncTraitComponent updates the run's OAHOAPCIDMK component (GridFightGameInfo_OAHOAPCIDMK) // with the calculated board traits and attaches any active trait effects (such as the Trailblaze store). // It also keeps the run's CAAGABEPPPE modifier list in sync with active traits. func cwSyncTraitComponent(catalog *common.CurrencyWarsCatalog, run *pb.MPIMAEMCEFH, runtime *common.CurrencyWarsRuntimeState) { if catalog == nil || run == nil { return } tbCat, _ := common.LoadCurrencyWarsTrailblaze() tbActive := tbCat != nil && cwTrailblazeActive(catalog, run, runtime) if tbActive && runtime != nil { if runtime.Rules == nil { runtime.Rules = make(map[string]uint32) } if runtime.Rules["TbOpened"] == 0 { cwTrailblazeNodeEntered(catalog, run, runtime) } } traits := cwCalculateBoardTraits(catalog, run) if tbActive { var foundTb *pb.FBNGHMHHHLL for _, t := range traits { if t.TraitId == cwTrailblazeTrait { foundTb = t break } } if foundTb == nil { foundTb = &pb.FBNGHMHHHLL{ TraitId: cwTrailblazeTrait, KOJFHFAKKFO: 0, } traits = append(traits, foundTb) } foundTb.TraitEffectList = []*pb.MGBHKCMHDOK{ cwTrailblazeTraitEffectProto(tbCat, runtime), } } var traitComp *pb.FFOGFOBHDEK for _, c := range run.NAGDJGMMCBE { if c.GetOAHOAPCIDMK() != nil { traitComp = c.GetOAHOAPCIDMK() break } } if traitComp == nil { traitComp = &pb.FFOGFOBHDEK{} run.NAGDJGMMCBE = append(run.NAGDJGMMCBE, &pb.GridFightGameInfo{ LEOIAOFBBFA: &pb.GridFightGameInfo_OAHOAPCIDMK{ OAHOAPCIDMK: traitComp, }, }) } traitComp.GridFightTraitInfo = traits if tbCat != nil && tbActive { if run.CAAGABEPPPE == nil { run.CAAGABEPPPE = &pb.HKDACEAEDDE{} } modProto := cwTrailblazeModifierProto(tbCat, runtime) found := false for i, mod := range run.CAAGABEPPPE.KLCKAOJAMNH { if mod.UniqueId == cwTrailblazeModifierUID { run.CAAGABEPPPE.KLCKAOJAMNH[i] = modProto found = true break } } if !found { run.CAAGABEPPPE.KLCKAOJAMNH = append(run.CAAGABEPPPE.KLCKAOJAMNH, modProto) } } } func cwCalculateBattleTraits(catalog *common.CurrencyWarsCatalog, run *pb.MPIMAEMCEFH, runtime *common.CurrencyWarsRuntimeState) []*pb.NIEGDAPHKGC { if catalog == nil || run == nil { return nil } traitsCatalog, err := common.LoadCurrencyWarsTraits(catalog) if err != nil { return nil } _, team, _ := cwComponents(run) if team == nil { return nil } tallies := make(map[uint32]uint32) members := make(map[uint32][]*pb.MHFNFINKJKP) for _, role := range team.GridGameRoleList { if role == nil || role.Pos >= benchFirstPos { continue } variant, err := catalog.CapturedRoleVariant(role.Id, role.RoleStar) if err == nil { for _, tid := range variant.Config.TraitList { tallies[tid]++ members[tid] = append(members[tid], &pb.MHFNFINKJKP{ CHEEOEHDOBF: role.UniqueId, }) } } } bag := cwEquipmentBag(run) if bag != nil && len(bag.GridFightEquipmentList) > 0 { equipMap, _ := common.LoadCurrencyWarsEquipment(catalog) if equipMap != nil { for _, role := range team.GridGameRoleList { if role == nil || role.Pos >= benchFirstPos { continue } for _, uid := range role.PNJIPHJJONG { for _, e := range bag.GridFightEquipmentList { if e != nil && e.UniqueId == uid { if info, ok := equipMap[e.GridFightEquipmentId]; ok { if (info.EquipFunc == 10 || info.EquipFunc == 11) && len(info.AbilityParamList) > 0 { var tid uint32 if _, scanErr := fmt.Sscanf(info.AbilityParamList[0], "%d", &tid); scanErr == nil && tid != 0 { tallies[tid]++ } } } } } } } } } tbActive := cwTrailblazeActive(catalog, run, runtime) if tbActive { if _, ok := tallies[cwTrailblazeTrait]; !ok { tallies[cwTrailblazeTrait] = 0 } } var tids []uint32 for tid := range tallies { tids = append(tids, tid) } sort.Slice(tids, func(i, j int) bool { return tids[i] < tids[j] }) var result []*pb.NIEGDAPHKGC for _, tid := range tids { count := tallies[tid] layer := traitsCatalog.ActiveLayer(tid, count) traitProto := &pb.NIEGDAPHKGC{ TraitId: tid, KOJFHFAKKFO: layer, KOJMGCBLKKA: members[tid], } if tid == cwTrailblazeTrait { tbPower := uint32(0) if runtime != nil && runtime.Rules != nil { tbPower = runtime.Rules["TbPower"] } traitProto.TraitEffectList = append(traitProto.TraitEffectList, &pb.BattleGridFightTraitEffectInfo{ EffectId: cwTrailblazeEffect, NEBNJDMFELO: &pb.BattleGridFightTraitEffectInfo_KDBKIPPHMFI{ KDBKIPPHMFI: &pb.LFNNCOMFBMD{ MJIGJEGMCML: tbPower, }, }, }) } result = append(result, traitProto) } return result }