diff options
Diffstat (limited to 'internal/game')
| -rw-r--r-- | internal/game/act_burn.go | 8 | ||||
| -rw-r--r-- | internal/game/act_clean.go | 12 | ||||
| -rw-r--r-- | internal/game/act_fletch.go | 8 | ||||
| -rw-r--r-- | internal/game/act_search.go | 10 | ||||
| -rw-r--r-- | internal/game/cmd_clean.go | 6 | ||||
| -rw-r--r-- | internal/game/cmd_craft.go | 6 | ||||
| -rw-r--r-- | internal/game/cmd_fletch.go | 10 | ||||
| -rw-r--r-- | internal/game/cmd_smelt.go | 2 | ||||
| -rw-r--r-- | internal/game/cmd_smith.go | 2 | ||||
| -rw-r--r-- | internal/game/cmd_stats.go | 14 | ||||
| -rw-r--r-- | internal/game/cmd_trigger_utility.go | 10 | ||||
| -rw-r--r-- | internal/game/cmd_use.go | 41 | ||||
| -rw-r--r-- | internal/game/cmd_verbs.go | 9 | ||||
| -rw-r--r-- | internal/game/cmd_wear.go | 18 | ||||
| -rw-r--r-- | internal/game/combat_attack.go | 32 | ||||
| -rw-r--r-- | internal/game/core_equip.go | 32 | ||||
| -rw-r--r-- | internal/game/core_production.go | 10 | ||||
| -rw-r--r-- | internal/game/look_target.go | 10 | ||||
| -rw-r--r-- | internal/game/production_engine.go | 32 | ||||
| -rw-r--r-- | internal/game/production_index.go | 30 | ||||
| -rw-r--r-- | internal/game/production_menu.go | 2 | ||||
| -rw-r--r-- | internal/game/sys_science.go | 6 | ||||
| -rw-r--r-- | internal/game/sys_technology.go | 2 |
23 files changed, 172 insertions, 140 deletions
diff --git a/internal/game/act_burn.go b/internal/game/act_burn.go index 7420dff..c24d3d7 100644 --- a/internal/game/act_burn.go +++ b/internal/game/act_burn.go @@ -309,8 +309,8 @@ func (g *Game) findFireTool(sess *net.Session, p *player.Player) (toolSpeed floa if itemID, equipped := p.Equipment[item.SlotMainHand]; equipped { def, err := g.ItemStore.Load(itemID) - if err == nil && def.ToolType == "fire" { - toolSpeed = def.ToolSpeed + if err == nil && def.ToolType() == "fire" { + toolSpeed = def.ToolSpeed() toolItemID = itemID } } @@ -321,10 +321,10 @@ func (g *Game) findFireTool(sess *net.Session, p *player.Player) (toolSpeed floa continue } def, err := g.ItemStore.Load(slot.ItemID) - if err != nil || def.ToolType != "fire" { + if err != nil || def.ToolType() != "fire" { continue } - toolSpeed = def.ToolSpeed + toolSpeed = def.ToolSpeed() toolItemID = slot.ItemID break } diff --git a/internal/game/act_clean.go b/internal/game/act_clean.go index 0c128a1..021a07c 100644 --- a/internal/game/act_clean.go +++ b/internal/game/act_clean.go @@ -25,16 +25,16 @@ func (g *Game) advanceClean(sess *net.Session, p *player.Player) { return } - items := g.CraftIndex.ByType("clean") + items := g.CraftIndex.BySubtype("clean") var matchItem *item.ItemDef for _, item := range items { c := item.FirstCraft() if filter != "" { - if len(c.Consume) == 0 || len(c.Consume[0].Items) == 0 { + if len(c.Ingredients) == 0 || len(c.Ingredients[0].Items) == 0 { continue } - if !strings.Contains(c.Consume[0].Items[0], filter) && + if !strings.Contains(c.Ingredients[0].Items[0], filter) && !strings.Contains(item.ID, filter) { continue } @@ -56,7 +56,7 @@ func (g *Game) advanceClean(sess *net.Session, p *player.Player) { } craft := matchItem.FirstCraft() - consumeID := craft.Consume[0].Items[0] + consumeID := craft.Ingredients[0].Items[0] for i := 0; i < 28; i++ { slot := p.InvSlot(i) @@ -81,10 +81,10 @@ func (g *Game) advanceClean(sess *net.Session, p *player.Player) { for _, item := range items { c := item.FirstCraft() if filter != "" { - if len(c.Consume) == 0 || len(c.Consume[0].Items) == 0 { + if len(c.Ingredients) == 0 || len(c.Ingredients[0].Items) == 0 { continue } - if !strings.Contains(c.Consume[0].Items[0], filter) && + if !strings.Contains(c.Ingredients[0].Items[0], filter) && !strings.Contains(item.ID, filter) { continue } diff --git a/internal/game/act_fletch.go b/internal/game/act_fletch.go index e85f2c1..800bc8e 100644 --- a/internal/game/act_fletch.go +++ b/internal/game/act_fletch.go @@ -44,7 +44,7 @@ func (g *Game) doInstantFletch(sess *net.Session, p *player.Player, def *item.It for i := 0; i < 28; i++ { slot := p.InvSlot(i) if slot != nil && slot.ItemID == def.ID { - craftConsumeAll(c, p.HasItem, p.RemoveItem) + consumeIngredients(c, p.HasItem, p.RemoveItem) slot.Quantity += outputQty placed = true break @@ -52,7 +52,7 @@ func (g *Game) doInstantFletch(sess *net.Session, p *player.Player, def *item.It } } if !placed { - craftConsumeAll(c, p.HasItem, p.RemoveItem) + consumeIngredients(c, p.HasItem, p.RemoveItem) freeSlot := p.FirstFreeSlot() if freeSlot == -1 { break @@ -165,7 +165,7 @@ func (g *Game) advanceFletch(sess *net.Session, p *player.Player) { for i := 0; i < 28; i++ { slot := p.InvSlot(i) if slot != nil && slot.ItemID == def.ID { - craftConsumeAll(c, p.HasItem, p.RemoveItem) + consumeIngredients(c, p.HasItem, p.RemoveItem) slot.Quantity += outputQty placed = true break @@ -173,7 +173,7 @@ func (g *Game) advanceFletch(sess *net.Session, p *player.Player) { } } if !placed { - craftConsumeAll(c, p.HasItem, p.RemoveItem) + consumeIngredients(c, p.HasItem, p.RemoveItem) freeSlot := p.FirstFreeSlot() if freeSlot == -1 { sess.WriteLine("Your inventory is too full!") diff --git a/internal/game/act_search.go b/internal/game/act_search.go index 6f5fa65..83ea534 100644 --- a/internal/game/act_search.go +++ b/internal/game/act_search.go @@ -82,16 +82,6 @@ func (g *Game) advanceSearch(sess *net.Session, p *player.Player) { } } - if def.SearchMiscTable != "" { - dt2, err := behavior.LoadDropTable(g.DataDir, def.SearchMiscTable) - if err == nil && len(dt2.Drops) > 0 { - drop := behavior.ResolveDrop(g.DataDir, dt2.Drops) - if drop != nil && drop.ItemID != "" { - g.giveSearchLoot(sess, p, drop) - } - } - } - g.AccountStore.SaveCharacter(p) g.cancelAction(p) } diff --git a/internal/game/cmd_clean.go b/internal/game/cmd_clean.go index a43295a..f77ff57 100644 --- a/internal/game/cmd_clean.go +++ b/internal/game/cmd_clean.go @@ -22,7 +22,7 @@ func (g *Game) doClean(sess *net.Session, input string) { return } - items := g.CraftIndex.ByType("clean") + items := g.CraftIndex.BySubtype("clean") filter := strings.TrimSpace(input) @@ -78,8 +78,8 @@ func (g *Game) doClean(sess *net.Session, input string) { } func matchesCleanFilter(item *item.ItemDef, filter string) bool { - if len(item.Craft) > 0 && len(item.FirstCraft().Consume) > 0 && len(item.FirstCraft().Consume[0].Items) > 0 { - if strings.Contains(item.FirstCraft().Consume[0].Items[0], filter) { + if len(item.Craft) > 0 && len(item.FirstCraft().Ingredients) > 0 && len(item.FirstCraft().Ingredients[0].Items) > 0 { + if strings.Contains(item.FirstCraft().Ingredients[0].Items[0], filter) { return true } } diff --git a/internal/game/cmd_craft.go b/internal/game/cmd_craft.go index 0fe3d5b..3d23f85 100644 --- a/internal/game/cmd_craft.go +++ b/internal/game/cmd_craft.go @@ -171,7 +171,7 @@ func (g *Game) startItem(sess *net.Session, p *player.Player, def *item.ItemDef, } func (g *Game) hasGrimyHerbs(p *player.Player) bool { - items := g.CraftIndex.ByType("clean") + items := g.CraftIndex.BySubtype("clean") for _, def := range items { if def.FindCraft(func(c item.CraftDef) bool { return craftHasAllItems(&c, p.HasItem) @@ -188,10 +188,10 @@ func (g *Game) findCraftItems(p *player.Player, itemAID, itemBID string) []*item toolTypeA := "" toolTypeB := "" if defA, _ := g.ItemStore.Load(itemAID); defA != nil { - toolTypeA = defA.ToolType + toolTypeA = defA.ToolType() } if defB, _ := g.ItemStore.Load(itemBID); defB != nil { - toolTypeB = defB.ToolType + toolTypeB = defB.ToolType() } var matched []*item.ItemDef diff --git a/internal/game/cmd_fletch.go b/internal/game/cmd_fletch.go index 0da8129..d638bc0 100644 --- a/internal/game/cmd_fletch.go +++ b/internal/game/cmd_fletch.go @@ -28,7 +28,7 @@ func fletchNeedsKnife(def *item.ItemDef) bool { if c.Tool == "knife" { return true } - for _, e := range c.Consume { + for _, e := range c.Ingredients { for _, id := range e.Items { if fletchLogItems[id] { if strings.Contains(def.ID, "shaft") || strings.Contains(def.ID, "bow") { @@ -46,7 +46,7 @@ func fletchNeedsChisel(def *item.ItemDef) bool { if c.Tool == "chisel" { return true } - for _, e := range c.Consume { + for _, e := range c.Ingredients { for _, id := range e.Items { if fletchGemItems[id] { return true @@ -179,10 +179,10 @@ func (g *Game) findFletchItems(p *player.Player, itemAID, itemBID string) []*ite toolTypeA := "" toolTypeB := "" if defA, _ := g.ItemStore.Load(itemAID); defA != nil { - toolTypeA = defA.ToolType + toolTypeA = defA.ToolType() } if defB, _ := g.ItemStore.Load(itemBID); defB != nil { - toolTypeB = defB.ToolType + toolTypeB = defB.ToolType() } isToolA := toolTypeA == "knife" || toolTypeA == "chisel" isToolB := toolTypeB == "knife" || toolTypeB == "chisel" @@ -204,7 +204,7 @@ func (g *Game) findFletchItems(p *player.Player, itemAID, itemBID string) []*ite aMatch := false bMatch := false - for _, e := range c.Consume { + for _, e := range c.Ingredients { for _, id := range e.Items { if id == itemAID { aMatch = true diff --git a/internal/game/cmd_smelt.go b/internal/game/cmd_smelt.go index 59e52db..b551e76 100644 --- a/internal/game/cmd_smelt.go +++ b/internal/game/cmd_smelt.go @@ -23,7 +23,7 @@ func (g *Game) doSmelt(sess *net.Session, input string) { return } - items := g.CraftIndex.ByType("smelting") + items := g.CraftIndex.BySubtype("smelt") if input == "" { g.showSmeltMenu(sess, p, items, stationDefID, stationName) diff --git a/internal/game/cmd_smith.go b/internal/game/cmd_smith.go index 9722896..4330b1d 100644 --- a/internal/game/cmd_smith.go +++ b/internal/game/cmd_smith.go @@ -118,7 +118,7 @@ func hasSmithingItems(items []*item.ItemDef, barID string) bool { func findSmithableBars(items []*item.ItemDef, p *player.Player) []string { barSet := make(map[string]bool) for _, item := range items { - for _, e := range item.FirstCraft().Consume { + for _, e := range item.FirstCraft().Ingredients { for _, id := range e.Items { if p.HasItem(id) { barSet[id] = true diff --git a/internal/game/cmd_stats.go b/internal/game/cmd_stats.go index ef5e2ba..0430c6e 100644 --- a/internal/game/cmd_stats.go +++ b/internal/game/cmd_stats.go @@ -19,18 +19,18 @@ func (g *Game) doStats(sess *net.Session) { attackType := "crush" weaponName := "unarmed" - var weaponType item.WeaponType + var weaponType item.EquipmentType var weaponDef *item.ItemDef if itemID, ok := p.Equipment[item.SlotMainHand]; ok { if def, err := g.ItemStore.Load(itemID); err == nil { weaponDef = def weaponName = def.Name - weaponType = def.WeaponType - if def.AttackType != "" { - attackType = def.AttackType - } else if def.WeaponType == item.WeaponRanged { + weaponType = def.EquipmentType() + if def.AttackType() != "" { + attackType = def.AttackType() + } else if def.EquipmentType() == item.EquipRangedWeapon { attackType = "ranged" - } else if def.WeaponType == item.WeaponScience { + } else if def.EquipmentType() == item.EquipScienceWeapon { attackType = "science" } } @@ -58,7 +58,7 @@ func (g *Game) doStats(sess *net.Session) { ) var attRoll, maxHitVal int - if weaponType == item.WeaponRanged { + if weaponType == item.EquipRangedWeapon { rangedBonus, _ := combat.RangedStyleBonus(string(p.AttackStyle)) attRoll = combat.EffectiveRoll(p.Level(player.Ranged), rangedBonus, totals.RangedAttack) maxHitVal = combat.MaxHit(p.Level(player.Ranged), rangedBonus, totals.RangedStrength) diff --git a/internal/game/cmd_trigger_utility.go b/internal/game/cmd_trigger_utility.go index 0dae505..1697417 100644 --- a/internal/game/cmd_trigger_utility.go +++ b/internal/game/cmd_trigger_utility.go @@ -170,7 +170,7 @@ func (g *Game) triggerSuperheat(sess *net.Session, p *player.Player, mod *ModDef } var match *item.ItemDef - for _, item := range g.CraftIndex.ByType("smelting") { + for _, item := range g.CraftIndex.BySubtype("smelt") { if craftMatchesEntry(item.FirstCraft(), inv.ItemID) { match = item break @@ -182,12 +182,12 @@ func (g *Game) triggerSuperheat(sess *net.Session, p *player.Player, mod *ModDef } c := match.FirstCraft() - if c.Level > 0 && p.Level(player.SkillName(c.Skill)) < c.Level { - sess.WriteLine(fmt.Sprintf("You need level %d %s to smelt that.", c.Level, c.Skill)) + if c.Level > 0 && p.Level(player.SkillName(c.Type)) < c.Level { + sess.WriteLine(fmt.Sprintf("You need level %d %s to smelt that.", c.Level, c.Type)) return } - for _, e := range c.Consume { + for _, e := range c.Ingredients { for _, itemID := range e.Items { qty := e.Quantity if qty <= 0 { @@ -209,7 +209,7 @@ func (g *Game) triggerSuperheat(sess *net.Session, p *player.Player, mod *ModDef g.cancelAction(p) } - craftConsumeAll(c, p.HasItem, p.RemoveItem) + consumeIngredients(c, p.HasItem, p.RemoveItem) outputQty := c.OutputQty if outputQty <= 0 { diff --git a/internal/game/cmd_use.go b/internal/game/cmd_use.go index d399e8f..033fd62 100644 --- a/internal/game/cmd_use.go +++ b/internal/game/cmd_use.go @@ -137,6 +137,19 @@ func (g *Game) stationRecipes(p *player.Player, stationDefID string) []*item.Ite return results } +func craftLabel(c *item.CraftDef) string { + if c == nil { + return "" + } + if c.Subtype != "" { + return c.Subtype + } + if c.Type != "" { + return c.Type + } + return "combine" +} + func (g *Game) showRecipeMenu(sess *net.Session, p *player.Player, items []*item.ItemDef, stationName string) { if len(items) == 0 { sess.WriteLine(fmt.Sprintf("You don't have anything you can make at the %s.", stationName)) @@ -149,7 +162,7 @@ func (g *Game) showRecipeMenu(sess *net.Session, p *player.Player, items []*item needTypes := false for i := range items { for j := i + 1; j < len(items); j++ { - if len(items[i].Craft) > 0 && len(items[j].Craft) > 0 && items[i].FirstCraft().Type != items[j].FirstCraft().Type { + if craftLabel(items[i].FirstCraft()) != craftLabel(items[j].FirstCraft()) { needTypes = true break } @@ -163,14 +176,8 @@ func (g *Game) showRecipeMenu(sess *net.Session, p *player.Player, items []*item sess.State = net.StateRecipeChoice var names []string for _, item := range items { - cType := "" - if len(item.Craft) > 0 { - cType = item.FirstCraft().Type - } - if cType == "" { - cType = "combine" - } - typeLabel := strings.ToUpper(cType[:1]) + cType[1:] + label := craftLabel(item.FirstCraft()) + typeLabel := strings.ToUpper(label[:1]) + label[1:] if needTypes { names = append(names, fmt.Sprintf("%s (%s)", g.itemName(sess, item), typeLabel)) } else { @@ -209,15 +216,15 @@ func (g *Game) doUseItemOnTarget(sess *net.Session, p *player.Player, itemAName, recipes := g.CraftIndex.FindByStationInput(def.ID, itemAID) if len(recipes) > 0 { - cType := "" + var firstSubtype string if len(recipes[0].Craft) > 0 { - cType = recipes[0].FirstCraft().Type + firstSubtype = recipes[0].FirstCraft().Subtype } - if cType == "smelting" { + if firstSubtype == "smelt" { var filtered []*item.ItemDef for _, item := range recipes { c := item.FirstCraft() - if c.Type != "smelting" { + if c.Subtype != "smelt" { continue } if !craftHasAllItemsQty(c, p.CountItem) { @@ -246,6 +253,10 @@ func (g *Game) doUseItemOnTarget(sess *net.Session, p *player.Player, itemAName, g.showMenuTable(sess, "What would you like to smelt?", names) return } + var cType string + if len(recipes[0].Craft) > 0 { + cType = recipes[0].FirstCraft().Type + } if cType == "smithing" { if !g.hasToolType(p, "hammer") { sess.WriteLine("You need a hammer to smith.") @@ -396,9 +407,9 @@ func (g *Game) doUseItemOnTarget(sess *net.Session, p *player.Player, itemAName, } func (g *Game) isGrimyHerb(itemID string) bool { - items := g.CraftIndex.ByType("clean") + items := g.CraftIndex.BySubtype("clean") for _, item := range items { - for _, e := range item.FirstCraft().Consume { + for _, e := range item.FirstCraft().Ingredients { for _, id := range e.Items { if id == itemID { return true diff --git a/internal/game/cmd_verbs.go b/internal/game/cmd_verbs.go index 70b2fb2..cad90c5 100644 --- a/internal/game/cmd_verbs.go +++ b/internal/game/cmd_verbs.go @@ -90,12 +90,17 @@ func (g *Game) executeVerbs(sess *net.Session, args []string, rawInput string) { if len(recipes) > 0 { addUnique(§ionObjs, &seen, "use "+name) for _, r := range recipes { - if info, ok := productionTypes[r.FirstCraft().Type]; ok { + c := r.FirstCraft() + key := c.Subtype + if key == "" { + key = c.Type + } + if info, ok := productionTypes[key]; ok { if info.ActionType != behavior.TypeCombine && info.ActionType != behavior.TypeFletch && info.ActionType != behavior.TypeMix { addUnique(§ionObjs, &seen, string(info.ActionType)) } } - for _, c := range r.FirstCraft().Consume { + for _, c := range r.FirstCraft().Ingredients { for _, itemID := range c.Items { if itemDef, err := g.ItemStore.Load(itemID); err == nil { addUnique(§ionObjs, &seen, "use "+itemDef.Name+" on "+name) diff --git a/internal/game/cmd_wear.go b/internal/game/cmd_wear.go index 64069bc..c52321c 100644 --- a/internal/game/cmd_wear.go +++ b/internal/game/cmd_wear.go @@ -75,7 +75,7 @@ func (g *Game) doWear(sess *net.Session, input string) { } def, err := g.ItemStore.Load(slot.ItemID) - if err != nil || def.EquipSlot == "" { + if err != nil || def.EquipSlot() == "" { sess.WriteLine(fmt.Sprintf("You can't wear %s.", g.itemColorize(sess, def, match.Name))) return } @@ -85,12 +85,12 @@ func (g *Game) doWear(sess *net.Session, input string) { return } - if def.EquipSlot == item.SlotAmmo && def.Stackable { + if def.EquipSlot() == item.SlotAmmo && def.Stackable { g.equipAmmo(sess, p, match.Slot, slot, def, qty) return } - existingItemID, slotOccupied := p.Equipment[def.EquipSlot] + existingItemID, slotOccupied := p.Equipment[def.EquipSlot()] if slotOccupied { freeSlot := p.FirstFreeSlot() @@ -116,11 +116,11 @@ func (g *Game) doWear(sess *net.Session, input string) { p.EquipQuality[slot.ItemID] = slot.Quality } - p.Equipment[def.EquipSlot] = slot.ItemID + p.Equipment[def.EquipSlot()] = slot.ItemID g.AccountStore.SaveCharacter(p) verb := "wear" - if def.WeaponType != "" { + if def.EquipmentType() != "" { verb = "wield" } sess.WriteLine(fmt.Sprintf("You %s %s.", verb, g.itemColorize(sess, def, match.Name))) @@ -193,19 +193,19 @@ func (g *Game) doWearAll(sess *net.Session) { continue } def, err := g.ItemStore.Load(slot.ItemID) - if err != nil || def.EquipSlot == "" { + if err != nil || def.EquipSlot() == "" { continue } if g.checkRequirements(sess, p, def) != "" { continue } - current, exists := bestPerSlot[def.EquipSlot] + current, exists := bestPerSlot[def.EquipSlot()] val := def.Value - if def.EquipSlot == item.SlotAmmo && def.Stackable { + if def.EquipSlot() == item.SlotAmmo && def.Stackable { val = def.Value * slot.Quantity } if !exists || val > current.value { - bestPerSlot[def.EquipSlot] = struct { + bestPerSlot[def.EquipSlot()] = struct { itemID string value int invSlot int diff --git a/internal/game/combat_attack.go b/internal/game/combat_attack.go index bae210b..ddc3b8f 100644 --- a/internal/game/combat_attack.go +++ b/internal/game/combat_attack.go @@ -59,7 +59,7 @@ func (g *Game) doAttack(sess *net.Session, input string) { } if itemID, ok := p.Equipment[item.SlotMainHand]; ok { - if def, err := g.ItemStore.Load(itemID); err == nil && def.WeaponType == item.WeaponRanged { + if def, err := g.ItemStore.Load(itemID); err == nil && def.EquipmentType() == item.EquipRangedWeapon { if _, hasAmmo := p.Equipment[item.SlotAmmo]; !hasAmmo || p.AmmoQty <= 0 { sess.WriteLine("You don't have any ammo equipped.") return @@ -289,23 +289,23 @@ func (g *Game) playerAttack(sess *net.Session, p *player.Player, mob *world.MobI } } -func (g *Game) calculatePlayerAttackRoll(p *player.Player, mob *world.MobInstance) (attackType string, weaponType item.WeaponType, attRoll int, defRoll int, maxHit int) { +func (g *Game) calculatePlayerAttackRoll(p *player.Player, mob *world.MobInstance) (attackType string, weaponType item.EquipmentType, attRoll int, defRoll int, maxHit int) { attackType = "crush" if itemID, ok := p.Equipment[item.SlotMainHand]; ok { if def, err := g.ItemStore.Load(itemID); err == nil { - if def.AttackType != "" { - attackType = def.AttackType - } else if def.WeaponType == item.WeaponRanged { + if def.AttackType() != "" { + attackType = def.AttackType() + } else if def.EquipmentType() == item.EquipRangedWeapon { attackType = "ranged" - } else if def.WeaponType == item.WeaponScience { + } else if def.EquipmentType() == item.EquipScienceWeapon { attackType = "science" } - weaponType = def.WeaponType + weaponType = def.EquipmentType() } } totals := g.playerEquipBonuses(p) - isRanged := weaponType == item.WeaponRanged + isRanged := weaponType == item.EquipRangedWeapon if isRanged { rangedBonus, _ := combat.RangedStyleBonus(string(p.AttackStyle)) @@ -343,15 +343,15 @@ func (g *Game) playerAttackUnarmed(sess *net.Session, p *player.Player, mob *wor attackType, _, attRoll, defRoll, maxHit := g.calculateUnarmedAttackRoll(p, mob) if combat.HitCheck(attRoll, defRoll) { - g.applyPlayerHit(sess, p, mob, attackType, item.WeaponMelee, maxHit) + g.applyPlayerHit(sess, p, mob, attackType, item.EquipMeleeWeapon, maxHit) } else { - g.applyPlayerMiss(sess, p, mob, item.WeaponMelee) + g.applyPlayerMiss(sess, p, mob, item.EquipMeleeWeapon) } } -func (g *Game) calculateUnarmedAttackRoll(p *player.Player, mob *world.MobInstance) (attackType string, weaponType item.WeaponType, attRoll int, defRoll int, maxHit int) { +func (g *Game) calculateUnarmedAttackRoll(p *player.Player, mob *world.MobInstance) (attackType string, weaponType item.EquipmentType, attRoll int, defRoll int, maxHit int) { attackType = "crush" - weaponType = item.WeaponMelee + weaponType = item.EquipMeleeWeapon attBonus, strBonus, _ := combat.AttackStyleBonus(string(p.AttackStyle)) effectiveAccuracy := p.Level(player.Accuracy) + g.techLevelBonus(p, "accuracy") + g.buffLevelBonus(p, "accuracy") @@ -365,7 +365,7 @@ func (g *Game) calculateUnarmedAttackRoll(p *player.Player, mob *world.MobInstan return } -func (g *Game) applyPlayerHit(sess *net.Session, p *player.Player, mob *world.MobInstance, attackType string, weaponType item.WeaponType, maxHit int) { +func (g *Game) applyPlayerHit(sess *net.Session, p *player.Player, mob *world.MobInstance, attackType string, weaponType item.EquipmentType, maxHit int) { dmg := combat.RollDamage(maxHit) mob.HP -= dmg @@ -390,7 +390,7 @@ func (g *Game) applyPlayerHit(sess *net.Session, p *player.Player, mob *world.Mo mobDisplayName(mob, false), fbName))) } - isRanged := weaponType == item.WeaponRanged + isRanged := weaponType == item.EquipRangedWeapon gains := g.awardCombatXP(sess, p, dmg, isRanged) if isRanged { @@ -425,10 +425,10 @@ func (g *Game) applyPlayerHit(sess *net.Session, p *player.Player, mob *world.Mo } } -func (g *Game) applyPlayerMiss(sess *net.Session, p *player.Player, mob *world.MobInstance, weaponType item.WeaponType) { +func (g *Game) applyPlayerMiss(sess *net.Session, p *player.Player, mob *world.MobInstance, weaponType item.EquipmentType) { sess.WriteLine(g.colorize(sess, "miss", fmt.Sprintf("You miss %s.", mobDisplayName(mob, true)))) - if weaponType == item.WeaponRanged { + if weaponType == item.EquipRangedWeapon { g.consumeAmmo(sess, p) if p.AmmoQty <= 0 { sess.WriteLine("You've run out of ammo!") diff --git a/internal/game/core_equip.go b/internal/game/core_equip.go index cc8016d..a297466 100644 --- a/internal/game/core_equip.go +++ b/internal/game/core_equip.go @@ -12,20 +12,20 @@ func (g *Game) playerEquipBonuses(p *player.Player) item.ItemStats { if err != nil { continue } - totals.StabAttack += def.Stats.StabAttack - totals.SlashAttack += def.Stats.SlashAttack - totals.CrushAttack += def.Stats.CrushAttack - totals.ScienceAttack += def.Stats.ScienceAttack - totals.RangedAttack += def.Stats.RangedAttack - totals.StabDefense += def.Stats.StabDefense - totals.SlashDefense += def.Stats.SlashDefense - totals.CrushDefense += def.Stats.CrushDefense - totals.ScienceDefense += def.Stats.ScienceDefense - totals.RangedDefense += def.Stats.RangedDefense - totals.StrengthBonus += def.Stats.StrengthBonus - totals.RangedStrength += def.Stats.RangedStrength - totals.ScienceDamage += def.Stats.ScienceDamage - totals.TechnologyBonus += def.Stats.TechnologyBonus + totals.StabAttack += def.Stats().StabAttack + totals.SlashAttack += def.Stats().SlashAttack + totals.CrushAttack += def.Stats().CrushAttack + totals.ScienceAttack += def.Stats().ScienceAttack + totals.RangedAttack += def.Stats().RangedAttack + totals.StabDefense += def.Stats().StabDefense + totals.SlashDefense += def.Stats().SlashDefense + totals.CrushDefense += def.Stats().CrushDefense + totals.ScienceDefense += def.Stats().ScienceDefense + totals.RangedDefense += def.Stats().RangedDefense + totals.StrengthBonus += def.Stats().StrengthBonus + totals.RangedStrength += def.Stats().RangedStrength + totals.ScienceDamage += def.Stats().ScienceDamage + totals.TechnologyBonus += def.Stats().TechnologyBonus } return totals } @@ -33,8 +33,8 @@ func (g *Game) playerEquipBonuses(p *player.Player) item.ItemStats { func (g *Game) playerWeaponSpeed(p *player.Player) float64 { if itemID, ok := p.Equipment[item.SlotMainHand]; ok { def, err := g.ItemStore.Load(itemID) - if err == nil && def.Speed > 0 { - return def.Speed + if err == nil && def.Speed()> 0 { + return def.Speed() } } return 5.0 diff --git a/internal/game/core_production.go b/internal/game/core_production.go index 8a38f36..da9466f 100644 --- a/internal/game/core_production.go +++ b/internal/game/core_production.go @@ -11,8 +11,8 @@ func (g *Game) findTool(p *player.Player, toolTypes []string) (toolSpeed float64 if itemID, ok := p.Equipment[item.SlotMainHand]; ok { if def, err := g.ItemStore.Load(itemID); err == nil { for _, t := range toolTypes { - if def.ToolType == t { - return def.ToolSpeed, def.Name, true + if def.ToolType() == t { + return def.ToolSpeed(), def.Name, true } } } @@ -27,8 +27,8 @@ func (g *Game) findTool(p *player.Player, toolTypes []string) (toolSpeed float64 continue } for _, t := range toolTypes { - if def.ToolType == t { - return def.ToolSpeed, def.Name, true + if def.ToolType() == t { + return def.ToolSpeed(), def.Name, true } } } @@ -58,7 +58,7 @@ var productionTypes = map[string]productionTypeInfo{ EndMessage: "You've finished cooking.", FailMessage: "You accidentally burn the %i1.", }, - "smelting": { + "smelt": { ActionType: behavior.TypeSmelt, DisplayVerb: "smelting", StartMessage: "You place the %i1 into the furnace.", diff --git a/internal/game/look_target.go b/internal/game/look_target.go index 915e4a7..a93d969 100644 --- a/internal/game/look_target.go +++ b/internal/game/look_target.go @@ -311,7 +311,7 @@ func showPlayerInfo(g *Game, sess *net.Session, p *player.Player) { } func (g *Game) showItemStats(sess *net.Session, def *item.ItemDef) { - s := def.Stats + s := def.Stats() hasAttack := s.StabAttack != 0 || s.SlashAttack != 0 || s.CrushAttack != 0 || s.ScienceAttack != 0 || s.RangedAttack != 0 hasDefense := s.StabDefense != 0 || s.SlashDefense != 0 || s.CrushDefense != 0 || @@ -348,11 +348,11 @@ func (g *Game) showItemStats(sess *net.Session, def *item.ItemDef) { sess.WriteLine(fmt.Sprintf(" Technology: %+d", s.TechnologyBonus)) } } - if def.AttackType != "" { - sess.WriteLine(fmt.Sprintf("Attack type: %s", def.AttackType)) + if def.AttackType() != "" { + sess.WriteLine(fmt.Sprintf("Attack type: %s", def.AttackType())) } - if def.Speed > 0 { - sess.WriteLine(fmt.Sprintf("Speed: %.0f", def.Speed)) + if def.Speed()> 0 { + sess.WriteLine(fmt.Sprintf("Speed: %.0f", def.Speed())) } if len(def.Requirements) > 0 { sess.WriteLine("") diff --git a/internal/game/production_engine.go b/internal/game/production_engine.go index c30e7bb..048e152 100644 --- a/internal/game/production_engine.go +++ b/internal/game/production_engine.go @@ -25,7 +25,7 @@ func (g *Game) resolveCraftVar(sess *net.Session, varSpec string, craft *item.Cr } varSpec = strings.ReplaceAll(varSpec, "%n", outputName) - for i, e := range craft.Consume { + for i, e := range craft.Ingredients { key := fmt.Sprintf("%%i%d", i+1) if !strings.Contains(varSpec, key) { continue @@ -134,14 +134,19 @@ func (g *Game) startProductionFromItem(sess *net.Session, p *player.Player, item stationName = "inventory" } - info, ok := productionTypes[craft.Type] + cKey := craft.Subtype + if cKey == "" { + cKey = craft.Type + } + + info, ok := productionTypes[cKey] if !ok { info = productionTypeInfo{ - ActionType: behavior.ActionType(craft.Type), - DisplayVerb: craft.Type, - StartMessage: "You start " + craft.Type + " %i1.", + ActionType: behavior.ActionType(cKey), + DisplayVerb: cKey, + StartMessage: "You start " + cKey + " %i1.", SuccessMessage: "You produce %n.", - EndMessage: "You've finished " + craft.Type + ".", + EndMessage: "You've finished " + cKey + ".", } } @@ -215,7 +220,12 @@ func (g *Game) advanceProduction(sess *net.Session, p *player.Player) bool { chance = behavior.SuccessChance(behavior.SuccessFormula(*craft.Success), skillLevel, craft.Level) } - info, _ := productionTypes[craft.Type] + cKey := craft.Subtype + if cKey == "" { + cKey = craft.Type + } + + info, _ := productionTypes[cKey] if rand.Float64() < chance { outputQty := craft.OutputQty @@ -231,7 +241,7 @@ func (g *Game) advanceProduction(sess *net.Session, p *player.Player) bool { for i := 0; i < 28; i++ { slot := p.InvSlot(i) if slot != nil && slot.ItemID == item.ID { - craftConsumeAll(craft, p.HasItem, p.RemoveItem) + consumeIngredients(craft, p.HasItem, p.RemoveItem) slot.Quantity += outputQty placed = true break @@ -239,7 +249,7 @@ func (g *Game) advanceProduction(sess *net.Session, p *player.Player) bool { } } if !placed { - craftConsumeAll(craft, p.HasItem, p.RemoveItem) + consumeIngredients(craft, p.HasItem, p.RemoveItem) freeSlot := p.FirstFreeSlot() if freeSlot == -1 { sess.WriteLine("Your inventory is too full!") @@ -274,7 +284,7 @@ func (g *Game) advanceProduction(sess *net.Session, p *player.Player) bool { } sess.WriteLine(msg) } else { - craftConsumeAll(craft, p.HasItem, p.RemoveItem) + consumeIngredients(craft, p.HasItem, p.RemoveItem) if craft.Fail != "" { freeSlot := p.FirstFreeSlot() @@ -320,7 +330,7 @@ func (g *Game) collectByproducts(p *player.Player, item *item.ItemDef) []string return nil } var byproducts []string - for _, e := range craft.Consume { + for _, e := range craft.Ingredients { if len(e.Byproducts) == 0 { continue } diff --git a/internal/game/production_index.go b/internal/game/production_index.go index 648ccc8..77fc08a 100644 --- a/internal/game/production_index.go +++ b/internal/game/production_index.go @@ -9,6 +9,7 @@ import ( type CraftIndex struct { mu sync.RWMutex byType map[string][]*item.ItemDef + bySubtype map[string][]*item.ItemDef byInput map[string][]*item.ItemDef byStation map[string][]*item.ItemDef } @@ -16,6 +17,7 @@ type CraftIndex struct { func NewCraftIndex() *CraftIndex { return &CraftIndex{ byType: make(map[string][]*item.ItemDef), + bySubtype: make(map[string][]*item.ItemDef), byInput: make(map[string][]*item.ItemDef), byStation: make(map[string][]*item.ItemDef), } @@ -26,6 +28,7 @@ func (idx *CraftIndex) Build(items []*item.ItemDef) { defer idx.mu.Unlock() idx.byType = make(map[string][]*item.ItemDef) + idx.bySubtype = make(map[string][]*item.ItemDef) idx.byInput = make(map[string][]*item.ItemDef) idx.byStation = make(map[string][]*item.ItemDef) @@ -41,7 +44,11 @@ func (idx *CraftIndex) Build(items []*item.ItemDef) { } idx.byType[t] = appendUnique(idx.byType[t], def) - for _, e := range craft.Consume { + if craft.Subtype != "" { + idx.bySubtype[craft.Subtype] = appendUnique(idx.bySubtype[craft.Subtype], def) + } + + for _, e := range craft.Ingredients { for _, id := range e.Items { idx.byInput[id] = appendUnique(idx.byInput[id], def) } @@ -72,6 +79,15 @@ func (idx *CraftIndex) ByType(craftType string) []*item.ItemDef { return out } +func (idx *CraftIndex) BySubtype(subtype string) []*item.ItemDef { + idx.mu.RLock() + defer idx.mu.RUnlock() + items := idx.bySubtype[subtype] + out := make([]*item.ItemDef, len(items)) + copy(out, items) + return out +} + func (idx *CraftIndex) ByStation(stationDefID string) []*item.ItemDef { idx.mu.RLock() defer idx.mu.RUnlock() @@ -147,7 +163,7 @@ func craftEntryFor(def *item.ItemDef, itemID string) int { } func craftEntry(craft item.CraftDef, itemID string) int { - for ei, e := range craft.Consume { + for ei, e := range craft.Ingredients { for _, id := range e.Items { if id == itemID { return ei @@ -161,7 +177,7 @@ func craftMatchesEntry(c *item.CraftDef, itemID string) bool { if c == nil { return false } - for _, e := range c.Consume { + for _, e := range c.Ingredients { for _, id := range e.Items { if id == itemID { return true @@ -175,7 +191,7 @@ func craftHasAllItems(c *item.CraftDef, hasItem func(string) bool) bool { if c == nil { return false } - for _, e := range c.Consume { + for _, e := range c.Ingredients { found := false for _, id := range e.Items { if hasItem(id) { @@ -194,7 +210,7 @@ func craftHasAllItemsQty(c *item.CraftDef, countItem func(string) int) bool { if c == nil { return false } - for _, e := range c.Consume { + for _, e := range c.Ingredients { found := false for _, id := range e.Items { qty := e.Quantity @@ -213,11 +229,11 @@ func craftHasAllItemsQty(c *item.CraftDef, countItem func(string) int) bool { return true } -func craftConsumeAll(c *item.CraftDef, hasItem func(string) bool, removeItem func(string, int) bool) bool { +func consumeIngredients(c *item.CraftDef, hasItem func(string) bool, removeItem func(string, int) bool) bool { if c == nil { return false } - for _, e := range c.Consume { + for _, e := range c.Ingredients { found := false for _, id := range e.Items { if hasItem(id) { diff --git a/internal/game/production_menu.go b/internal/game/production_menu.go index bc2fccc..ff9fc51 100644 --- a/internal/game/production_menu.go +++ b/internal/game/production_menu.go @@ -106,7 +106,7 @@ func (g *Game) formatMaterials(sess *net.Session, item *item.ItemDef) string { return "" } var parts []string - for _, e := range craft.Consume { + for _, e := range craft.Ingredients { itemName := e.Items[0] if def, err := g.ItemStore.Load(e.Items[0]); err == nil { itemName = g.itemColorize(sess, def, def.Name) diff --git a/internal/game/sys_science.go b/internal/game/sys_science.go index b04072f..bded8c4 100644 --- a/internal/game/sys_science.go +++ b/internal/game/sys_science.go @@ -182,7 +182,7 @@ func (g *Game) hasDeckEquipped(p *player.Player) bool { if err != nil { return false } - return def.WeaponType == item.WeaponScience + return def.EquipmentType() == item.EquipScienceWeapon } func (g *Game) providesJunk(p *player.Player) string { @@ -194,7 +194,7 @@ func (g *Game) providesJunk(p *player.Player) string { if err != nil { return "" } - return def.ProvidesJunk + return def.ProvidesJunk() } func (g *Game) effectiveJunkCost(p *player.Player, mod *ModDef) map[string]int { @@ -296,7 +296,7 @@ func (g *Game) totalScienceAttack(p *player.Player) int { for _, itemID := range p.Equipment { def, err := g.ItemStore.Load(itemID) if err == nil { - total += def.Stats.ScienceAttack + total += def.Stats().ScienceAttack } } return total diff --git a/internal/game/sys_technology.go b/internal/game/sys_technology.go index 7df68d4..9e6a635 100644 --- a/internal/game/sys_technology.go +++ b/internal/game/sys_technology.go @@ -128,7 +128,7 @@ func (g *Game) totalTechBonus(p *player.Player) int { for _, itemID := range p.Equipment { def, err := g.ItemStore.Load(itemID) if err == nil { - total += def.Stats.TechnologyBonus + total += def.Stats().TechnologyBonus } } return total |
