package action import ( "fmt" "math/rand" "os" "path/filepath" "gopkg.in/yaml.v3" ) func SuccessChance(cfg SuccessFormula, level int, requiredLevel int) float64 { chance := cfg.Base + float64(level-requiredLevel)*cfg.PerLevel if chance > cfg.Cap { chance = cfg.Cap } if chance < 0 { chance = 0 } return chance } func LoadDropTable(dataDir, id string) (*DropTableDef, error) { path := filepath.Join(dataDir, "drops", id+".yaml") data, err := os.ReadFile(path) if err != nil { return nil, fmt.Errorf("read drop table %s: %w", id, err) } var dt DropTableDef if err := yaml.Unmarshal(data, &dt); err != nil { return nil, fmt.Errorf("parse drop table %s: %w", id, err) } return &dt, nil } func ResolveDrop(dataDir string, drops []DropEntry) *DropEntry { if len(drops) == 0 { return nil } total := 0 for _, d := range drops { total += d.Weight } if total <= 0 { return nil } roll := rand.Intn(total) cumulative := 0 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, Message: drops[i].Message, } } } return nil } return &drops[i] } } return &drops[0] }