aboutsummaryrefslogtreecommitdiff
path: root/internal/game/action_smelt.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/game/action_smelt.go')
-rw-r--r--internal/game/action_smelt.go153
1 files changed, 153 insertions, 0 deletions
diff --git a/internal/game/action_smelt.go b/internal/game/action_smelt.go
new file mode 100644
index 0000000..75fb8a0
--- /dev/null
+++ b/internal/game/action_smelt.go
@@ -0,0 +1,153 @@
+package game
+
+import (
+ "fmt"
+ "math/rand"
+
+ "thehouseoficarus/internal/action"
+ "thehouseoficarus/internal/engine"
+ "thehouseoficarus/internal/net"
+ "thehouseoficarus/internal/player"
+)
+
+func (g *Game) startSmelt(sess *net.Session, p *player.Player, recipe *action.RecipeDef, stationName string) {
+ g.CancelAction(p)
+
+ if recipe.Skill != "" {
+ skillLevel := p.Level(player.SkillName(recipe.Skill))
+ if skillLevel < recipe.Level {
+ sess.WriteLine(fmt.Sprintf("You need level %d %s to smelt that.", recipe.Level, recipe.Skill))
+ return
+ }
+ }
+
+ if !recipe.HasAllItemsQty(p.CountItem) {
+ sess.WriteLine("You don't have the required ores.")
+ return
+ }
+
+ if p.FirstFreeSlot() == -1 {
+ sess.WriteLine("Your inventory is too full!")
+ return
+ }
+
+ wait := recipe.Wait
+ if wait <= 0 {
+ wait = 4
+ }
+
+ outputName := recipe.Output
+ if def, err := g.ItemStore.Load(recipe.Output); err == nil {
+ outputName = def.Name
+ }
+
+ p.Action = &action.Action{
+ Type: "smelt",
+ TargetID: recipe.ID,
+ TargetName: recipe.DisplayName(),
+ Data: map[string]any{
+ "recipe_id": recipe.ID,
+ "station_name": stationName,
+ "phase": 0,
+ "wait": wait,
+ },
+ WaitLeft: engine.ToTicks(1),
+ }
+
+ p.ActionState = &ActionState{Type: ActionSmelting, TargetName: outputName}
+}
+
+func (g *Game) advanceSmelt(sess *net.Session, p *player.Player) bool {
+ recipeID := p.Action.Data["recipe_id"].(string)
+ phase := p.Action.Data["phase"].(int)
+ wait := p.Action.Data["wait"].(float64)
+
+ all, err := g.RecipeStore.LoadAll()
+ if err != nil {
+ g.CancelAction(p)
+ return false
+ }
+ var recipe *action.RecipeDef
+ for _, r := range all {
+ if r.ID == recipeID {
+ recipe = &r
+ break
+ }
+ }
+ if recipe == nil {
+ g.CancelAction(p)
+ return false
+ }
+
+ if phase == 0 {
+ firstItem := recipe.FirstItemName(func(id string) (string, bool) {
+ def, err := g.ItemStore.Load(id)
+ if err != nil {
+ return id, false
+ }
+ return def.Name, true
+ })
+ sess.WriteLine(fmt.Sprintf("\nYou begin to process %s in the furnace.", firstItem))
+ p.Action.Data["phase"] = 1
+ p.Action.WaitLeft = engine.ToTicks(wait)
+ return true
+ }
+
+ skillLevel := p.Level(player.SkillName(recipe.Skill))
+ chance := 1.0
+ if recipe.Success != nil {
+ chance = action.SuccessChance(*recipe.Success, skillLevel, recipe.Level)
+ }
+
+ if rand.Float64() < chance {
+ freeSlot := p.FirstFreeSlot()
+ if freeSlot == -1 {
+ sess.WriteLine("Your inventory is too full!")
+ g.CancelAction(p)
+ return false
+ }
+
+ recipe.ConsumeAll(p.HasItem, p.RemoveItem)
+ p.SetInvSlot(freeSlot, &player.InventorySlot{ItemID: recipe.Output, Quantity: 1})
+
+ if recipe.XP > 0 {
+ if newLevel := p.AddSkillXP(player.SkillName(recipe.Skill), recipe.XP); newLevel > 0 {
+ sess.WriteLine(g.colorize(sess, "level_up", fmt.Sprintf("*** You are now level %d %s! ***", newLevel, recipe.Skill)))
+ }
+ }
+ g.AccountStore.SaveCharacter(p)
+
+ msg := recipe.Message
+ if msg == "" {
+ outputName := recipe.Output
+ if def, loadErr := g.ItemStore.Load(recipe.Output); loadErr == nil {
+ outputName = def.Name
+ }
+ msg = fmt.Sprintf("You remove a white hot %s!", outputName)
+ }
+ if p.OptionBool("xp_drops") && recipe.XP > 0 {
+ abbr := player.SkillAbbr[player.SkillName(recipe.Skill)]
+ msg += g.colorize(sess, "xp", fmt.Sprintf(" (+%dxp %s)", recipe.XP, abbr))
+ }
+ sess.WriteLine(msg)
+ } else {
+ recipe.ConsumeAll(p.HasItem, p.RemoveItem)
+ g.AccountStore.SaveCharacter(p)
+
+ msg := recipe.FailMessage
+ if msg == "" {
+ msg = "You fail to smelt a usable bar."
+ }
+ sess.WriteLine(g.colorize(sess, "damage", msg))
+ }
+
+ if recipe.HasAllItemsQty(p.CountItem) && p.FirstFreeSlot() >= 0 {
+ p.Action.Data["phase"] = 0
+ p.Action.WaitLeft = engine.ToTicks(wait)
+ return true
+ }
+
+ sess.WriteLine("\nYou've processed all the ore in your inventory.")
+ g.CancelAction(p)
+ return false
+}