package behavior type GatherConfig struct { Skill string `yaml:"skill"` Tools []string `yaml:"tools"` Bait string `yaml:"bait"` Success SuccessFormula `yaml:"success"` GatherMessage string `yaml:"gather_message"` DepletedMessage string `yaml:"depleted_message"` ExhaustedMessage string `yaml:"exhausted_message"` FailMessage string `yaml:"fail_message"` Drops []DropEntry `yaml:"drops"` RespawnTimer float64 `yaml:"respawn_timer"` RespawnBroadcast string `yaml:"respawn_broadcast"` DepleteTimer float64 `yaml:"deplete_timer"` NestChance int `yaml:"nest_chance"` BroadcastMessage string `yaml:"broadcast_message"` } type SuccessFormula struct { Base float64 `yaml:"base"` PerLevel float64 `yaml:"per_level"` Cap float64 `yaml:"cap"` } type TalkConfig struct { Nodes map[string]TalkNode `yaml:"nodes"` } type TalkNode struct { Messages []string `yaml:"messages,omitempty"` Condition *Condition `yaml:"condition,omitempty"` Options []TalkOption `yaml:"options"` Action *NodeAction `yaml:"action"` Goto string `yaml:"goto,omitempty"` } type TalkOption struct { Text string `yaml:"text"` Goto string `yaml:"goto"` Condition *Condition `yaml:"condition"` Action *NodeAction `yaml:"action,omitempty"` } type NodeAction struct { SetFlags map[string]any `yaml:"set_flags"` SetPlayerFlags map[string]any `yaml:"set_player_flags"` GiveItem string `yaml:"give_item"` TakeItem string `yaml:"take_item"` Teleport int `yaml:"teleport"` Heal int `yaml:"heal"` Credits int `yaml:"credits"` ReputationCost int `yaml:"reputation_cost"` ApsNode bool `yaml:"aps_node"` } // ShopConfig is a root-level mob property (mob YAML `shop:`). Buy prices are // always 100% of the item's value; sell prices follow the OSRS store formula: // // sell = value * max(10, buy_percentage - stock*change_percentage) / 100 // // where stock is the shop's current holding of that item. BuyPercentage // defaults to 40 and ChangePercentage to 3 when unset (see ShopBuyPercentage / // ShopChangePercentage). 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) BuysAnything *bool `yaml:"buys_anything"` // buy items not in the list (default true) Items []ShopItem `yaml:"items"` } type ShopItem struct { ItemID string `yaml:"item_id"` Stock int `yaml:"stock"` // target/max stock; also starting stock RestockTicks float64 `yaml:"restock_ticks"` // per-item restock interval (overrides shop default) } // Shop pricing defaults, applied when the YAML leaves a field at zero. const ( ShopBuyPercentage = 40.0 ShopChangePercentage = 3.0 ShopMinSellPercent = 10.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 { return c.BuyPercentage } return ShopBuyPercentage } // EffectiveChangePercentage returns ChangePercentage or the default. func (c *ShopConfig) EffectiveChangePercentage() float64 { if c.ChangePercentage > 0 { return c.ChangePercentage } return ShopChangePercentage } // Buys reports whether the shop will buy items not in its item list. func (c *ShopConfig) Buys() bool { return c.BuysAnything == nil || *c.BuysAnything } // SellPrice computes the per-unit price the shop pays for an item of the given // value when the shop currently holds `stock` of it. func (c *ShopConfig) SellPrice(value, stock int) int { if stock < 0 { stock = 0 } pct := c.EffectiveBuyPercentage() - float64(stock)*c.EffectiveChangePercentage() if pct < ShopMinSellPercent { pct = ShopMinSellPercent } return int(float64(value) * pct / 100.0) } // RestockInterval returns the effective restock interval (in ticks) for an item, // 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) } return int(ShopDefaultRestock) } // FindItem returns the configured shop item with the given id, or nil. func (c *ShopConfig) FindItem(itemID string) *ShopItem { for i := range c.Items { if c.Items[i].ItemID == itemID { return &c.Items[i] } } return nil } type Condition struct { Flag string `yaml:"flag"` Value any `yaml:"value"` Not bool `yaml:"not"` PlayerFlag string `yaml:"player_flag"` HasItem string `yaml:"has_item"` MinCredits int `yaml:"min_credits"` AllOf []Condition `yaml:"all_of"` AnyOf []Condition `yaml:"any_of"` } type UseConfig struct { StartMessage string `yaml:"start_message"` TicksPerCycle float64 `yaml:"ticks_per_cycle"` Consume map[string]int `yaml:"consume"` Reward DropEntry `yaml:"reward"` FailMessage string `yaml:"fail_message"` Success *SuccessFormula `yaml:"success"` Skill string `yaml:"skill"` Level int `yaml:"level"` XP int `yaml:"xp"` SuccessMessage string `yaml:"success_message"` EndMessage string `yaml:"end_message"` BroadcastMessage string `yaml:"broadcast_message"` }