Update GaCy-GO
This commit is contained in:
1 parent
da8a32f60d
commit
0cbe460e49
345 files changed
+98202
-77559
No files matched your search
@@ -0,0 +1,146 @@
|
||||
package gameserver
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"fmt"
|
||||
"gac-hkrpg-go/internal/common"
|
||||
pb "gac-hkrpg-go/protocol/proto"
|
||||
"math/big"
|
||||
"slices"
|
||||
"sort"
|
||||
)
|
||||
|
||||
// Current Client GridFightForgeFuncType metadata: Equip = 1.
|
||||
const cwForgeEquipment uint32 = 1
|
||||
|
||||
func cwFreeBenchPosition(c *common.CurrencyWarsCatalog, run *pb.MPIMAEMCEFH) (uint32, error) {
|
||||
player, team, _ := cwComponents(run)
|
||||
if player == nil || team == nil {
|
||||
return 0, fmt.Errorf("CW team missing")
|
||||
}
|
||||
front, err := c.IntegerRule("GridFight_Front_AvatarMaxNum")
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
back, err := c.IntegerRule("GridFight_Back_AvatarMaxNum")
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
used := map[uint32]bool{}
|
||||
for _, r := range team.GridGameRoleList {
|
||||
used[r.Pos] = true
|
||||
}
|
||||
for _, r := range team.KCOMPKMJCMC {
|
||||
used[r.Pos] = true
|
||||
}
|
||||
for _, r := range team.PMEOPPDAMLM {
|
||||
used[r.Pos] = true
|
||||
}
|
||||
for p := uint64(front) + uint64(back) + 1; p <= uint64(front)+uint64(back)+uint64(player.MICEOJBAKGN) && p <= uint64(^uint32(0)); p++ {
|
||||
if !used[uint32(p)] {
|
||||
return uint32(p), nil
|
||||
}
|
||||
}
|
||||
return 0, fmt.Errorf("CW bench full")
|
||||
}
|
||||
|
||||
// GM offers use a uniform draw without replacement from captured equipment of
|
||||
// the configured category, matching the reference RollForgeEquipment policy.
|
||||
// This does not claim original server weights or implement Role/Expert actions.
|
||||
func cwGrantForge(c *common.CurrencyWarsCatalog, run *pb.MPIMAEMCEFH, id uint32) (*pb.KFNCAIHIHCM, error) {
|
||||
rewards, err := common.LoadCurrencyWarsRewards(c)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
row, ok := rewards.Forges[id]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("forge %d not captured", id)
|
||||
}
|
||||
if row.FuncType != cwForgeEquipment || len(row.ParamList) == 0 {
|
||||
return nil, fmt.Errorf("forge function %d needs its Role/Expert pending action", row.FuncType)
|
||||
}
|
||||
gear, err := common.LoadCurrencyWarsEquipment(c)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var pool []uint32
|
||||
for id, e := range gear {
|
||||
if e.EquipCategory == row.ParamList[0] {
|
||||
pool = append(pool, id)
|
||||
}
|
||||
}
|
||||
sort.Slice(pool, func(i, j int) bool { return pool[i] < pool[j] })
|
||||
if uint64(len(pool)) < uint64(row.EquipNum) {
|
||||
return nil, fmt.Errorf("forge equipment category capture incomplete")
|
||||
}
|
||||
pos, err := cwFreeBenchPosition(c, run)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
uid, err := cwNextEntityID(run)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
forge := &pb.DDAMEHEPOBD{UniqueId: uid, Pos: pos, LCLPEJHEAID: id}
|
||||
for i := uint32(0); i < row.EquipNum; i++ {
|
||||
n, e := rand.Int(rand.Reader, big.NewInt(int64(len(pool))-int64(i)))
|
||||
if e != nil {
|
||||
return nil, e
|
||||
}
|
||||
j := int(i) + int(n.Int64())
|
||||
pool[i], pool[j] = pool[j], pool[i]
|
||||
forge.CKJAKKNOHEK = append(forge.CKJAKKNOHEK, &pb.MBPDIPLJMKN{OFJBCEDFLKL: &pb.MBPDIPLJMKN_GGMPEGMEHPD{GGMPEGMEHPD: &pb.ELGLKEAPLGM{GridFightEquipmentId: pool[i]}}})
|
||||
}
|
||||
_, team, _ := cwComponents(run)
|
||||
team.PMEOPPDAMLM = append(team.PMEOPPDAMLM, forge)
|
||||
// Current _ProcessUpdateInfo: tag 1821 -> Team.AddForge; 1257 -> UpdateForge.
|
||||
return &pb.KFNCAIHIHCM{MNLCHEJKDHO: &pb.KFNCAIHIHCM_OLCKALFILKK{OLCKALFILKK: forge}}, nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
cwHandle("GridFightUseForge", func(s *Session, req *pb.GridFightUseForgeCsReq, rsp *pb.GridFightUseForgeScRsp) error {
|
||||
rsp.Retcode = uint32(pb.Retcode_RET_GRID_FIGHT_PARAM_NOT_MATCH)
|
||||
c, data, err := cwPreparingData(s)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
run := data.DHFOFLFCLAH
|
||||
_, team, _ := cwComponents(run)
|
||||
if team == nil {
|
||||
return nil
|
||||
}
|
||||
index := slices.IndexFunc(team.PMEOPPDAMLM, func(x *pb.DDAMEHEPOBD) bool { return x.UniqueId == req.UniqueId })
|
||||
if index < 0 {
|
||||
return nil
|
||||
}
|
||||
forge := team.PMEOPPDAMLM[index]
|
||||
rewards, err := common.LoadCurrencyWarsRewards(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
row, ok := rewards.Forges[forge.LCLPEJHEAID]
|
||||
if !ok || row.FuncType != cwForgeEquipment || uint64(req.PFIKCNFBGHE) >= uint64(len(forge.CKJAKKNOHEK)) {
|
||||
return nil
|
||||
}
|
||||
// Zero-based choice index follows the reference UseForge contract. Current
|
||||
// request names remain obfuscated; record the index in the gameplay log.
|
||||
id := forge.CKJAKKNOHEK[req.PFIKCNFBGHE].GetGGMPEGMEHPD().GetGridFightEquipmentId()
|
||||
notify, err := cwApplyCommand(c, run, common.CurrencyWarsCommand{Field: "equip", Value: id, Quantity: 1})
|
||||
if err != nil {
|
||||
PacketLog("CW_FORGE_USE rejected: " + err.Error())
|
||||
return nil
|
||||
}
|
||||
team.PMEOPPDAMLM = slices.Delete(team.PMEOPPDAMLM, index, index+1)
|
||||
// tag 703 -> Team.RemoveForge(UInt32), verified through the current switch.
|
||||
notify.GCPNIHHBGGD[0].JKPJFKCBIEM = append([]*pb.KFNCAIHIHCM{{MNLCHEJKDHO: &pb.KFNCAIHIHCM_OACCGHIHLBA{OACCGHIHLBA: req.UniqueId}}}, notify.GCPNIHHBGGD[0].JKPJFKCBIEM...)
|
||||
if err = s.saveCurrencyWarsData(data, c); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = cwSend(s, notify); err != nil {
|
||||
return err
|
||||
}
|
||||
rsp.Retcode = 0
|
||||
PacketLog(fmt.Sprintf("CW_FORGE_USE saved uid=%d index=%d equipment=%d revision=%d", req.UniqueId, req.PFIKCNFBGHE, id, s.currencyWarsRevision))
|
||||
return nil
|
||||
})
|
||||
}
|
||||
Reference in new issue
Block a user