aboutsummaryrefslogtreecommitdiff
path: root/internal/game/act_fletch.go
diff options
context:
space:
mode:
authorhistoria <[not public]>2026-06-25 15:40:48 -0400
committerhistoria <[not public]>2026-06-25 15:40:48 -0400
commitabd612c15799f604e671e83dc7c410ed2b44185f (patch)
tree0597ca92350de73aac2a7cf26b2f2d6595dac0cc /internal/game/act_fletch.go
parent2725e2927a1595c7b100d942d1f14146252adeb7 (diff)
downloadthehouseoficarus-abd612c15799f604e671e83dc7c410ed2b44185f.tar.gz
slop refactor
Diffstat (limited to 'internal/game/act_fletch.go')
-rw-r--r--internal/game/act_fletch.go214
1 files changed, 214 insertions, 0 deletions
diff --git a/internal/game/act_fletch.go b/internal/game/act_fletch.go
new file mode 100644
index 0000000..78a19ad
--- /dev/null
+++ b/internal/game/act_fletch.go
@@ -0,0 +1,214 @@
+package game
+
+import (
+ "fmt"
+
+ "thehouseoficarus/internal/behavior"
+ "thehouseoficarus/internal/engine"
+ "thehouseoficarus/internal/item"
+ "thehouseoficarus/internal/net"
+ "thehouseoficarus/internal/player"
+)
+
+func (g *Game) startFletchAction(sess *net.Session, p *player.Player, def *item.ItemDef, count int) {
+ p.EnsureFlags()
+ p.Flags["last_fletch"] = def.ID
+ g.AccountStore.SaveCharacter(p)
+
+ if def.FirstCraft().Wait <= 0 {
+ g.doInstantFletch(sess, p, def, count)
+ return
+ }
+
+ g.startTimedFletch(sess, p, def, count)
+}
+
+func (g *Game) doInstantFletch(sess *net.Session, p *player.Player, def *item.ItemDef, count int) {
+ c := def.FirstCraft()
+ outputQty := c.OutputQty
+ if outputQty <= 0 {
+ outputQty = 1
+ }
+
+ batches := 0
+ totalOutput := 0
+ skill := player.SkillName(c.EffectiveSkill())
+ tmpItem := &item.ItemDef{Craft: item.CraftList{*c}}
+ for {
+ if !g.canDoFletchItem(p, tmpItem) {
+ break
+ }
+
+ placed := false
+ if def.Stackable {
+ for i := 0; i < 28; i++ {
+ slot := p.InvSlot(i)
+ if slot != nil && slot.ItemID == def.ID {
+ craftConsumeAll(c, p.HasItem, p.RemoveItem)
+ slot.Quantity += outputQty
+ placed = true
+ break
+ }
+ }
+ }
+ if !placed {
+ craftConsumeAll(c, p.HasItem, p.RemoveItem)
+ freeSlot := p.FirstFreeSlot()
+ if freeSlot == -1 {
+ break
+ }
+ p.SetInvSlot(freeSlot, &player.InventorySlot{ItemID: def.ID, Quantity: outputQty})
+ }
+
+ if c.XP > 0 {
+ g.awardSkillXP(sess, p, skill, c.XP)
+ }
+
+ batches++
+ totalOutput += outputQty
+
+ if count > 0 {
+ count--
+ if count <= 0 {
+ break
+ }
+ }
+ }
+
+ if batches == 0 {
+ sess.WriteLine("You don't have the materials for that.")
+ return
+ }
+
+ g.AccountStore.SaveCharacter(p)
+
+ outDef, _ := g.ItemStore.Load(def.ID)
+ outputName := def.Name
+ if outDef != nil {
+ outputName = g.itemColorize(sess, outDef, outDef.Name)
+ }
+ msg := fmt.Sprintf("You fletch %d %s.", totalOutput, outputName)
+ if p.OptionBool("xp_drops") && c.XP > 0 {
+ msg += g.formatXpDropSingle(sess, p, skill, c.XP*batches)
+ }
+ sess.WriteLine(msg)
+}
+
+func (g *Game) startTimedFletch(sess *net.Session, p *player.Player, def *item.ItemDef, count int) {
+ craft := def.FirstCraft()
+
+ startMsg := g.resolveCraftMessage(sess, craft.StartMessage, "You begin fletching %i1.", craft, def.ID, nil, p.HasItem)
+
+ sess.WriteLine(startMsg)
+
+ broadcastName := def.Name
+ if dd, _ := g.ItemStore.Load(def.ID); dd != nil {
+ broadcastName = dd.Name
+ }
+ g.broadcastAction(sess, "%s starts fletching.", p.Name)
+ _ = broadcastName
+
+ p.BackgroundAction = &behavior.Action{
+ Type: "fletch",
+ TargetID: def.ID,
+ TargetName: def.Name,
+ Data: &behavior.FletchData{
+ ItemID: def.ID,
+ Phase: 0,
+ Wait: craft.Wait,
+ Remaining: count,
+ },
+ WaitLeft: engine.ToTicks(1),
+ }
+}
+
+func (g *Game) advanceFletch(sess *net.Session, p *player.Player) {
+ data, ok := p.BackgroundAction.Data.(*behavior.FletchData)
+ if !ok {
+ g.cancelBgAction(p)
+ return
+ }
+ itemID := data.ItemID
+ phase := data.Phase
+ wait := data.Wait
+ remaining := data.Remaining
+
+ def := g.loadCraftItem(itemID)
+ if def == nil {
+ g.cancelBgAction(p)
+ return
+ }
+ c := def.FirstCraft()
+
+ if phase == 0 {
+ data.Phase = 1
+ p.BackgroundAction.WaitLeft = engine.ToTicks(wait)
+ return
+ }
+
+ tmpItem := &item.ItemDef{Craft: item.CraftList{*c}}
+ if !g.canDoFletchItem(p, tmpItem) {
+ sess.WriteLine("You've run out of fletching materials.")
+ g.cancelBgAction(p)
+ return
+ }
+
+ outputQty := c.OutputQty
+ if outputQty <= 0 {
+ outputQty = 1
+ }
+
+ skill := player.SkillName(c.EffectiveSkill())
+
+ placed := false
+ if def.Stackable {
+ for i := 0; i < 28; i++ {
+ slot := p.InvSlot(i)
+ if slot != nil && slot.ItemID == def.ID {
+ craftConsumeAll(c, p.HasItem, p.RemoveItem)
+ slot.Quantity += outputQty
+ placed = true
+ break
+ }
+ }
+ }
+ if !placed {
+ craftConsumeAll(c, p.HasItem, p.RemoveItem)
+ freeSlot := p.FirstFreeSlot()
+ if freeSlot == -1 {
+ sess.WriteLine("Your inventory is too full!")
+ g.cancelBgAction(p)
+ return
+ }
+ p.SetInvSlot(freeSlot, &player.InventorySlot{ItemID: def.ID, Quantity: outputQty})
+ }
+
+ if c.XP > 0 {
+ g.awardSkillXP(sess, p, skill, c.XP)
+ }
+ g.AccountStore.SaveCharacter(p)
+
+ msg := g.resolveCraftMessage(sess, c.Message, "You fletch a %n.", c, def.ID, nil, p.HasItem)
+ if p.OptionBool("xp_drops") && c.XP > 0 {
+ msg += g.formatXpDropSingle(sess, p, skill, c.XP)
+ }
+ sess.WriteLine(msg)
+
+ if remaining > 0 {
+ remaining--
+ data.Remaining = remaining
+ if remaining <= 0 {
+ sess.WriteLine("You've finished fletching.")
+ g.cancelBgAction(p)
+ return
+ }
+ }
+
+ if !g.canContinueProduction(p, def) {
+ sess.WriteLine("You've run out of fletching materials.")
+ g.cancelBgAction(p)
+ return
+ }
+
+ p.BackgroundAction.WaitLeft = engine.ToTicks(wait)
+}