DNF90 服务端与启动器完整源码(含 GM 工具功能增强)
服务端(Go): - GM 塞背包/带属性装备发放:在线角色推送 op14 增量物品行,背包实时刷新,无需回角色选择界面 - GM 改金币/改等级:去掉在线拒绝,落库后推送 op14 钱包/op37 等级状态,在线实时刷新 - 等级端点统一切换到新版 GMSetCharacterLevel(自带在线刷新) - 无限/锁死疲劳模式 + 燃烧疲劳:每房间消耗 2 点、打怪与通关经验双倍 - 燃烧疲劳开关时给所有在线角色推送系统提示(op12 mode 0) - 深渊史诗掉率:GM 全局倍率 + 城镇增益药剂窗口倍率,真实接入掉落结算 启动器(Python/JS): - 标题栏自绘、窗口 1204x717、禁止拖拽改大小、仅最小化/关闭 - GM 工具:疲劳与燃烧、深渊史诗掉率、拍卖行上架(单一定价对齐) - 拍卖行上架前端对齐服务端单一价格语义,修复 400 报错
This commit is contained in:
commit
645b64fe21
4388 files changed
+1405457
No files matched your search
@@ -0,0 +1,445 @@
|
||||
// 本文件定义背包类命令计划。
|
||||
// 计划只承载已解析的客户端意图;真正资产变更必须进入可靠 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)
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user