106 lines
2.8 KiB
Go
106 lines
2.8 KiB
Go
package gameserver
|
|||
|
|
|
||
|
|
import (
|
||
|
|
"crypto/rand"
|
||
|
|
"fmt"
|
||
|
|
"gac-hkrpg-go/internal/common"
|
||
|
|
pb "gac-hkrpg-go/protocol/proto"
|
||
|
|
"math/big"
|
||
|
|
)
|
||
|
|
|
||
|
|
// Aligns an imported encounter template with this run's selected camp pool.
|
||
|
|
// The resource explicitly identifies this server's compatibility sampling
|
||
|
|
// policy; original-server generation weights are not claimed. Preserve wave
|
||
|
|
// count, stars, encounter IDs, difficulty, penalties and displayed rewards.
|
||
|
|
func cwAlignEncounterCamp(catalog *common.CurrencyWarsCatalog, run *pb.MPIMAEMCEFH) (bool, error) {
|
||
|
|
if run.GetFMIGOKIDKJL().GetBAKAKODKECM() == nil {
|
||
|
|
return false, nil
|
||
|
|
}
|
||
|
|
stage, _ := cwStage(run)
|
||
|
|
if stage == nil {
|
||
|
|
return false, fmt.Errorf("CW Encounter stage missing")
|
||
|
|
}
|
||
|
|
layer := stage.GetIMPNAHBCADN().GetMPOBBIPMNNJ()
|
||
|
|
if layer == nil || len(layer.BPDABHGFBFO) < 2 {
|
||
|
|
return false, fmt.Errorf("CW Encounter offer layer missing")
|
||
|
|
}
|
||
|
|
for _, camp := range stage.HEKMEJLMGFF {
|
||
|
|
if camp.LOGHLGKIFEN == layer.LNDKCPBJDKH {
|
||
|
|
return false, nil
|
||
|
|
}
|
||
|
|
}
|
||
|
|
rows, err := common.LoadCurrencyWarsMonsters(catalog)
|
||
|
|
if err != nil {
|
||
|
|
return false, err
|
||
|
|
}
|
||
|
|
required := map[uint32]bool{}
|
||
|
|
for _, plan := range layer.BPDABHGFBFO {
|
||
|
|
for _, wave := range plan.MonsterWaveList {
|
||
|
|
for _, monster := range wave.PBLBBDBDLEK {
|
||
|
|
row, ok := rows[monster.MonsterId]
|
||
|
|
if !ok {
|
||
|
|
return false, fmt.Errorf("CW template monster %d missing native tier", monster.MonsterId)
|
||
|
|
}
|
||
|
|
required[row.Tier] = true
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
type candidate struct {
|
||
|
|
id uint32
|
||
|
|
pools map[uint32][]uint32
|
||
|
|
}
|
||
|
|
var candidates []candidate
|
||
|
|
for _, camp := range stage.HEKMEJLMGFF {
|
||
|
|
data, e := catalog.MonsterCamp(run.LJNGPCKPJLF, camp.LOGHLGKIFEN)
|
||
|
|
if e != nil {
|
||
|
|
return false, e
|
||
|
|
}
|
||
|
|
pools := map[uint32][]uint32{}
|
||
|
|
complete := true
|
||
|
|
for _, id := range data.Season.MonsterList {
|
||
|
|
row, ok := rows[id]
|
||
|
|
if !ok {
|
||
|
|
complete = false
|
||
|
|
break
|
||
|
|
}
|
||
|
|
pools[row.Tier] = append(pools[row.Tier], id)
|
||
|
|
}
|
||
|
|
for tier := range required {
|
||
|
|
if len(pools[tier]) == 0 {
|
||
|
|
complete = false
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if complete {
|
||
|
|
candidates = append(candidates, candidate{camp.LOGHLGKIFEN, pools})
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if len(candidates) == 0 {
|
||
|
|
return false, fmt.Errorf("CW no captured active camp supports Encounter tiers")
|
||
|
|
}
|
||
|
|
choose := func(n int) (int, error) {
|
||
|
|
v, e := rand.Int(rand.Reader, big.NewInt(int64(n)))
|
||
|
|
if e != nil {
|
||
|
|
return 0, e
|
||
|
|
}
|
||
|
|
return int(v.Int64()), nil
|
||
|
|
}
|
||
|
|
index, err := choose(len(candidates))
|
||
|
|
if err != nil {
|
||
|
|
return false, err
|
||
|
|
}
|
||
|
|
selected := candidates[index]
|
||
|
|
for _, plan := range layer.BPDABHGFBFO {
|
||
|
|
for _, wave := range plan.MonsterWaveList {
|
||
|
|
for _, monster := range wave.PBLBBDBDLEK {
|
||
|
|
pool := selected.pools[rows[monster.MonsterId].Tier]
|
||
|
|
i, e := choose(len(pool))
|
||
|
|
if e != nil {
|
||
|
|
return false, e
|
||
|
|
}
|
||
|
|
monster.MonsterId = pool[i]
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
layer.LNDKCPBJDKH = selected.id
|
||
|
|
return true, nil
|
||
|
|
}
|