477 lines
14 KiB
Go
477 lines
14 KiB
Go
package gameserver
|
|||
|
|
|
||
|
|
import (
|
||
|
|
"fmt"
|
||
|
|
"maps"
|
||
|
|
"math/rand/v2"
|
||
|
|
"strconv"
|
||
|
|
"strings"
|
||
|
|
|
||
|
|
"gac-hkrpg-go/internal/common"
|
||
|
|
pb "gac-hkrpg-go/protocol/proto"
|
||
|
|
)
|
||
|
|
|
||
|
|
const (
|
||
|
|
cwTrailblazeTrait uint32 = 100502
|
||
|
|
cwTrailblazeEffect uint32 = 1005021
|
||
|
|
cwTrailblazeModifierUID uint32 = 1005021
|
||
|
|
cwTrailblazeSlots int = 4
|
||
|
|
)
|
||
|
|
|
||
|
|
// cwGetTrailblazeLayer returns the active layer (2, 4, 6, 8, 10 or 0) of the Trailblaze Silver Rail trait.
|
||
|
|
func cwGetTrailblazeLayer(catalog *common.CurrencyWarsCatalog, run *pb.MPIMAEMCEFH) uint32 {
|
||
|
|
traits := cwCalculateBoardTraits(catalog, run)
|
||
|
|
for _, t := range traits {
|
||
|
|
if t.TraitId == cwTrailblazeTrait {
|
||
|
|
return t.KOJFHFAKKFO
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return 0
|
||
|
|
}
|
||
|
|
|
||
|
|
func cwTrailblazeActive(catalog *common.CurrencyWarsCatalog, run *pb.MPIMAEMCEFH, runtime *common.CurrencyWarsRuntimeState) bool {
|
||
|
|
if runtime != nil && (runtime.Rules["TbOpened"] != 0 || runtime.Rules["TbPower"] > 0) {
|
||
|
|
return true
|
||
|
|
}
|
||
|
|
return cwGetTrailblazeLayer(catalog, run) > 0
|
||
|
|
}
|
||
|
|
|
||
|
|
func tbOffered(runtime *common.CurrencyWarsRuntimeState, goodID uint32) bool {
|
||
|
|
if runtime == nil {
|
||
|
|
return false
|
||
|
|
}
|
||
|
|
for slot := 0; slot < cwTrailblazeSlots; slot++ {
|
||
|
|
if runtime.Rules[fmt.Sprintf("TbGood/%d", slot)] == goodID {
|
||
|
|
return true
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return false
|
||
|
|
}
|
||
|
|
|
||
|
|
func tbBoughtCount(runtime *common.CurrencyWarsRuntimeState, goodID uint32) uint32 {
|
||
|
|
if runtime == nil {
|
||
|
|
return 0
|
||
|
|
}
|
||
|
|
return runtime.Rules[fmt.Sprintf("TbBought/%d", goodID)]
|
||
|
|
}
|
||
|
|
|
||
|
|
func tbIsEligible(tbCat *common.CurrencyWarsTrailblazeCatalog, runtime *common.CurrencyWarsRuntimeState, row common.CurrencyWarsTrailblazeGood, tier uint32) bool {
|
||
|
|
if row.Kind == "refresh" || row.ID == tbCat.InitialGoodID {
|
||
|
|
return false
|
||
|
|
}
|
||
|
|
if row.ID/100 > tier+1 {
|
||
|
|
return false
|
||
|
|
}
|
||
|
|
if row.Father != 0 && tbBoughtCount(runtime, row.Father) == 0 {
|
||
|
|
return false
|
||
|
|
}
|
||
|
|
if row.Kind == "maze_buff" && tbBoughtCount(runtime, row.ID) != 0 {
|
||
|
|
return false
|
||
|
|
}
|
||
|
|
pomItem := row.Kind == "item" && len(row.Params) == 1 && (row.Params[0] == 353201 || row.Params[0] == 353202)
|
||
|
|
pomUnlocked := runtime != nil && runtime.Rules["TbCosted"] >= tbCat.PomThreshold
|
||
|
|
if (row.ID == tbCat.PomGoodID || pomItem) && !pomUnlocked {
|
||
|
|
return false
|
||
|
|
}
|
||
|
|
return !tbOffered(runtime, row.ID)
|
||
|
|
}
|
||
|
|
|
||
|
|
func cwTrailblazeRNG(run *pb.MPIMAEMCEFH, runtime *common.CurrencyWarsRuntimeState) *rand.Rand {
|
||
|
|
var runID uint64 = 1
|
||
|
|
var nodeKey uint64 = 0
|
||
|
|
if run != nil {
|
||
|
|
runID = uint64(run.UniqueId)
|
||
|
|
if stage, _ := cwStage(run); stage != nil {
|
||
|
|
nodeKey = uint64(stage.DCAHJELNJNP)*10000 + uint64(stage.SectionId)*100
|
||
|
|
}
|
||
|
|
}
|
||
|
|
var refresh uint64 = 0
|
||
|
|
if runtime != nil && runtime.Rules != nil {
|
||
|
|
refresh = uint64(runtime.Rules["TbRefreshCount"])
|
||
|
|
}
|
||
|
|
seed := runID*1000003 + nodeKey*31 + refresh*7 + 100502
|
||
|
|
return rand.New(rand.NewPCG(seed, seed^0x5DEECE66D))
|
||
|
|
}
|
||
|
|
|
||
|
|
func cwTrailblazeRoll(tbCat *common.CurrencyWarsTrailblazeCatalog, run *pb.MPIMAEMCEFH, runtime *common.CurrencyWarsRuntimeState, tier uint32) {
|
||
|
|
if runtime == nil || runtime.Rules == nil {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
rng := cwTrailblazeRNG(run, runtime)
|
||
|
|
for slot := 0; slot < cwTrailblazeSlots; slot++ {
|
||
|
|
runtime.Rules[fmt.Sprintf("TbGood/%d", slot)] = 0
|
||
|
|
var eligible []common.CurrencyWarsTrailblazeGood
|
||
|
|
for _, row := range tbCat.GoodsList {
|
||
|
|
if tbIsEligible(tbCat, runtime, row, tier) {
|
||
|
|
eligible = append(eligible, row)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if len(eligible) == 0 {
|
||
|
|
continue
|
||
|
|
}
|
||
|
|
pick := eligible[rng.IntN(len(eligible))]
|
||
|
|
runtime.Rules[fmt.Sprintf("TbGood/%d", slot)] = pick.ID
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func cwTrailblazeNodeEntered(catalog *common.CurrencyWarsCatalog, run *pb.MPIMAEMCEFH, runtime *common.CurrencyWarsRuntimeState) {
|
||
|
|
layer := cwGetTrailblazeLayer(catalog, run)
|
||
|
|
if layer == 0 {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
tbCat, err := common.LoadCurrencyWarsTrailblaze()
|
||
|
|
if err != nil {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
tier := tbCat.Tier(layer)
|
||
|
|
if runtime.Rules == nil {
|
||
|
|
runtime.Rules = make(map[string]uint32)
|
||
|
|
}
|
||
|
|
stage, _ := cwStage(run)
|
||
|
|
var currentNode uint32
|
||
|
|
if stage != nil {
|
||
|
|
currentNode = stage.DCAHJELNJNP*1000 + stage.SectionId
|
||
|
|
}
|
||
|
|
if runtime.Rules["TbOpened"] == 0 {
|
||
|
|
runtime.Rules["TbOpened"] = 1
|
||
|
|
runtime.Rules["TbNode"] = currentNode
|
||
|
|
runtime.Rules["TbRefreshCount"] = 0
|
||
|
|
cwTrailblazeRoll(tbCat, run, runtime, tier)
|
||
|
|
if tbBoughtCount(runtime, tbCat.InitialGoodID) == 0 {
|
||
|
|
runtime.Rules["TbGood/0"] = tbCat.InitialGoodID
|
||
|
|
}
|
||
|
|
} else if runtime.Rules["TbNode"] != currentNode {
|
||
|
|
runtime.Rules["TbNode"] = currentNode
|
||
|
|
runtime.Rules["TbRefreshCount"] = 0
|
||
|
|
cwTrailblazeRoll(tbCat, run, runtime, tier)
|
||
|
|
if tbBoughtCount(runtime, tbCat.InitialGoodID) == 0 {
|
||
|
|
runtime.Rules["TbGood/0"] = tbCat.InitialGoodID
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func cwTrailblazeShopProto(tbCat *common.CurrencyWarsTrailblazeCatalog, runtime *common.CurrencyWarsRuntimeState) *pb.GGFHGKGJOOB {
|
||
|
|
shop := &pb.GGFHGKGJOOB{
|
||
|
|
OBHKKOFDEFG: make(map[uint32]uint32),
|
||
|
|
}
|
||
|
|
if runtime != nil {
|
||
|
|
shop.MJIGJEGMCML = runtime.Rules["TbPower"]
|
||
|
|
for slot := 0; slot < cwTrailblazeSlots; slot++ {
|
||
|
|
gid := runtime.Rules[fmt.Sprintf("TbGood/%d", slot)]
|
||
|
|
if gid != 0 {
|
||
|
|
if good, ok := tbCat.Goods[gid]; ok {
|
||
|
|
shop.OGDKJPDFFAI = append(shop.OGDKJPDFFAI, &pb.AMNAMDLMADK{
|
||
|
|
GoodsId: gid,
|
||
|
|
OICGFNGNLOE: good.Cost,
|
||
|
|
})
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
for k, v := range runtime.Rules {
|
||
|
|
if strings.HasPrefix(k, "TbBought/") {
|
||
|
|
idStr := strings.TrimPrefix(k, "TbBought/")
|
||
|
|
if gid, err := strconv.ParseUint(idStr, 10, 32); err == nil && v > 0 {
|
||
|
|
shop.OBHKKOFDEFG[uint32(gid)] = v
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
shop.OGDKJPDFFAI = append(shop.OGDKJPDFFAI, &pb.AMNAMDLMADK{
|
||
|
|
GoodsId: tbCat.RefreshGoodID,
|
||
|
|
OICGFNGNLOE: 1,
|
||
|
|
})
|
||
|
|
return shop
|
||
|
|
}
|
||
|
|
|
||
|
|
func cwTrailblazeModifierProto(tbCat *common.CurrencyWarsTrailblazeCatalog, runtime *common.CurrencyWarsRuntimeState) *pb.NJKFOJJDGGG {
|
||
|
|
costed := uint32(0)
|
||
|
|
if runtime != nil {
|
||
|
|
costed = runtime.Rules["TbCosted"]
|
||
|
|
}
|
||
|
|
return &pb.NJKFOJJDGGG{
|
||
|
|
UniqueId: cwTrailblazeModifierUID,
|
||
|
|
FMEKLFFDPGG: &pb.NJKFOJJDGGG_ONKMJAGNECC{
|
||
|
|
ONKMJAGNECC: &pb.CONKAFGLHFE{
|
||
|
|
IANFMIJBKAF: costed,
|
||
|
|
PLAIPMBIHGJ: tbCat.PomThreshold,
|
||
|
|
},
|
||
|
|
},
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func cwTrailblazeTraitEffectProto(tbCat *common.CurrencyWarsTrailblazeCatalog, runtime *common.CurrencyWarsRuntimeState) *pb.MGBHKCMHDOK {
|
||
|
|
return &pb.MGBHKCMHDOK{
|
||
|
|
EffectId: cwTrailblazeEffect,
|
||
|
|
NEBNJDMFELO: &pb.MGBHKCMHDOK_KDBKIPPHMFI{
|
||
|
|
KDBKIPPHMFI: cwTrailblazeShopProto(tbCat, runtime),
|
||
|
|
},
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
type tbListedGood struct {
|
||
|
|
id uint32
|
||
|
|
cost uint32
|
||
|
|
slot int
|
||
|
|
}
|
||
|
|
|
||
|
|
func cwTrailblazeBuy(catalog *common.CurrencyWarsCatalog, run *pb.MPIMAEMCEFH, runtime *common.CurrencyWarsRuntimeState, index uint32) (*pb.GridFightSyncUpdateResultScNotify, error) {
|
||
|
|
if !cwTrailblazeActive(catalog, run, runtime) {
|
||
|
|
return nil, fmt.Errorf("Trailblaze Silver Rail trait is inactive")
|
||
|
|
}
|
||
|
|
layer := cwGetTrailblazeLayer(catalog, run)
|
||
|
|
tbCat, err := common.LoadCurrencyWarsTrailblaze()
|
||
|
|
if err != nil {
|
||
|
|
return nil, err
|
||
|
|
}
|
||
|
|
if runtime == nil || runtime.Rules == nil {
|
||
|
|
return nil, fmt.Errorf("runtime rules missing")
|
||
|
|
}
|
||
|
|
if runtime.Rules["TbOpened"] == 0 {
|
||
|
|
cwTrailblazeNodeEntered(catalog, run, runtime)
|
||
|
|
}
|
||
|
|
|
||
|
|
var listed []tbListedGood
|
||
|
|
for slot := 0; slot < cwTrailblazeSlots; slot++ {
|
||
|
|
gid := runtime.Rules[fmt.Sprintf("TbGood/%d", slot)]
|
||
|
|
if gid != 0 {
|
||
|
|
if good, ok := tbCat.Goods[gid]; ok {
|
||
|
|
listed = append(listed, tbListedGood{id: gid, cost: good.Cost, slot: slot})
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
listed = append(listed, tbListedGood{id: tbCat.RefreshGoodID, cost: 1, slot: -1})
|
||
|
|
|
||
|
|
if int(index) >= len(listed) {
|
||
|
|
return nil, fmt.Errorf("goods index %d out of bounds (listed len %d)", index, len(listed))
|
||
|
|
}
|
||
|
|
|
||
|
|
target := listed[index]
|
||
|
|
good, ok := tbCat.Goods[target.id]
|
||
|
|
if !ok {
|
||
|
|
return nil, fmt.Errorf("goods %d definition missing", target.id)
|
||
|
|
}
|
||
|
|
|
||
|
|
power := runtime.Rules["TbPower"]
|
||
|
|
if power < target.cost {
|
||
|
|
return nil, fmt.Errorf("insufficient Trailblaze Power: have %d need %d", power, target.cost)
|
||
|
|
}
|
||
|
|
|
||
|
|
player, team, _ := cwComponents(run)
|
||
|
|
bag := cwEquipmentBag(run)
|
||
|
|
if player == nil || team == nil || bag == nil {
|
||
|
|
return nil, fmt.Errorf("CW components missing")
|
||
|
|
}
|
||
|
|
|
||
|
|
var grantUpdates []*pb.KFNCAIHIHCM
|
||
|
|
|
||
|
|
switch good.Kind {
|
||
|
|
case "role":
|
||
|
|
if len(good.Params) < 1 {
|
||
|
|
return nil, fmt.Errorf("role goods %d has empty params", good.ID)
|
||
|
|
}
|
||
|
|
roleID := good.Params[0]
|
||
|
|
star := uint32(1)
|
||
|
|
if len(good.Params) >= 2 && good.Params[1] > 0 {
|
||
|
|
star = good.Params[1]
|
||
|
|
}
|
||
|
|
front, e := catalog.IntegerRule("GridFight_Front_AvatarMaxNum")
|
||
|
|
if e != nil {
|
||
|
|
return nil, e
|
||
|
|
}
|
||
|
|
back, e := catalog.IntegerRule("GridFight_Back_AvatarMaxNum")
|
||
|
|
if e != nil {
|
||
|
|
return nil, e
|
||
|
|
}
|
||
|
|
overflow, e := catalog.IntegerRule("GridFight_Bench_OverFlow_AvatarNum")
|
||
|
|
if e != nil {
|
||
|
|
return nil, e
|
||
|
|
}
|
||
|
|
occupied := map[uint32]bool{}
|
||
|
|
for _, r := range team.GridGameRoleList {
|
||
|
|
occupied[r.Pos] = true
|
||
|
|
}
|
||
|
|
var pos uint32
|
||
|
|
for p := uint64(front+back) + 1; p <= uint64(front+back)+uint64(player.MICEOJBAKGN)+uint64(overflow); p++ {
|
||
|
|
if !occupied[uint32(p)] {
|
||
|
|
pos = uint32(p)
|
||
|
|
break
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if pos == 0 {
|
||
|
|
return nil, fmt.Errorf("bench is full")
|
||
|
|
}
|
||
|
|
uid, e := cwNextEntityID(run)
|
||
|
|
if e != nil {
|
||
|
|
return nil, e
|
||
|
|
}
|
||
|
|
var scales map[uint32]uint32
|
||
|
|
if len(team.GridGameRoleList) > 0 {
|
||
|
|
scales = maps.Clone(team.GridGameRoleList[0].ConvertPropertyToFixpoint)
|
||
|
|
}
|
||
|
|
newRole := &pb.CDEAABODKCP{
|
||
|
|
Id: roleID,
|
||
|
|
RoleStar: star,
|
||
|
|
UniqueId: uid,
|
||
|
|
Pos: pos,
|
||
|
|
ConvertPropertyToFixpoint: scales,
|
||
|
|
}
|
||
|
|
team.GridGameRoleList = append(team.GridGameRoleList, newRole)
|
||
|
|
grantUpdates = append(grantUpdates, &pb.KFNCAIHIHCM{
|
||
|
|
MNLCHEJKDHO: &pb.KFNCAIHIHCM_PIDDDHKPDDM{PIDDDHKPDDM: newRole},
|
||
|
|
})
|
||
|
|
merged, e := cwMergeRoles(catalog, run, uid)
|
||
|
|
if e == nil && len(merged) > 0 {
|
||
|
|
for _, m := range merged {
|
||
|
|
grantUpdates = append(grantUpdates, m.JKPJFKCBIEM...)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
case "item":
|
||
|
|
if len(good.Params) < 1 {
|
||
|
|
return nil, fmt.Errorf("item goods %d has empty params", good.ID)
|
||
|
|
}
|
||
|
|
itemID := good.Params[0]
|
||
|
|
rewards, _ := common.LoadCurrencyWarsRewards(catalog)
|
||
|
|
isConsumable := false
|
||
|
|
if rewards != nil {
|
||
|
|
_, isConsumable = rewards.Consumables[itemID]
|
||
|
|
}
|
||
|
|
if isConsumable {
|
||
|
|
result, err := cwApplyCommand(catalog, run, common.CurrencyWarsCommand{Field: "consumable", Value: itemID, Quantity: 1}, runtime)
|
||
|
|
if err != nil {
|
||
|
|
return nil, err
|
||
|
|
}
|
||
|
|
for _, g := range result.GCPNIHHBGGD {
|
||
|
|
grantUpdates = append(grantUpdates, g.JKPJFKCBIEM...)
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
result, err := cwApplyCommand(catalog, run, common.CurrencyWarsCommand{Field: "equip", Value: itemID, Quantity: 1}, runtime)
|
||
|
|
if err != nil {
|
||
|
|
return nil, err
|
||
|
|
}
|
||
|
|
for _, g := range result.GCPNIHHBGGD {
|
||
|
|
grantUpdates = append(grantUpdates, g.JKPJFKCBIEM...)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
case "power":
|
||
|
|
if len(good.Params) >= 1 {
|
||
|
|
runtime.Rules["TbPower"] += good.Params[0]
|
||
|
|
}
|
||
|
|
|
||
|
|
case "maze_buff":
|
||
|
|
if tbBoughtCount(runtime, target.id) > 0 {
|
||
|
|
return nil, fmt.Errorf("buff %d is already purchased", target.id)
|
||
|
|
}
|
||
|
|
case "stat":
|
||
|
|
// Handled via recorded bought count
|
||
|
|
}
|
||
|
|
|
||
|
|
wasUnlocked := runtime.Rules["TbCosted"] >= tbCat.PomThreshold
|
||
|
|
runtime.Rules["TbPower"] -= target.cost
|
||
|
|
runtime.Rules["TbCosted"] += target.cost
|
||
|
|
|
||
|
|
if target.id == tbCat.RefreshGoodID {
|
||
|
|
runtime.Rules["TbRefreshCount"]++
|
||
|
|
cwTrailblazeRoll(tbCat, run, runtime, tbCat.Tier(layer))
|
||
|
|
if tbBoughtCount(runtime, tbCat.InitialGoodID) == 0 {
|
||
|
|
runtime.Rules["TbGood/0"] = tbCat.InitialGoodID
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
runtime.Rules[fmt.Sprintf("TbBought/%d", target.id)]++
|
||
|
|
if target.slot >= 0 && target.slot < cwTrailblazeSlots {
|
||
|
|
runtime.Rules[fmt.Sprintf("TbGood/%d", target.slot)] = 0
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if !wasUnlocked && runtime.Rules["TbCosted"] >= tbCat.PomThreshold {
|
||
|
|
slotToPut := target.slot
|
||
|
|
if slotToPut < 0 || slotToPut >= cwTrailblazeSlots || runtime.Rules[fmt.Sprintf("TbGood/%d", slotToPut)] != 0 {
|
||
|
|
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(catalog, 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),
|
||
|
|
},
|
||
|
|
},
|
||
|
|
},
|
||
|
|
}
|
||
|
|
bundle.JKPJFKCBIEM = append(bundle.JKPJFKCBIEM, grantUpdates...)
|
||
|
|
|
||
|
|
return &pb.GridFightSyncUpdateResultScNotify{
|
||
|
|
GCPNIHHBGGD: []*pb.ABPLALCHNFA{bundle},
|
||
|
|
}, nil
|
||
|
|
}
|
||
|
|
|
||
|
|
func init() {
|
||
|
|
cwHandle("GridFightTraitUpdate", func(s *Session, req *pb.GridFightTraitUpdateCsReq, rsp *pb.GridFightTraitUpdateScRsp) error {
|
||
|
|
rsp.Retcode = uint32(pb.Retcode_RET_GRID_FIGHT_PARAM_NOT_MATCH)
|
||
|
|
if req == nil {
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
catalog, err := common.LoadCurrencyWarsCatalog()
|
||
|
|
if err != nil {
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
data, revision, err := readCurrencyWarsData(catalog)
|
||
|
|
if err != nil {
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
if data == nil || data.DHFOFLFCLAH == nil {
|
||
|
|
rsp.Retcode = uint32(pb.Retcode_RET_GRID_FIGHT_NOT_IN_GAMEPLAY)
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
s.currencyWarsRevision = revision
|
||
|
|
|
||
|
|
run := data.DHFOFLFCLAH
|
||
|
|
runtime, err := cwBonfireRuntime(catalog, run)
|
||
|
|
if err != nil {
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
|
||
|
|
if req.GetTraitId() == cwTrailblazeTrait && req.GetEffectId() == cwTrailblazeEffect && req.GetKDBKIPPHMFI() != nil {
|
||
|
|
notify, buyErr := cwTrailblazeBuy(catalog, run, runtime, req.GetKDBKIPPHMFI().Pos)
|
||
|
|
if buyErr != nil {
|
||
|
|
PacketLog(fmt.Sprintf("CW_TRAIT_UPDATE Trailblaze rejected: %v", buyErr))
|
||
|
|
rsp.Retcode = uint32(pb.Retcode_RET_GRID_FIGHT_PARAM_NOT_MATCH)
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
if err = s.saveCurrencyWarsDataWithRuntime(data, catalog, runtime); err != nil {
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
if err = s.Send(notify); err != nil {
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
rsp.Retcode = 0
|
||
|
|
PacketLog(fmt.Sprintf("CW_TRAIT_UPDATE Trailblaze bought pos=%d power=%d costed=%d", req.GetKDBKIPPHMFI().Pos, runtime.Rules["TbPower"], runtime.Rules["TbCosted"]))
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
|
||
|
|
rsp.Retcode = 0
|
||
|
|
PacketLog(fmt.Sprintf("CW_TRAIT_UPDATE trait=%d effect=%d", req.GetTraitId(), req.GetEffectId()))
|
||
|
|
return nil
|
||
|
|
})
|
||
|
|
}
|