diff options
Diffstat (limited to 'internal/behavior')
| -rw-r--r-- | internal/behavior/behavior.go | 13 | ||||
| -rw-r--r-- | internal/behavior/store.go | 86 |
2 files changed, 71 insertions, 28 deletions
diff --git a/internal/behavior/behavior.go b/internal/behavior/behavior.go index 646495a..06e2715 100644 --- a/internal/behavior/behavior.go +++ b/internal/behavior/behavior.go @@ -66,7 +66,6 @@ type ShopConfig struct { Message string `yaml:"message"` BuyPercentage float64 `yaml:"buy_percentage"` // sell price at zero stock, % of value (default 40) ChangePercentage float64 `yaml:"change_percentage"` // sell price drop per unit of stock, % of value (default 3) - RestockTicks float64 `yaml:"restock_ticks"` // shop-wide default restock interval BuysAnything *bool `yaml:"buys_anything"` // buy items not in the list (default true) Items []ShopItem `yaml:"items"` } @@ -82,9 +81,14 @@ const ( ShopBuyPercentage = 40.0 ShopChangePercentage = 3.0 ShopMinSellPercent = 10.0 - ShopDefaultRestock = 100.0 ) +// ShopDefaultRestock is the fallback restock interval (in ticks) for a shop item +// that does not set its own restock_ticks. It is configurable via +// game_constants.shop_default_restock in config.yaml (wired up at startup); the +// value here is only the default used when no config is loaded. +var ShopDefaultRestock = 1000.0 + // EffectiveBuyPercentage returns BuyPercentage or the default. func (c *ShopConfig) EffectiveBuyPercentage() float64 { if c.BuyPercentage > 0 { @@ -120,14 +124,11 @@ func (c *ShopConfig) SellPrice(value, stock int) int { } // RestockInterval returns the effective restock interval (in ticks) for an item, -// honoring the per-item override, then the shop default, then the global default. +// honoring the per-item override, then the configurable global default. func (c *ShopConfig) RestockInterval(item *ShopItem) int { if item != nil && item.RestockTicks > 0 { return int(item.RestockTicks) } - if c.RestockTicks > 0 { - return int(c.RestockTicks) - } return int(ShopDefaultRestock) } diff --git a/internal/behavior/store.go b/internal/behavior/store.go index 38cc72b..8112e1c 100644 --- a/internal/behavior/store.go +++ b/internal/behavior/store.go @@ -126,7 +126,9 @@ func LoadDropTable(dataDir, id string) (*DropTableDef, error) { return &dt, nil } -func ResolveDrop(dataDir string, drops []DropEntry) *DropEntry { +// pickWeighted returns a single entry chosen by weight, without resolving any +// table reference on it. Returns nil if the list is empty or has no weight. +func pickWeighted(drops []DropEntry) *DropEntry { if len(drops) == 0 { return nil } @@ -142,29 +144,69 @@ func ResolveDrop(dataDir string, drops []DropEntry) *DropEntry { for i := range drops { cumulative += drops[i].Weight if roll < cumulative { - if drops[i].Table != "" { - sub, err := LoadDropTable(dataDir, drops[i].Table) - if err == nil { - if resolved := ResolveDrop(dataDir, sub.Drops); resolved != nil { - qty := drops[i].Quantity - if qty <= 0 { - qty = resolved.Quantity - } - if qty <= 0 { - qty = 1 - } - return &DropEntry{ - ItemID: resolved.ItemID, - Quantity: qty, - Depletes: drops[i].Depletes, - SuccessMessage: drops[i].SuccessMessage, - } - } - } - return nil - } return &drops[i] } } return &drops[0] } + +func ResolveDrop(dataDir string, drops []DropEntry) *DropEntry { + picked := pickWeighted(drops) + if picked == nil { + return nil + } + if picked.Table != "" { + sub, err := LoadDropTable(dataDir, picked.Table) + if err != nil { + return nil + } + resolved := ResolveDrop(dataDir, sub.Drops) + if resolved == nil { + return nil + } + qty := picked.Quantity + if qty <= 0 { + qty = resolved.Quantity + } + if qty <= 0 { + qty = 1 + } + return &DropEntry{ + ItemID: resolved.ItemID, + Quantity: qty, + Depletes: picked.Depletes, + SuccessMessage: picked.SuccessMessage, + } + } + return picked +} + +// ResolveDropList performs one weighted pick from drops. A plain item entry +// yields a single result. When the picked entry references a sub-table, its +// Quantity is treated as the number of INDEPENDENT rolls against that sub-table +// (default 1) — each roll may produce a different item — and all results are +// returned. Tables are just weighted lists of items; this is skill-independent. +func ResolveDropList(dataDir string, drops []DropEntry) []DropEntry { + picked := pickWeighted(drops) + if picked == nil { + return nil + } + if picked.Table == "" { + return []DropEntry{*picked} + } + sub, err := LoadDropTable(dataDir, picked.Table) + if err != nil { + return nil + } + rolls := picked.Quantity + if rolls <= 0 { + rolls = 1 + } + var out []DropEntry + for i := 0; i < rolls; i++ { + if resolved := ResolveDrop(dataDir, sub.Drops); resolved != nil && resolved.ItemID != "" { + out = append(out, *resolved) + } + } + return out +} |
