feat(currency_wars): complete systems, settlement Rank SS, damage report, camera and recovery fixes

This commit is contained in:
CAtlas0784 committed 2026-10-31 20:47:36 +07:00
1 parent c008243f11
commit 0995055296
78 files changed
+33840 -9525

No files matched your search

+112 -7
View File
@@ -1,15 +1,19 @@
package gameserver
import (
"crypto/rand"
"fmt"
"maps"
"math/big"
"sort"
"gac-hkrpg-go/internal/common"
pb "gac-hkrpg-go/protocol/proto"
"maps"
)
// Grant transactions operate on the detached Preparation snapshot, then the
// caller saves before sending the same acquisition updates used by Supply/shop.
func cwApplyCommand(c *common.CurrencyWarsCatalog, run *pb.MPIMAEMCEFH, cmd common.CurrencyWarsCommand) (*pb.GridFightSyncUpdateResultScNotify, error) {
func cwApplyCommand(c *common.CurrencyWarsCatalog, run *pb.MPIMAEMCEFH, cmd common.CurrencyWarsCommand, rt ...*common.CurrencyWarsRuntimeState) (*pb.GridFightSyncUpdateResultScNotify, error) {
player, team, shop := cwComponents(run)
if player == nil {
return nil, fmt.Errorf("CW player missing")
@@ -18,6 +22,75 @@ func cwApplyCommand(c *common.CurrencyWarsCatalog, run *pb.MPIMAEMCEFH, cmd comm
case "gold":
player.Gold = cmd.Value
return cwNotify(cwGoldSync(player.Gold)), nil
case "tbpower", "tb", "trailblaze":
tbCat, err := common.LoadCurrencyWarsTrailblaze()
if err != nil {
return nil, err
}
var runtime *common.CurrencyWarsRuntimeState
if len(rt) > 0 && rt[0] != nil {
runtime = rt[0]
} else {
runtime, _ = cwBonfireRuntime(c, run)
}
if runtime == nil {
runtime = &common.CurrencyWarsRuntimeState{RunID: run.UniqueId}
}
if runtime.Rules == nil {
runtime.Rules = make(map[string]uint32)
}
layer := cwGetTrailblazeLayer(c, run)
tier := tbCat.Tier(layer)
if runtime.Rules["TbOpened"] == 0 {
runtime.Rules["TbOpened"] = 1
stage, _ := cwStage(run)
if stage != nil {
runtime.Rules["TbNode"] = stage.DCAHJELNJNP*1000 + stage.SectionId
}
cwTrailblazeRoll(tbCat, run, runtime, tier)
if tbBoughtCount(runtime, tbCat.InitialGoodID) == 0 {
runtime.Rules["TbGood/0"] = tbCat.InitialGoodID
}
}
runtime.Rules["TbPower"] = cmd.Value
if cmd.Star > 0 {
runtime.Rules["TbCosted"] = cmd.Star - 1
if runtime.Rules["TbCosted"] >= tbCat.PomThreshold && !tbOffered(runtime, tbCat.PomGoodID) {
slotToPut := 0
for s := 0; s < cwTrailblazeSlots; s++ {
if runtime.Rules[fmt.Sprintf("TbGood/%d", s)] == 0 {
slotToPut = s
break
}
}
runtime.Rules[fmt.Sprintf("TbGood/%d", slotToPut)] = tbCat.PomGoodID
}
}
cwSyncTraitComponent(c, run, runtime)
bundle := &pb.ABPLALCHNFA{
GridUpdateSrc: pb.JJDFGMMMCMI_JJDFGMMMCMI_GLKAGBGLENM,
OOEOCGLLHFO: []uint32{cwTrailblazeTrait, cwTrailblazeEffect},
JKPJFKCBIEM: []*pb.KFNCAIHIHCM{
{
MNLCHEJKDHO: &pb.KFNCAIHIHCM_HKHJJCMKKJE{
HKHJJCMKKJE: &pb.JLKCBOIFJKC{
TraitId: cwTrailblazeTrait,
ENPLACDLJGA: cwTrailblazeTraitEffectProto(tbCat, runtime),
},
},
},
{
MNLCHEJKDHO: &pb.KFNCAIHIHCM_GOOCHGKBIPN{
GOOCHGKBIPN: cwTrailblazeModifierProto(tbCat, runtime),
},
},
},
}
return &pb.GridFightSyncUpdateResultScNotify{
GCPNIHHBGGD: []*pb.ABPLALCHNFA{bundle},
}, nil
case "hp":
if cmd.Value == 0 || cmd.Value > player.PPKKHHNEOHB {
return nil, fmt.Errorf("HP must be 1..%d", player.PPKKHHNEOHB)
@@ -68,8 +141,27 @@ func cwApplyCommand(c *common.CurrencyWarsCatalog, run *pb.MPIMAEMCEFH, cmd comm
if err != nil {
return nil, err
}
if _, ok := rewards.Orbs[cmd.Value]; !ok {
return nil, fmt.Errorf("Orb %d not captured", cmd.Value)
var pool []uint32
if cmd.Value == 0 {
recipes, err := common.LoadCurrencyWarsOrbRecipes()
if err != nil {
return nil, err
}
for _, r := range recipes.Recipes {
if r.Status == "Implemented" && r.Engine == "Orb" {
if _, ok := rewards.Orbs[r.ID]; ok {
pool = append(pool, r.ID)
}
}
}
if len(pool) == 0 {
return nil, fmt.Errorf("no implemented CW orbs found")
}
sort.Slice(pool, func(i, j int) bool { return pool[i] < pool[j] })
} else {
if _, ok := rewards.Orbs[cmd.Value]; !ok {
return nil, fmt.Errorf("Orb %d not captured", cmd.Value)
}
}
var orbs *pb.DBONCGFHHDN
for _, component := range run.NAGDJGMMCBE {
@@ -78,7 +170,12 @@ func cwApplyCommand(c *common.CurrencyWarsCatalog, run *pb.MPIMAEMCEFH, cmd comm
}
}
if orbs == nil {
return nil, fmt.Errorf("CW Orb component missing")
orbs = &pb.DBONCGFHHDN{}
run.NAGDJGMMCBE = append(run.NAGDJGMMCBE, &pb.GridFightGameInfo{
LEOIAOFBBFA: &pb.GridFightGameInfo_DBAGKJNPDOL{
DBAGKJNPDOL: orbs,
},
})
}
quantity := cmd.Quantity
if quantity == 0 {
@@ -86,12 +183,20 @@ func cwApplyCommand(c *common.CurrencyWarsCatalog, run *pb.MPIMAEMCEFH, cmd comm
}
notify := cwNotify()
for i := uint32(0); i < quantity; i++ {
orbID := cmd.Value
if orbID == 0 {
idx, err := rand.Int(rand.Reader, big.NewInt(int64(len(pool))))
if err != nil {
return nil, err
}
orbID = pool[idx.Int64()]
}
uid, e := cwNextEntityID(run)
if e != nil {
return nil, e
}
orbs.MDKGCIKOMLI = append(orbs.MDKGCIKOMLI, &pb.IBPDPCOGDEP{UniqueId: uid, LDBNOMPCOKK: cmd.Value})
notify.GCPNIHHBGGD[0].JKPJFKCBIEM = append(notify.GCPNIHHBGGD[0].JKPJFKCBIEM, &pb.KFNCAIHIHCM{MNLCHEJKDHO: &pb.KFNCAIHIHCM_AFILIPBHMOO{AFILIPBHMOO: &pb.MMEDLCAENAL{UniqueId: uid, LDBNOMPCOKK: cmd.Value}}})
orbs.MDKGCIKOMLI = append(orbs.MDKGCIKOMLI, &pb.IBPDPCOGDEP{UniqueId: uid, LDBNOMPCOKK: orbID})
notify.GCPNIHHBGGD[0].JKPJFKCBIEM = append(notify.GCPNIHHBGGD[0].JKPJFKCBIEM, &pb.KFNCAIHIHCM{MNLCHEJKDHO: &pb.KFNCAIHIHCM_AFILIPBHMOO{AFILIPBHMOO: &pb.MMEDLCAENAL{UniqueId: uid, LDBNOMPCOKK: orbID}}})
}
return notify, nil
case "consumable":