92 lines
3.7 KiB
Go
92 lines
3.7 KiB
Go
package gameserver
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"gac-hkrpg-go/internal/common"
|
|
pb "gac-hkrpg-go/protocol/proto"
|
|
)
|
|
|
|
// The current native BuyExp capture sends capacity, shop weights and level
|
|
// together. The native before/after capture does not rewrite individual role
|
|
// property maps. This does not implement all level-dependent combat effects.
|
|
func cwApplyBaseExperience(catalog *common.CurrencyWarsCatalog, player *pb.NIHNGPKHEPC, shop *pb.POCJDMMANBM, gain uint32) error {
|
|
previous, err := catalog.PlayerLevel(player.EHNJDIDABHD)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
plan, err := catalog.PlanBaseExperience(player.EHNJDIDABHD, player.GridFightCurLevelExp, gain, player.NDAINFLOLPJ)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
row, err := catalog.PlayerLevel(plan.Level)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
// Preserve already resolved run bonuses, rather than resetting capacity
|
|
// to the unmodified level table when equipment/augments add slots.
|
|
capacity := int64(player.AFFCFLFIFPH) + int64(row.AvatarMaxNumber) - int64(previous.AvatarMaxNumber)
|
|
if capacity <= 0 || uint64(capacity) > uint64(^uint32(0)) {
|
|
return fmt.Errorf("CW level capacity is outside protocol range")
|
|
}
|
|
player.EHNJDIDABHD = plan.Level
|
|
player.GridFightCurLevelExp = plan.Exp
|
|
player.AFFCFLFIFPH = uint32(capacity)
|
|
shop.ABBNGCPECAI = &pb.MONJNCPINKN{}
|
|
for i, weight := range row.RarityWeights() {
|
|
shop.ABBNGCPECAI.FIJPICNPKIG = append(shop.ABBNGCPECAI.FIJPICNPKIG, &pb.BOPHDCKJMMN{CKKDAEMFDPA: uint32(i + 1), APAKCBFMCAB: weight})
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func cwCapacitySync(player *pb.NIHNGPKHEPC) *pb.KFNCAIHIHCM {
|
|
return &pb.KFNCAIHIHCM{MNLCHEJKDHO: &pb.KFNCAIHIHCM_BPCFDPNHIEL{BPCFDPNHIEL: player.AFFCFLFIFPH}}
|
|
}
|
|
|
|
func init() {
|
|
cwHandle("GridFightBuyExp", func(s *Session, _ *pb.GridFightBuyExpCsReq, rsp *pb.GridFightBuyExpScRsp) error {
|
|
rsp.Retcode = uint32(pb.Retcode_RET_GRID_FIGHT_PARAM_NOT_MATCH)
|
|
catalog, data, err := cwPreparingData(s)
|
|
if err != nil {
|
|
PacketLog("CW_BUY_EXP rejected: " + err.Error())
|
|
return nil
|
|
}
|
|
player, _, shop := cwComponents(data.DHFOFLFCLAH)
|
|
if player == nil || shop == nil {
|
|
return nil
|
|
}
|
|
row, err := catalog.PlayerLevel(player.EHNJDIDABHD)
|
|
if err != nil || row.LevelUpExp == 0 || player.EHNJDIDABHD >= player.NDAINFLOLPJ {
|
|
return nil
|
|
}
|
|
cost := player.BEPMODICONA // The run's resolved quote, not a fixed gold price.
|
|
if player.Gold < cost {
|
|
rsp.Retcode = uint32(pb.Retcode_RET_GRID_FIGHT_COIN_NOT_ENOUGH)
|
|
return nil
|
|
}
|
|
gain, err := catalog.IntegerRule("GridFight_LevelUpExp")
|
|
if err != nil || gain <= 0 || uint64(gain) > uint64(^uint32(0)) {
|
|
PacketLog(fmt.Sprintf("CW_BUY_EXP rejected: missing or invalid GridFight_LevelUpExp rule value=%d error=%v", gain, err))
|
|
rsp.Retcode = uint32(pb.Retcode_RET_GRID_FIGHT_CONF_MISS)
|
|
return nil
|
|
}
|
|
if err = cwApplyBaseExperience(catalog, player, shop, uint32(gain)); err != nil {
|
|
PacketLog("CW_BUY_EXP rejected: " + err.Error())
|
|
return nil
|
|
}
|
|
player.Gold -= cost
|
|
if err = s.saveCurrencyWarsData(data, catalog); err != nil {
|
|
PacketLog("CW_BUY_EXP save failed: " + err.Error())
|
|
return nil
|
|
}
|
|
notify := cwNotify(cwGoldSync(player.Gold), cwCapacitySync(player), cwShopSync(shop), &pb.KFNCAIHIHCM{MNLCHEJKDHO: &pb.KFNCAIHIHCM_PLPHEIBLPDL{PLPHEIBLPDL: &pb.PIHKLPJGEPM{Level: player.EHNJDIDABHD, Exp: player.GridFightCurLevelExp, HFMKLAPEKFA: player.NDAINFLOLPJ}}})
|
|
notify.GCPNIHHBGGD[0].GridUpdateSrc = pb.JJDFGMMMCMI_JJDFGMMMCMI_IHEKGIGCGEC
|
|
if err = cwSend(s, notify); err != nil {
|
|
return err
|
|
}
|
|
rsp.Retcode = 0
|
|
PacketLog(fmt.Sprintf("CW_BUY_EXP saved cost=%d gain=%d level=%d exp=%d capacity=%d gold=%d revision=%d", cost, gain, player.EHNJDIDABHD, player.GridFightCurLevelExp, player.AFFCFLFIFPH, player.Gold, s.currencyWarsRevision))
|
|
return nil
|
|
})
|
|
}
|