服务端(Go): - GM 塞背包/带属性装备发放:在线角色推送 op14 增量物品行,背包实时刷新,无需回角色选择界面 - GM 改金币/改等级:去掉在线拒绝,落库后推送 op14 钱包/op37 等级状态,在线实时刷新 - 等级端点统一切换到新版 GMSetCharacterLevel(自带在线刷新) - 无限/锁死疲劳模式 + 燃烧疲劳:每房间消耗 2 点、打怪与通关经验双倍 - 燃烧疲劳开关时给所有在线角色推送系统提示(op12 mode 0) - 深渊史诗掉率:GM 全局倍率 + 城镇增益药剂窗口倍率,真实接入掉落结算 启动器(Python/JS): - 标题栏自绘、窗口 1204x717、禁止拖拽改大小、仅最小化/关闭 - GM 工具:疲劳与燃烧、深渊史诗掉率、拍卖行上架(单一定价对齐) - 拍卖行上架前端对齐服务端单一价格语义,修复 400 报错
446 lines
22 KiB
Go
446 lines
22 KiB
Go
// 本文件定义背包类命令计划。
|
|
// 计划只承载已解析的客户端意图;真正资产变更必须进入可靠 owner、事务和幂等边界后才能回包。
|
|
package inventory
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
|
|
"longheng.io/server/internal/modules/dnf/alignedcmd"
|
|
)
|
|
|
|
// Command 是 inventory handler 交给后续 inventory/equipment/wallet owner 的最小命令计划。
|
|
type Command struct {
|
|
Operation string
|
|
AccountID string
|
|
SelectedCharacterID uint16
|
|
InDungeon bool
|
|
DungeonID int64
|
|
// ConsumableFree marks a sandbox run (修炼道场): the use still runs for its
|
|
// effect, but the owner must not deduct the stack.
|
|
ConsumableFree bool
|
|
SourceListType byte
|
|
SourceSlotIndex int16
|
|
SourceInstanceValue int32
|
|
ReservedValue uint32
|
|
MoveCount int32
|
|
DestinationListType byte
|
|
DestinationSlotIndex int16
|
|
DestinationInstance int32
|
|
DestinationStack int32
|
|
ActorIndex int32
|
|
TrailingState0 byte
|
|
TrailingState1 byte
|
|
EntryCount int
|
|
DeleteStateTrailer bool
|
|
DeleteEntries []DeleteEntry
|
|
Count int32
|
|
ItemTemplateID int32
|
|
RepairSlot int16
|
|
AutoRepair bool
|
|
QuickRepair bool
|
|
TargetSlotIndex int16
|
|
TargetItemTemplateID int32
|
|
MaterialSlotIndex int16
|
|
MaterialItemTemplateID int32
|
|
OptionalTicketSlot int16
|
|
Mode string
|
|
TargetItemName string
|
|
AmplifyAction byte
|
|
SelectedAmplifyOption byte
|
|
RandomOptionIndex byte
|
|
ChronicleOptionNo byte
|
|
InventoryManagerState uint16
|
|
BeadListType byte
|
|
BeadSlotIndex int16
|
|
TargetListType byte
|
|
ItemSpace byte
|
|
DisjointItemSlotIndex int16
|
|
ContextValue int32
|
|
ActionIndex uint32
|
|
DamageFontIndex uint16
|
|
Category byte
|
|
Condition byte
|
|
NeedsOwner string
|
|
// Upgrade policy fields (populated by dnfbridge from PVF table).
|
|
// SuccessWeight is out of 100000; >= 100000 means guaranteed success.
|
|
UpgradeSuccessWeight int
|
|
// PenaltyType: 0=fail no change, 1=one-level downgrade,
|
|
// 2=PVF-value downgrade, 3=destroy.
|
|
UpgradePenaltyType int
|
|
UpgradePenaltyValue int
|
|
// UpgradeGoldCost is resolved from the runtime PVF equipment level,
|
|
// rarity and type. The boolean distinguishes an authoritative zero from
|
|
// legacy focused tests that still carry cost in ItemStack.Extra.
|
|
UpgradeGoldCost int64
|
|
UpgradeGoldCostResolved bool
|
|
// MaterialItemID/Count are the runtime-PVF upgrade table requirement.
|
|
UpgradeMaterialItemID int
|
|
UpgradeMaterialCount int
|
|
// UpgradeHighUpgrade is op50 sub mode 2, the 高级装备强化机. House rule,
|
|
// not PVF: etc/upgrade.etc has no high-upgrade table and never names
|
|
// 高级炉岩炭, so the operator set the terms -- the fuel replaces the
|
|
// ordinary 无色小晶块 one for one, and the table's success weight is
|
|
// multiplied by 1.1 (the item's own [explain] says 110% of 普通炉岩炭).
|
|
UpgradeHighUpgrade bool
|
|
// DestroyBonusItemID/Count: compensation item on destruction.
|
|
UpgradeDestroyBonusItemID int
|
|
UpgradeDestroyBonusCount int
|
|
// UpgradeDestroyExtraRewards: fixed extra rows granted on destruction
|
|
// (异界 equipment refunds 异次元碎片).
|
|
UpgradeDestroyExtraRewards []alignedcmd.UpgradeDestroyReward
|
|
// NoticeLevel: announcement threshold (-1 = disabled).
|
|
UpgradeNoticeLevel int
|
|
// UpgradeGuildMedal marks a list-38 公会徽章 reinforce, whose success
|
|
// weight, penalty, gold cost and material all come from the native
|
|
// flag_upgrade_table row instead of the equipment upgrade table.
|
|
// UpgradePolicyLevel is the flag level that row was resolved for, so the
|
|
// owner can refuse a request whose stored level moved since.
|
|
UpgradeGuildMedal bool
|
|
UpgradePolicyLevel int
|
|
// Portable amplification devices travel in op50's material slot but use
|
|
// the ordinary amplification probability/penalty table. They replace the
|
|
// normal PVF material and gold cost while retaining destruction/protection.
|
|
UpgradePortableAmplifier bool
|
|
UpgradePortableReinforcer bool
|
|
UpgradePortableMinimum int64
|
|
UpgradePortableMaximum int64
|
|
UpgradeTargetMinimumLevel int64
|
|
UpgradeTargetLevelMinimum int64
|
|
UpgradeTargetLevelMaximum int64
|
|
// UpgradePolicyError records PVF resolver failures so packet-log command
|
|
// reasons do not silently degrade into materialPVF=(0,0).
|
|
UpgradePolicyError string
|
|
ChronicleTicketSlot int16
|
|
ChronicleTargetSlot int16
|
|
ChronicleMaterialSlot int16
|
|
ChronicleTicketID int64
|
|
ChronicleTargetID int64
|
|
ChronicleMaterialID int64
|
|
}
|
|
|
|
func NewChronicleGrowthCommand(req alignedcmd.Request, parsed ChronicleGrowthRequest) Command {
|
|
cmd := baseCommand(req, "upgrade_chronicle", "inventory owner + PVF ticket policy + atomic target/material mutation + op271/op14 order")
|
|
cmd.ChronicleTicketSlot = parsed.TicketSlotIndex
|
|
cmd.ChronicleTargetSlot = parsed.TargetSlotIndex
|
|
cmd.ChronicleMaterialSlot = parsed.MaterialSlotIndex
|
|
cmd.ChronicleTicketID = int64(parsed.TicketItemCode)
|
|
cmd.ChronicleTargetID = int64(parsed.TargetItemCode)
|
|
cmd.ChronicleMaterialID = int64(parsed.MaterialItemCode)
|
|
return cmd
|
|
}
|
|
|
|
func NewMonsterCardUpgradeCommand(req alignedcmd.Request, parsed MonsterCardUpgradeRequest) Command {
|
|
cmd := baseCommand(req, "upgrade_monster_card", "current NoPack op603 + runtime-PVF card policy + atomic wallet/inventory mutation")
|
|
cmd.SourceListType = parsed.ListType
|
|
cmd.TargetSlotIndex = parsed.TargetSlot
|
|
cmd.MaterialSlotIndex = parsed.MaterialSlot
|
|
cmd.Count = int32(parsed.MaterialCount)
|
|
return cmd
|
|
}
|
|
|
|
// NewDeleteCommand 构造删除物品命令计划。
|
|
func NewDeleteCommand(req alignedcmd.Request, parsed DeleteRequest) Command {
|
|
cmd := baseCommand(req, "delete_item", "inventory owner + mutation id + backpack/USERINFO/NOTI order")
|
|
cmd.SourceListType = parsed.ListType
|
|
cmd.SourceSlotIndex = parsed.SlotIndex
|
|
cmd.Count = int32(parsed.Count)
|
|
cmd.EntryCount = len(parsed.Entries)
|
|
cmd.DeleteStateTrailer = parsed.StateTrailer
|
|
cmd.DeleteEntries = append([]DeleteEntry(nil), parsed.Entries...)
|
|
if parsed.Extended && len(parsed.Entries) > 0 {
|
|
cmd.SourceSlotIndex = parsed.Entries[0].SlotIndex
|
|
cmd.ItemTemplateID = parsed.Entries[0].ItemID
|
|
cmd.Count = parsed.Entries[0].DeleteCount
|
|
}
|
|
return cmd
|
|
}
|
|
|
|
// NewMoveCommand 构造移动或拆分物品命令计划。
|
|
func NewMoveCommand(req alignedcmd.Request, parsed MoveItemspaceRequest) Command {
|
|
cmd := baseCommand(req, "move_itemspace", "inventory/equipment/cargo owner + mutation id + backpack/USERINFO/NOTI order")
|
|
cmd.SourceListType = parsed.SourceListType
|
|
cmd.SourceSlotIndex = parsed.SourceSlotIndex
|
|
cmd.SourceInstanceValue = parsed.SourceInstanceValue
|
|
cmd.MoveCount = parsed.MoveCount
|
|
cmd.DestinationListType = parsed.DestinationListType
|
|
cmd.DestinationSlotIndex = parsed.DestinationSlotIndex
|
|
cmd.DestinationInstance = parsed.DestinationInstanceValue
|
|
cmd.DestinationStack = parsed.DestinationStack
|
|
cmd.ActorIndex = parsed.ActorIndex
|
|
cmd.TrailingState0 = parsed.TrailingState0
|
|
cmd.TrailingState1 = parsed.TrailingState1
|
|
return cmd
|
|
}
|
|
|
|
// NewSortCommand 构造整理背包命令计划。
|
|
func NewSortCommand(req alignedcmd.Request, parsed SortItemRequest) Command {
|
|
cmd := baseCommand(req, "sort_item", "inventory owner + deterministic sort + backpack refresh order")
|
|
cmd.SourceListType = parsed.ListType
|
|
cmd.Category = parsed.Category
|
|
cmd.Condition = parsed.Condition
|
|
return cmd
|
|
}
|
|
|
|
// NewBuyCommand 构造 NPC 购买命令计划。
|
|
func NewBuyCommand(req alignedcmd.Request, parsed BuyItemRequest) Command {
|
|
cmd := baseCommand(req, "buy_item", "inventory owner + wallet owner + shop validation + mutation id + popup/NOTI order")
|
|
cmd.ItemTemplateID = parsed.ItemTemplateID
|
|
cmd.Count = parsed.Count
|
|
return cmd
|
|
}
|
|
|
|
// NewSellCommand 构造出售物品命令计划。
|
|
func NewSellCommand(req alignedcmd.Request, parsed DeleteOrSellRequest) Command {
|
|
cmd := baseCommand(req, "sell_item", "inventory owner + wallet owner + mutation id + backpack/USERINFO/NOTI order")
|
|
cmd.SourceListType = parsed.ListType
|
|
cmd.SourceSlotIndex = parsed.SlotIndex
|
|
cmd.Count = int32(parsed.Count)
|
|
return cmd
|
|
}
|
|
|
|
// NewRepairCommand 构造修理装备命令计划。
|
|
func NewRepairCommand(req alignedcmd.Request, parsed RepairEquipmentRequest) Command {
|
|
cmd := baseCommand(req, "repair_equipment", "equipment owner + wallet owner + durability persistence + USERINFO/NOTI order")
|
|
cmd.SourceListType = parsed.InvenType
|
|
cmd.SourceSlotIndex = parsed.SlotIndex
|
|
cmd.RepairSlot = parsed.RepairItemSlot
|
|
cmd.AutoRepair = parsed.AutoRepair
|
|
cmd.QuickRepair = parsed.QuickRepair
|
|
return cmd
|
|
}
|
|
|
|
// NewDisjointCommand 构造分解物品命令计划。
|
|
func NewDisjointCommand(req alignedcmd.Request, parsed DisjointItemRequest) Command {
|
|
cmd := baseCommand(req, "disjoint_item", "inventory owner + disjoint reward owner + mutation id + ACK/backpack/popup order")
|
|
cmd.TargetSlotIndex = parsed.TargetSlotIndex
|
|
cmd.ItemSpace = parsed.ItemSpace
|
|
cmd.DisjointItemSlotIndex = parsed.DisjointItemSlotIndex
|
|
cmd.ContextValue = parsed.ContextValue
|
|
return cmd
|
|
}
|
|
|
|
// NewUseStackableCommand 构造使用消耗品命令计划。
|
|
func NewUseStackableCommand(req alignedcmd.Request, parsed UseStackableRequest) Command {
|
|
cmd := baseCommand(req, "use_stackable", "inventory owner + effect/reward owner + mutation id + USERINFO/NOTI order")
|
|
cmd.SourceListType = parsed.ListType
|
|
cmd.SourceSlotIndex = parsed.SlotIndex
|
|
cmd.SourceInstanceValue = parsed.InstanceValue
|
|
cmd.ItemTemplateID = parsed.ItemCode
|
|
cmd.ReservedValue = parsed.Reserved
|
|
return cmd
|
|
}
|
|
|
|
// NewEventServerLevelUpCommand constructs the compact op418 command. Unlike
|
|
// op44, the current client does not echo an instance value or item template;
|
|
// the owner resolves authority and identity from the durable source row.
|
|
func NewEventServerLevelUpCommand(req alignedcmd.Request, parsed EventServerLevelUpRequest) Command {
|
|
cmd := baseCommand(req, "event_server_level_up", "inventory + character + skill + quest atomic owner + current-PVF level-up ticket")
|
|
cmd.SourceListType = parsed.ListType
|
|
cmd.SourceSlotIndex = parsed.SlotIndex
|
|
return cmd
|
|
}
|
|
|
|
// NewIncreaseStatusCommand constructs the current NoPack op30 command. The
|
|
// request carries only a slot, so the list owner is fixed to the main
|
|
// inventory and the item identity stays zero until the durable row resolves it.
|
|
func NewIncreaseStatusCommand(req alignedcmd.Request, parsed IncreaseStatusRequest) Command {
|
|
cmd := baseCommand(req, "increase_status_book", "inventory + character + skill atomic owner + current-PVF SP/TP or experience book")
|
|
cmd.SourceListType = listTypeMain
|
|
cmd.SourceSlotIndex = parsed.SlotIndex
|
|
return cmd
|
|
}
|
|
|
|
// NewUseSharedEffectItemCommand constructs the type251 shared-effect plan.
|
|
// Its six-byte request carries the source item template followed by the source
|
|
// slot, both of which the owner verifies against durable inventory state.
|
|
func NewUseSharedEffectItemCommand(req alignedcmd.Request, parsed UseSharedEffectItemRequest) Command {
|
|
cmd := baseCommand(req, "use_shared_effect_item", "inventory owner + random-reward transaction + type251 ACK/op14 order")
|
|
cmd.SourceListType = parsed.ListType
|
|
cmd.SourceSlotIndex = parsed.SlotIndex
|
|
cmd.ItemTemplateID = parsed.ItemTemplateID
|
|
return cmd
|
|
}
|
|
|
|
func NewUseStackableActionCommand(req alignedcmd.Request, parsed UseStackableActionRequest) Command {
|
|
cmd := baseCommand(req, "use_stackable_action", "character + inventory atomic owner + runtime-PVF action definition")
|
|
cmd.SourceListType = parsed.ListType
|
|
cmd.SourceSlotIndex = parsed.SourceSlotIndex
|
|
cmd.ActionIndex = parsed.ActionIndex
|
|
return cmd
|
|
}
|
|
|
|
func NewSelectDamageFontCommand(req alignedcmd.Request, parsed SelectDamageFontRequest) Command {
|
|
cmd := baseCommand(req, "select_damage_font", "character asset owner + owned/unexpired damage-font state")
|
|
cmd.DamageFontIndex = parsed.FontIndex
|
|
return cmd
|
|
}
|
|
|
|
// NewContainerUpgradeCommand 构造扩容券(op430 物品栏 / op408 金库)的请求计划。
|
|
// 请求体只有一个槽位,券的身份由 owner 从持久行 + 运行时 PVF action type 反查。
|
|
func NewContainerUpgradeCommand(req alignedcmd.Request, parsed ContainerUpgradeRequest) Command {
|
|
cmd := baseCommand(req, "upgrade_container", "inventory + character container-state + account cargo atomic owner + runtime-PVF [upgrade *] action type")
|
|
cmd.SourceListType = parsed.ListType
|
|
cmd.SourceSlotIndex = parsed.SlotIndex
|
|
return cmd
|
|
}
|
|
|
|
// NewUpgradeCommand 构造强化或增幅命令计划。
|
|
func NewUpgradeCommand(req alignedcmd.Request, parsed UpgradeItemRequest) Command {
|
|
cmd := baseCommand(req, "upgrade_item", "equipment owner + wallet/material owner + mutation id + reinforce result/USERINFO order")
|
|
cmd.Mode = parsed.Mode
|
|
cmd.TargetListType = parsed.TargetListType
|
|
cmd.TargetSlotIndex = parsed.TargetSlotIndex
|
|
cmd.TargetItemTemplateID = parsed.TargetItemTemplateID
|
|
cmd.MaterialSlotIndex = parsed.MaterialSlotIndex
|
|
cmd.OptionalTicketSlot = parsed.OptionalTicketSlotIndex
|
|
if parsed.TargetListType == listTypeGuildMedal && cmd.OptionalTicketSlot == 255 {
|
|
// The medal page has no ticket slot, so the client sends its unsigned
|
|
// "none" sentinel (255) instead of -1. The owner's list-38 gate refuses
|
|
// any optional ticket, so normalise it here.
|
|
cmd.OptionalTicketSlot = -1
|
|
}
|
|
cmd.TargetItemName = parsed.TargetItemName
|
|
cmd.UpgradeHighUpgrade = parsed.HighUpgrade
|
|
cmd.UpgradeNoticeLevel = -1
|
|
return cmd
|
|
}
|
|
|
|
// NewSeparateUpgradeCommand constructs the current op438 forging mutation.
|
|
func NewSeparateUpgradeCommand(req alignedcmd.Request, parsed SeparateUpgradeRequest) Command {
|
|
cmd := baseCommand(req, "upgrade_item_separate", "inventory + equipment atomic owner + runtime-PVF forging table")
|
|
cmd.TargetListType = parsed.TargetListType
|
|
cmd.TargetSlotIndex = parsed.TargetSlotIndex
|
|
cmd.TargetItemTemplateID = parsed.TargetItemTemplateID
|
|
cmd.MaterialSlotIndex = parsed.MaterialSlotIndex
|
|
cmd.TargetItemName = parsed.TargetItemName
|
|
cmd.TrailingState0 = parsed.TrailingFlag
|
|
return cmd
|
|
}
|
|
|
|
// NewChronicleRefineCommand constructs the current op370 mutation plan.
|
|
func NewChronicleRefineCommand(req alignedcmd.Request, parsed ChronicleRefineRequest) Command {
|
|
cmd := baseCommand(req, "chronicle_refine", "character + inventory + equipment atomic owner + runtime-PVF imported aura script")
|
|
cmd.MaterialSlotIndex = parsed.MaterialSlotIndex
|
|
cmd.MaterialItemTemplateID = parsed.MaterialItemTemplateID
|
|
cmd.TargetListType = parsed.TargetListType
|
|
cmd.TargetSlotIndex = parsed.TargetSlotIndex
|
|
cmd.TargetItemTemplateID = parsed.TargetItemTemplateID
|
|
cmd.ChronicleOptionNo = parsed.OptionNo
|
|
return cmd
|
|
}
|
|
|
|
// NewEnchantCommand 构造宝珠附魔命令计划。
|
|
func NewEnchantCommand(req alignedcmd.Request, parsed EnchantByBeadRequest) Command {
|
|
cmd := baseCommand(req, "enchant_by_bead", "inventory owner + equipment owner + mutation id + equipment/USERINFO/NOTI order")
|
|
cmd.BeadListType = parsed.BeadListType
|
|
cmd.BeadSlotIndex = parsed.BeadSlotIndex
|
|
cmd.TargetListType = parsed.TargetListType
|
|
cmd.TargetSlotIndex = parsed.TargetSlotIndex
|
|
return cmd
|
|
}
|
|
|
|
func NewPurifyItemCommand(req alignedcmd.Request, parsed PurifyItemRequest) Command {
|
|
cmd := baseCommand(req, "purify_item", "inventory owner + runtime PVF amplify config + atomic target/material mutation + current-EXE op204 ACK")
|
|
cmd.TargetSlotIndex = parsed.TargetSlotIndex
|
|
cmd.TargetItemTemplateID = parsed.TargetItemTemplateID
|
|
cmd.MaterialSlotIndex = parsed.MaterialSlotIndex
|
|
cmd.MaterialItemTemplateID = parsed.MaterialItemTemplateID
|
|
return cmd
|
|
}
|
|
|
|
func NewInvestItemAmplifyOptionCommand(req alignedcmd.Request, parsed InvestItemAmplifyOptionRequest) Command {
|
|
cmd := baseCommand(req, "invest_item_amplify_option", "inventory owner + runtime PVF amplify config + atomic target/material mutation + current-EXE op205 ACK")
|
|
cmd.AmplifyAction = parsed.Action
|
|
cmd.TargetSlotIndex = parsed.TargetSlotIndex
|
|
cmd.TargetItemTemplateID = parsed.TargetItemTemplateID
|
|
cmd.MaterialSlotIndex = parsed.MaterialSlotIndex
|
|
cmd.MaterialItemTemplateID = parsed.MaterialItemTemplateID
|
|
cmd.SelectedAmplifyOption = parsed.SelectedOption
|
|
cmd.TargetItemName = parsed.TargetItemName
|
|
return cmd
|
|
}
|
|
|
|
func baseCommand(req alignedcmd.Request, operation string, needs string) Command {
|
|
return Command{
|
|
Operation: operation,
|
|
AccountID: strings.TrimSpace(req.AccountID),
|
|
SelectedCharacterID: req.SelectedCharacterID,
|
|
InDungeon: req.InDungeon,
|
|
DungeonID: req.DungeonID,
|
|
ConsumableFree: req.ConsumableFree,
|
|
NeedsOwner: needs,
|
|
}
|
|
}
|
|
|
|
// NewUnsealRandomOptionCommand constructs the current op401 mutation plan.
|
|
func NewUnsealRandomOptionCommand(req alignedcmd.Request, parsed UnsealRandomOptionRequest) Command {
|
|
cmd := baseCommand(req, "unseal_random_option", "inventory + character wallet atomic owner + runtime PVF")
|
|
cmd.TargetSlotIndex = parsed.TargetSlotIndex
|
|
cmd.InventoryManagerState = parsed.InventoryManagerState
|
|
return cmd
|
|
}
|
|
|
|
// NewChangeRandomOptionCommand constructs the current op437 mutation plan.
|
|
func NewChangeRandomOptionCommand(req alignedcmd.Request, parsed ChangeRandomOptionRequest) Command {
|
|
cmd := baseCommand(req, "change_random_option", "inventory + character wallet atomic owner + runtime PVF")
|
|
cmd.TargetSlotIndex = parsed.TargetSlotIndex
|
|
cmd.ReservedValue = uint32(parsed.Reserved)
|
|
cmd.RandomOptionIndex = parsed.OptionIndex
|
|
return cmd
|
|
}
|
|
|
|
// NewResetRandomOptionCommand constructs the current op455 mutation plan: the
|
|
// seal-grade reset consumes one adjustment box from MaterialSlotIndex and
|
|
// re-rolls only the selected option's grade percentage.
|
|
func NewResetRandomOptionCommand(req alignedcmd.Request, parsed ResetRandomOptionRequest) Command {
|
|
cmd := baseCommand(req, "reset_random_option", "inventory atomic owner + runtime PVF grade windows")
|
|
cmd.TargetSlotIndex = parsed.TargetSlotIndex
|
|
cmd.MaterialSlotIndex = parsed.MaterialSlotIndex
|
|
cmd.RandomOptionIndex = parsed.OptionIndex
|
|
return cmd
|
|
}
|
|
|
|
func (c Command) String() string {
|
|
base := fmt.Sprintf("account=%q char=%d", c.AccountID, c.SelectedCharacterID)
|
|
switch c.Operation {
|
|
case "delete_item", "sell_item":
|
|
return fmt.Sprintf("%s list=%d slot=%d count=%d entries=%d item=%d needs=%s", base, c.SourceListType, c.SourceSlotIndex, c.Count, c.EntryCount, c.ItemTemplateID, c.NeedsOwner)
|
|
case "move_itemspace":
|
|
return fmt.Sprintf("%s src=(%d,%d,0x%08X) count=%d dst=(%d,%d,0x%08X) dstStack=%d actor=%d tail=(%d,%d) needs=%s", base, c.SourceListType, c.SourceSlotIndex, uint32(c.SourceInstanceValue), c.MoveCount, c.DestinationListType, c.DestinationSlotIndex, uint32(c.DestinationInstance), c.DestinationStack, c.ActorIndex, c.TrailingState0, c.TrailingState1, c.NeedsOwner)
|
|
case "sort_item":
|
|
return fmt.Sprintf("%s list=%d category=%d condition=%d needs=%s", base, c.SourceListType, c.Category, c.Condition, c.NeedsOwner)
|
|
case "buy_item":
|
|
return fmt.Sprintf("%s item=%d count=%d needs=%s", base, c.ItemTemplateID, c.Count, c.NeedsOwner)
|
|
case "repair_equipment":
|
|
return fmt.Sprintf("%s list=%d slot=%d repairSlot=%d auto=%t quick=%t needs=%s", base, c.SourceListType, c.SourceSlotIndex, c.RepairSlot, c.AutoRepair, c.QuickRepair, c.NeedsOwner)
|
|
case "disjoint_item":
|
|
return fmt.Sprintf("%s targetSlot=%d itemSpace=%d disjointSlot=%d ctx=0x%08X needs=%s", base, c.TargetSlotIndex, c.ItemSpace, c.DisjointItemSlotIndex, uint32(c.ContextValue), c.NeedsOwner)
|
|
case "use_stackable":
|
|
return fmt.Sprintf("%s list=%d slot=%d instance=0x%08X item=0x%08X reserved=0x%08X needs=%s", base, c.SourceListType, c.SourceSlotIndex, uint32(c.SourceInstanceValue), uint32(c.ItemTemplateID), c.ReservedValue, c.NeedsOwner)
|
|
case "event_server_level_up", "increase_status_book":
|
|
return fmt.Sprintf("%s list=%d slot=%d needs=%s", base, c.SourceListType, c.SourceSlotIndex, c.NeedsOwner)
|
|
case "use_shared_effect_item":
|
|
return fmt.Sprintf("%s list=%d slot=%d item=0x%08X needs=%s", base, c.SourceListType, c.SourceSlotIndex, uint32(c.ItemTemplateID), c.NeedsOwner)
|
|
case "upgrade_item":
|
|
if c.UpgradePolicyError != "" {
|
|
return fmt.Sprintf("%s mode=%s target=(%d,%d) materialSlot=%d materialPVF=(%d,%d) policyErr=%q ticket=%d name=%q needs=%s", base, c.Mode, c.TargetSlotIndex, c.TargetItemTemplateID, c.MaterialSlotIndex, c.UpgradeMaterialItemID, c.UpgradeMaterialCount, c.UpgradePolicyError, c.OptionalTicketSlot, c.TargetItemName, c.NeedsOwner)
|
|
}
|
|
return fmt.Sprintf("%s mode=%s target=(%d,%d) materialSlot=%d materialPVF=(%d,%d) goldPVF=%d ticket=%d name=%q needs=%s", base, c.Mode, c.TargetSlotIndex, c.TargetItemTemplateID, c.MaterialSlotIndex, c.UpgradeMaterialItemID, c.UpgradeMaterialCount, c.UpgradeGoldCost, c.OptionalTicketSlot, c.TargetItemName, c.NeedsOwner)
|
|
case "upgrade_item_separate":
|
|
return fmt.Sprintf("%s target=(%d,%d,%d) materialSlot=%d name=%q tail=%d needs=%s", base, c.TargetListType, c.TargetSlotIndex, c.TargetItemTemplateID, c.MaterialSlotIndex, c.TargetItemName, c.TrailingState0, c.NeedsOwner)
|
|
case "enchant_by_bead":
|
|
return fmt.Sprintf("%s bead=(%d,%d) target=(%d,%d) needs=%s", base, c.BeadListType, c.BeadSlotIndex, c.TargetListType, c.TargetSlotIndex, c.NeedsOwner)
|
|
case "purify_item":
|
|
return fmt.Sprintf("%s target=(%d,%d) material=(%d,%d) needs=%s", base, c.TargetSlotIndex, c.TargetItemTemplateID, c.MaterialSlotIndex, c.MaterialItemTemplateID, c.NeedsOwner)
|
|
case "invest_item_amplify_option":
|
|
return fmt.Sprintf("%s action=%d target=(%d,%d) material=(%d,%d) selected=%d name=%q needs=%s", base, c.AmplifyAction, c.TargetSlotIndex, c.TargetItemTemplateID, c.MaterialSlotIndex, c.MaterialItemTemplateID, c.SelectedAmplifyOption, c.TargetItemName, c.NeedsOwner)
|
|
case "unseal_random_option":
|
|
return fmt.Sprintf("%s targetSlot=%d managerState=0x%04X needs=%s", base, c.TargetSlotIndex, c.InventoryManagerState, c.NeedsOwner)
|
|
case "change_random_option":
|
|
return fmt.Sprintf("%s targetSlot=%d reserved=0x%04X optionIndex=%d needs=%s", base, c.TargetSlotIndex, c.ReservedValue, c.RandomOptionIndex, c.NeedsOwner)
|
|
default:
|
|
return fmt.Sprintf("%s needs=%s", base, c.NeedsOwner)
|
|
}
|
|
}
|