aboutsummaryrefslogtreecommitdiff
path: root/internal/game
diff options
context:
space:
mode:
Diffstat (limited to 'internal/game')
-rw-r--r--internal/game/act_burn.go8
-rw-r--r--internal/game/act_clean.go12
-rw-r--r--internal/game/act_fletch.go8
-rw-r--r--internal/game/act_search.go10
-rw-r--r--internal/game/cmd_clean.go6
-rw-r--r--internal/game/cmd_craft.go6
-rw-r--r--internal/game/cmd_fletch.go10
-rw-r--r--internal/game/cmd_smelt.go2
-rw-r--r--internal/game/cmd_smith.go2
-rw-r--r--internal/game/cmd_stats.go14
-rw-r--r--internal/game/cmd_trigger_utility.go10
-rw-r--r--internal/game/cmd_use.go41
-rw-r--r--internal/game/cmd_verbs.go9
-rw-r--r--internal/game/cmd_wear.go18
-rw-r--r--internal/game/combat_attack.go32
-rw-r--r--internal/game/core_equip.go32
-rw-r--r--internal/game/core_production.go10
-rw-r--r--internal/game/look_target.go10
-rw-r--r--internal/game/production_engine.go32
-rw-r--r--internal/game/production_index.go30
-rw-r--r--internal/game/production_menu.go2
-rw-r--r--internal/game/sys_science.go6
-rw-r--r--internal/game/sys_technology.go2
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(&sectionObjs, &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(&sectionObjs, &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(&sectionObjs, &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