package game import ( "fmt" "math/rand" "thehouseoficarus/internal/action" "thehouseoficarus/internal/engine" "thehouseoficarus/internal/net" "thehouseoficarus/internal/object" "thehouseoficarus/internal/player" ) func (g *Game) startUse(sess *net.Session, p *player.Player, obj *object.ObjectDef) { cfg := obj.Use if cfg == nil { sess.WriteLine("You can't use this.") return } for itemID := range cfg.Consume { if !p.HasItem(itemID) { defName := itemID if def, err := g.ItemStore.Load(itemID); err == nil { defName = def.Name } sess.WriteLine(fmt.Sprintf("You need %s to use this.", defName)) return } } if cfg.Success == nil && p.FirstFreeSlot() == -1 { sess.WriteLine("Your inventory is full.") return } p.ActionState = &ActionState{Type: ActionUsing, TargetName: obj.Name} g.broadcastAction(sess, "\n%s uses the %s.", p.Name, obj.Name) p.Action = &action.Action{ Type: "use", TargetID: obj.ID, TargetName: obj.Name, WaitLeft: engine.ToTicks(1), Data: map[string]any{"step": 0, "use_cfg": cfg}, } sess.WriteLine(fmt.Sprintf("\n%s", cfg.Message)) } func (g *Game) advanceUse(sess *net.Session, p *player.Player) { cfg, ok := p.Action.Data["use_cfg"].(*action.UseConfig) if !ok || cfg == nil { g.cancelAction(p) return } for itemID, qty := range cfg.Consume { if !p.HasItem(itemID) { defName := itemID if def, err := g.ItemStore.Load(itemID); err == nil { defName = def.Name } sess.WriteLine(fmt.Sprintf("You've run out of %s.", defName)) g.cancelAction(p) return } if !p.RemoveItem(itemID, qty) { sess.WriteLine(fmt.Sprintf("You need %d of %s.", qty, itemID)) g.cancelAction(p) return } } if cfg.Success != nil { skillLevel := p.Level(player.SkillName(cfg.Skill)) chance := action.SuccessChance(*cfg.Success, skillLevel, cfg.Level) if rand.Float64() >= chance { if cfg.FailMsg != "" { sess.WriteLine(cfg.FailMsg) } p.Action.WaitLeft = engine.ToTicks(cfg.Wait) return } } freeSlot := p.FirstFreeSlot() if freeSlot == -1 { sess.WriteLine("Your inventory is full.") g.cancelAction(p) return } qty := cfg.Reward.Quantity if qty <= 0 { qty = 1 } p.SetInvSlot(freeSlot, &player.InventorySlot{ItemID: cfg.Reward.ItemID, Quantity: qty}) if cfg.XP > 0 { g.awardSkillXP(sess, p, player.SkillName(cfg.Skill), cfg.XP) } g.AccountStore.SaveCharacter(p) itemName := cfg.Reward.ItemID rewardDef, _ := g.ItemStore.Load(cfg.Reward.ItemID) if rewardDef != nil { itemName = rewardDef.Name } line := fmt.Sprintf("You make a %s.", g.itemColorize(sess, rewardDef, itemName)) if cfg.XP > 0 && p.OptionBool("xp_drops") { line += fmt.Sprintf(" (+%dxp %s)", cfg.XP, player.SkillAbbr[player.SkillName(cfg.Skill)]) } sess.WriteLine(line) if p.FirstFreeSlot() == -1 { sess.WriteLine("Your inventory is full.") g.cancelAction(p) return } p.Action.WaitLeft = engine.ToTicks(cfg.Wait) }