package gameserver import ( "gac-hkrpg-go/internal/common" goproto "gac-hkrpg-go/protocol/proto" "google.golang.org/protobuf/proto" ) // ChallengeTargetConfigRow.ChallengeTargetType, captured from this Client. const challengeTargetTotalScore uint32 = 7 func tierceTargets(id, total uint32) []uint32 { stage := getChallengeData().Tierce[id] ids := append([]uint32(nil), stage.Targets...) if stage.SpecialTarget != 0 { ids = append(ids, stage.SpecialTarget) } var finished []uint32 for _, targetID := range ids { r, ok := getChallengeData().TargetRules[targetID] if ok && r.Type == challengeTargetTotalScore && total >= r.Param { finished = append(finished, targetID) } } return finished } func tierceBestRecord(saved *common.TierceProgress) (uint32, bool) { var total uint32 allWon := true for node := uint32(0); node < tierceNodeCount; node++ { n, ok := saved.Nodes[node] total += n.Score if !ok || !n.Won { allWon = false } } return total, allWon } func tierceNodeResult(node uint32, n common.TierceNodeProgress, teams ...[]uint32) *goproto.PMMOFOBCINL { result := &goproto.PMMOFOBCINL{} if len(n.Result) > 0 && proto.Unmarshal(n.Result, result) == nil { return result } // Imported confirmed scores have no historical equipment snapshot. Supply // known team IDs and empty wrappers rather than inventing gear/stats. result.Lineup = &goproto.GLLFJFJBIBC{} if len(teams) > 0 { for slot, id := range teams[0] { result.Lineup.MNABNJOEHLF = append(result.Lineup.MNABNJOEHLF, &goproto.CLDOIEGCNLD{AvatarId: id, Slot: uint32(slot), AvatarType: uint32(goproto.AvatarType_AVATAR_FORMAL_TYPE), PAGPNOKLNOM: &goproto.ChallengeBossEquipmentInfo{}, OKCGHKDMFAM: &goproto.ChallengeBossAvatarRelicInfo{}}) } } result.FINOCEGDBDI = node result.ScoreId = n.Score if n.Won { result.EndStatus = goproto.BattleEndStatus_BATTLE_END_WIN } return result } func saveTierceResult(s *Session, result *goproto.PMMOFOBCINL) error { saved := s.JSON().TierceProgress[s.ChallengeRun.ID] if saved.Nodes == nil { saved.Nodes = map[uint32]common.TierceNodeProgress{} } node := result.FINOCEGDBDI old, known := saved.Nodes[node] won := result.EndStatus == goproto.BattleEndStatus_BATTLE_END_WIN if !known || result.ScoreId > old.Score || (result.ScoreId == old.Score && won && !old.Won) { raw, err := proto.Marshal(result) if err != nil { return err } saved.Nodes[node] = common.TierceNodeProgress{Score: result.ScoreId, Won: won, Result: raw} } return s.JSON().SavePersistentChecked() } func buildTierceGroup(id uint32, saved *common.TierceProgress) *goproto.ChallengeTierceGroup { group := &goproto.ChallengeTierceGroup{ChallengeId: id} if saved == nil { return group } total, allWon := tierceBestRecord(saved) group.Record = &goproto.ChallengeTierceRecord{TotalScore: total} group.IsWin = allWon if limit := getChallengeData().Tierce[id].ClearScore; limit != 0 && total < limit { group.IsWin = false } if allWon { group.FinishedTargetList = tierceTargets(id, total) } for node, team := range saved.Teams { lineup := &goproto.CMOPLAHDEPN{FINOCEGDBDI: uint32(node)} if node < len(saved.Buffs) { lineup.BuffId = saved.Buffs[node] } for _, aid := range team { lineup.TierceAvatarIdList = append(lineup.TierceAvatarIdList, &goproto.AvatarLineup{Id: aid, AvatarType: goproto.AvatarType_AVATAR_FORMAL_TYPE}) } group.MOGEEAJCFNO = append(group.MOGEEAJCFNO, lineup) } for node := uint32(0); node < tierceNodeCount; node++ { if n, ok := saved.Nodes[node]; ok { var team []uint32 if int(node) < len(saved.Teams) { team = saved.Teams[node] } group.HGKCEEOONGA = append(group.HGKCEEOONGA, tierceNodeResult(node, n, team)) } } return group }