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() g.setPlayerFlag(p, "last_fletch", def.ID) g.AccountStore.SaveCharacter(p) if def.FirstCraft().TicksPerCycle <= 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 { consumeIngredients(c, p.HasItem, p.RemoveItem) slot.Quantity += outputQty placed = true break } } } if !placed { consumeIngredients(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, TicksPerCycle: craft.TicksPerCycle, 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.TicksPerCycle 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 { consumeIngredients(c, p.HasItem, p.RemoveItem) slot.Quantity += outputQty placed = true break } } } if !placed { consumeIngredients(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.SuccessMessage, "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) }