package object import ( "fmt" "strings" "gopkg.in/yaml.v3" ) func WordPrefixMatch(input, name string) bool { inputWords := strings.Fields(strings.ToLower(input)) if len(inputWords) == 0 { return false } nameWords := strings.Fields(strings.ToLower(name)) for _, iw := range inputWords { found := false for _, nw := range nameWords { if strings.HasPrefix(nw, iw) || strings.HasPrefix(iw, nw) { found = true break } } if !found { return false } } return true } type EquipSlot string const ( SlotHead EquipSlot = "head" SlotNeck EquipSlot = "neck" SlotTorso EquipSlot = "torso" SlotLegs EquipSlot = "legs" SlotHands EquipSlot = "hands" SlotFeet EquipSlot = "feet" SlotBack EquipSlot = "back" SlotAmmo EquipSlot = "ammo" SlotMainHand EquipSlot = "main_hand" SlotOffHand EquipSlot = "off_hand" SlotRing EquipSlot = "ring" ) type WeaponType string const ( WeaponMelee WeaponType = "melee" WeaponRanged WeaponType = "ranged" WeaponScience WeaponType = "science" ) type ItemDef struct { ID string `yaml:"id"` Name string `yaml:"name"` Color string `yaml:"color"` Description string `yaml:"description"` Value int `yaml:"value"` Stackable bool `yaml:"stackable"` EquipSlot EquipSlot `yaml:"equip_slot"` WeaponType WeaponType `yaml:"weapon_type"` AttackType string `yaml:"attack_type"` Stats ItemStats `yaml:"stats"` Speed float64 `yaml:"speed"` Requirements map[string]int `yaml:"requirements,omitempty"` ToolType string `yaml:"tool_type"` ToolSpeed float64 `yaml:"tool_speed"` BurnTicks float64 `yaml:"burn_ticks"` FireLevel int `yaml:"fire_level"` FireXP int `yaml:"fire_xp"` Quality int `yaml:"quality"` MaxQuality int `yaml:"max_quality"` SearchTable string `yaml:"search_table"` SearchMiscTable string `yaml:"search_misc_table"` SearchTicks float64 `yaml:"search_ticks"` SearchMessage string `yaml:"search_message"` HealValue int `yaml:"heal_value"` EatMessage string `yaml:"eat_message"` Craft CraftList `yaml:"craft,omitempty"` ProvidesJunk string `yaml:"provides_junk,omitempty"` FarmPatchType string `yaml:"farm_patch_type"` FarmLevel int `yaml:"farm_level"` FarmPlantXP int `yaml:"farm_plant_xp"` FarmHarvestXP int `yaml:"farm_harvest_xp"` FarmStages int `yaml:"farm_stages"` FarmProduct string `yaml:"farm_product"` FarmMinYield int `yaml:"farm_min_yield"` FarmMaxYield int `yaml:"farm_max_yield"` PotionEffect string `yaml:"potion_effect"` PotionBonus int `yaml:"potion_bonus"` PotionDuration float64 `yaml:"potion_duration"` Recoverable bool `yaml:"recoverable"` } type CraftList []CraftDef func (cl *CraftList) UnmarshalYAML(value *yaml.Node) error { switch value.Kind { case yaml.SequenceNode: return value.Decode((*[]CraftDef)(cl)) case yaml.MappingNode: var single CraftDef if err := value.Decode(&single); err != nil { return err } *cl = []CraftDef{single} return nil } return fmt.Errorf("craft: expected mapping or sequence") } func (d *ItemDef) FirstCraft() *CraftDef { if len(d.Craft) == 0 { return nil } return &d.Craft[0] } func (d *ItemDef) FindCraft(fn func(CraftDef) bool) *CraftDef { for i := range d.Craft { if fn(d.Craft[i]) { return &d.Craft[i] } } return nil } func (d *ItemDef) MatchingCrafts(fn func(CraftDef) bool) []*CraftDef { var result []*CraftDef for i := range d.Craft { if fn(d.Craft[i]) { result = append(result, &d.Craft[i]) } } return result } type ConsumeEntry struct { Items []string `yaml:"items"` Quantity int `yaml:"quantity"` Byproducts []string `yaml:"byproducts"` } type CraftStep struct { Tick float64 `yaml:"tick"` Message string `yaml:"message"` } type SuccessFormula struct { Base float64 `yaml:"base"` PerLevel float64 `yaml:"per_level"` Cap float64 `yaml:"cap"` } type CraftDef struct { Type string `yaml:"type"` Skill string `yaml:"skill"` Level int `yaml:"level"` XP int `yaml:"xp"` Wait float64 `yaml:"wait"` Station []string `yaml:"station"` Tool string `yaml:"tool"` Consume []ConsumeEntry `yaml:"consume"` OutputQty int `yaml:"output_qty"` Fail string `yaml:"fail"` Message string `yaml:"message"` FailMessage string `yaml:"fail_message"` StartMessage string `yaml:"start_message"` EndMessage string `yaml:"end_message"` Steps []CraftStep `yaml:"steps"` Success *SuccessFormula `yaml:"success"` } func (c *CraftDef) EffectiveSkill() string { if c.Skill != "" { return c.Skill } return c.Type } type ItemStats struct { StabAttack int `yaml:"stab_attack"` SlashAttack int `yaml:"slash_attack"` CrushAttack int `yaml:"crush_attack"` ScienceAttack int `yaml:"science_attack"` RangedAttack int `yaml:"ranged_attack"` StabDefense int `yaml:"stab_defense"` SlashDefense int `yaml:"slash_defense"` CrushDefense int `yaml:"crush_defense"` ScienceDefense int `yaml:"science_defense"` RangedDefense int `yaml:"ranged_defense"` StrengthBonus int `yaml:"strength_bonus"` RangedStrength int `yaml:"ranged_strength"` ScienceDamage int `yaml:"science_damage"` TechnologyBonus int `yaml:"technology_bonus"` } func (d *ItemDef) MatchesName(input string) bool { lower := strings.ToLower(strings.TrimSpace(input)) if lower == "" { return false } if strings.ToLower(d.Name) == lower { return true } return WordPrefixMatch(lower, d.Name) }