diff options
Diffstat (limited to 'internal/game/action_burn.go')
| -rw-r--r-- | internal/game/action_burn.go | 532 |
1 files changed, 0 insertions, 532 deletions
diff --git a/internal/game/action_burn.go b/internal/game/action_burn.go deleted file mode 100644 index e1872ed..0000000 --- a/internal/game/action_burn.go +++ /dev/null @@ -1,532 +0,0 @@ -package game - -import ( - "fmt" - "math/rand" - "strings" - - "thehouseoficarus/internal/action" - "thehouseoficarus/internal/engine" - "thehouseoficarus/internal/net" - "thehouseoficarus/internal/object" - "thehouseoficarus/internal/player" -) - -func (g *Game) executeBurn(sess *net.Session, args []string, rawInput string) { - p := sess.Player - g.cancelAction(p) - g.doBurn(sess, p, strings.Join(args, " ")) -} - -func (g *Game) executeStoke(sess *net.Session, args []string, rawInput string) { - p := sess.Player - g.cancelAction(p) - g.doStoke(sess, p, strings.Join(args, " ")) -} - -func (g *Game) doBurn(sess *net.Session, p *player.Player, input string) { - if p.Action != nil { - g.cancelAction(p) - } - g.cancelBgAction(p) - - itemID, fromGround, ambiguous := g.resolveBurnTarget(p, input) - if ambiguous { - sess.WriteLine("Burn what?") - return - } - if itemID == "" { - sess.WriteLine("Burn what?") - return - } - - g.startBurn(sess, p, itemID, fromGround) -} - -func (g *Game) doStoke(sess *net.Session, p *player.Player, input string) { - if p.Action != nil { - g.cancelAction(p) - } - g.cancelBgAction(p) - - if !g.hasFireObject(p.RoomID) { - sess.WriteLine("There's no fire here to stoke.") - return - } - - itemID, ambiguous := g.resolveStokeTarget(p, input) - if ambiguous { - sess.WriteLine("Stoke what?") - return - } - if itemID == "" { - sess.WriteLine("You have no logs to stoke with!") - return - } - - g.startStoke(sess, p, itemID) -} - -func (g *Game) startBurn(sess *net.Session, p *player.Player, itemID string, fromGround bool) { - if p.FirstFreeSlot() == -1 && !fromGround { - sess.WriteLine("Your inventory is too full!") - return - } - - if g.hasFireObject(p.RoomID) { - sess.WriteLine("There is already a fire burning here.") - return - } - - logDef, err := g.ItemStore.Load(itemID) - if err != nil { - sess.WriteLine("Something is wrong with that item.") - return - } - - if logDef.BurnTicks <= 0 { - sess.WriteLine(fmt.Sprintf("You can't burn the %s.", g.itemColorize(sess, logDef, logDef.Name))) - return - } - - skillLevel := p.Level(player.Firemaking) - if logDef.FireLevel > 0 && skillLevel < logDef.FireLevel { - sess.WriteLine(fmt.Sprintf("You need level %d firemaking to burn %s.", logDef.FireLevel, g.itemColorize(sess, logDef, logDef.Name))) - return - } - - toolSpeed, ok := g.findFireTool(sess, p) - if !ok { - return - } - - if !fromGround { - if !p.HasItem(itemID) { - sess.WriteLine(fmt.Sprintf("You don't have any %s.", g.itemColorize(sess, logDef, logDef.Name))) - return - } - } else { - ground := g.World.GroundItems(p.RoomID) - if ground[itemID] <= 0 { - sess.WriteLine(fmt.Sprintf("There are no %s on the ground here.", g.itemColorize(sess, logDef, logDef.Name))) - return - } - } - - phase := 1 - if !fromGround { - phase = 0 - } - - g.broadcastAction(sess, "\n%s starts building a fire.", p.Name) - - p.Action = &action.Action{ - Type: action.TypeBurn, - TargetID: itemID, - TargetName: logDef.Name, - WaitLeft: 0, - Data: &action.BurnData{ - ItemID: itemID, - ToolSpeed: toolSpeed, - Level: logDef.FireLevel, - XP: logDef.FireXP, - BurnTicks: logDef.BurnTicks, - Phase: phase, - }, - } -} - -func (g *Game) startStoke(sess *net.Session, p *player.Player, itemID string) { - fireKey := g.findFireObjectKey(p.RoomID) - if fireKey == "" { - sess.WriteLine("There's no fire here to stoke.") - return - } - - logDef, err := g.ItemStore.Load(itemID) - if err != nil || logDef.BurnTicks <= 0 { - sess.WriteLine(fmt.Sprintf("You can't stoke the fire with that.")) - return - } - - if !p.HasItem(itemID) { - sess.WriteLine(fmt.Sprintf("You don't have any %s.", g.itemColorize(sess, logDef, logDef.Name))) - return - } - - sess.WriteLine("You begin to tend to the fire.") - - g.broadcastAction(sess, "\n%s tends to the fire.", p.Name) - - p.Action = &action.Action{ - Type: action.TypeStoke, - TargetID: itemID, - TargetName: logDef.Name, - WaitLeft: engine.ToTicks(10), - Data: &action.BurnData{ - ItemID: itemID, - BurnTicks: logDef.BurnTicks, - XP: logDef.FireXP, - }, - } -} - -func (g *Game) advanceBurn(sess *net.Session, p *player.Player) { - d := p.Action.Data.(*action.BurnData) - itemID := d.ItemID - toolSpeed := d.ToolSpeed - phase := d.Phase - - logDef, err := g.ItemStore.Load(itemID) - if err != nil { - g.cancelAction(p) - return - } - - if phase == 0 { - if !p.HasItem(itemID) { - sess.WriteLine(fmt.Sprintf("You're out of %s.", g.itemColorize(sess, logDef, logDef.Name))) - g.cancelAction(p) - return - } - p.RemoveItem(itemID, 1) - g.World.AddGroundItem(p.RoomID, itemID, 1) - g.AccountStore.SaveCharacter(p) - - sess.WriteLine(g.colorize(sess, "fire", fmt.Sprintf("You drop the %s and begin to make a fire...", g.itemColorize(sess, logDef, logDef.Name)))) - g.broadcastDrop(p, itemID, logDef.Name) - - d.Phase = 1 - p.Action.WaitLeft = engine.ToTicks(toolSpeed) - return - } - - ground := g.World.GroundItems(p.RoomID) - if ground[itemID] <= 0 { - sess.WriteLine("The thing you were trying to burn is gone.") - g.cancelAction(p) - return - } - - if phase == 1 { - sess.WriteLine(g.colorize(sess, "fire", fmt.Sprintf("You try burning the %s on the ground...", g.itemColorize(sess, logDef, logDef.Name)))) - d.Phase = 2 - p.Action.WaitLeft = engine.ToTicks(toolSpeed) - return - } - - if phase == 2 { - skillLevel := p.Level(player.Firemaking) - chance := 0.5 + float64(skillLevel-logDef.FireLevel)*0.02 - if chance > 0.95 { - chance = 0.95 - } - if chance < 0.05 { - chance = 0.05 - } - - if rand.Float64() < chance { - g.World.RemoveGroundItem(p.RoomID, itemID, 1) - g.World.AddObjInstance(p.RoomID, "fire", logDef.BurnTicks) - - xp := logDef.FireXP - if xp > 0 { - g.awardSkillXP(sess, p, player.Firemaking, xp) - } - - g.AccountStore.SaveCharacter(p) - g.cancelAction(p) - - msg := g.colorize(sess, "fire", "You manage to get a fire going!") - if xp > 0 && p.OptionBool("xp_drops") { - msg += g.formatXpDropSingle(sess, p, player.Firemaking, xp) - } - sess.WriteLine(msg) - - g.broadcastAction(sess, "\n%s started a fire!", p.Name) - return - } - - sess.WriteLine("You can't seem to get a fire going.") - d.Phase = 1 - p.Action.WaitLeft = engine.ToTicks(toolSpeed) - } -} - -func (g *Game) advanceStoke(sess *net.Session, p *player.Player) { - d := p.Action.Data.(*action.BurnData) - itemID := d.ItemID - fireKey := g.findFireObjectKey(p.RoomID) - burnTicks := d.BurnTicks - xp := d.XP - - st := g.World.GetObjStateByKey(fireKey) - if st == nil || st.Quality <= 0 { - sess.WriteLine("The fire went out!") - g.cancelAction(p) - return - } - - logDef, _ := g.ItemStore.Load(itemID) - name := itemID - if logDef != nil { - name = logDef.Name - } - - if !p.HasItem(itemID) { - sess.WriteLine(g.colorize(sess, "fire", fmt.Sprintf("You're out of %s and the fire is roaring.", g.itemColorize(sess, logDef, name)))) - g.cancelAction(p) - return - } - - p.RemoveItem(itemID, 1) - st.Quality += burnTicks / 2 - - if xp > 0 { - g.awardSkillXP(sess, p, player.Firemaking, xp) - } - - g.AccountStore.SaveCharacter(p) - - msg := g.colorize(sess, "fire", fmt.Sprintf("You throw %s onto the fire.", g.itemColorize(sess, logDef, name))) - if xp > 0 && p.OptionBool("xp_drops") { - msg += g.formatXpDropSingle(sess, p, player.Firemaking, xp) - } - sess.WriteLine(msg) - - if !p.HasItem(itemID) { - sess.WriteLine(g.colorize(sess, "fire", fmt.Sprintf("You're out of %s and the fire is roaring.", g.itemColorize(sess, logDef, name)))) - g.cancelAction(p) - return - } - - p.Action.WaitLeft = engine.ToTicks(10.0) -} - -func (g *Game) findFireTool(sess *net.Session, p *player.Player) (toolSpeed float64, ok bool) { - toolSpeed = -1 - var toolItemID string - - if itemID, equipped := p.Equipment[object.SlotMainHand]; equipped { - def, err := g.ItemStore.Load(itemID) - if err == nil && def.ToolType == "fire" { - toolSpeed = def.ToolSpeed - toolItemID = itemID - } - } - - if toolSpeed < 0 { - for _, slot := range p.Inventory { - if slot == nil || slot.Quantity <= 0 { - continue - } - def, err := g.ItemStore.Load(slot.ItemID) - if err != nil || def.ToolType != "fire" { - continue - } - toolSpeed = def.ToolSpeed - toolItemID = slot.ItemID - break - } - } - - if toolSpeed < 0 { - sess.WriteLine("You need a fire starter to do that.") - return 0, false - } - - if !g.consumeFireTool(sess, p, toolItemID) { - return 0, false - } - - return toolSpeed, true -} - -func (g *Game) consumeFireTool(sess *net.Session, p *player.Player, toolItemID string) bool { - def, _ := g.ItemStore.Load(toolItemID) - - if def != nil && def.MaxQuality > 0 { - for _, slot := range p.Inventory { - if slot != nil && slot.ItemID == toolItemID && slot.MaxQuality > 0 { - if slot.Quality <= 0 { - sess.WriteLine("The lighter is out of butane!") - return false - } - slot.Quality-- - g.AccountStore.SaveCharacter(p) - return true - } - } - if q, ok := p.EquipQuality[toolItemID]; ok { - if q <= 0 { - sess.WriteLine("The lighter is out of butane!") - return false - } - p.EquipQuality[toolItemID] = q - 1 - g.AccountStore.SaveCharacter(p) - return true - } - } - - if def != nil && def.Stackable { - if p.HasItem(toolItemID) { - p.RemoveItem(toolItemID, 1) - g.AccountStore.SaveCharacter(p) - return true - } - for slot, itemID := range p.Equipment { - if itemID == toolItemID { - delete(p.Equipment, slot) - g.AccountStore.SaveCharacter(p) - return true - } - } - sess.WriteLine("You need a fire starter to do that.") - return false - } - - return true -} - -func (g *Game) findFireObjectKey(roomID int) string { - objs := g.World.AllObjInstances(roomID) - for _, st := range objs { - if st.DefID == "fire" && st.Quality > 0 { - return g.World.ObjStateKey(st.RoomID, st.DefID, st.Index) - } - } - return "" -} - -func (g *Game) hasFireObject(roomID int) bool { - return g.findFireObjectKey(roomID) != "" -} - -func (g *Game) broadcastDrop(p *player.Player, itemID, itemName string) { - itemDef, _ := g.ItemStore.Load(itemID) - for _, other := range g.Hub.PlayersInRoom(p.RoomID) { - op := other.Player - if op != nil && op.Name != p.Name { - colored := itemName - if itemDef != nil { - colored = g.itemColorize(other, itemDef, itemName) - } - other.WriteLine(fmt.Sprintf("%s drops a %s.", p.Name, colored)) - } - } -} - -func (g *Game) FireTick() { - for _, st := range g.World.AllFireStates() { - st.Quality-- - if st.Quality <= 0 { - g.World.RemoveObjInstance(st.RoomID, st.DefID) - g.cancelStokers(st.RoomID) - if def, err := g.ObjectStore.Load(st.DefID); err == nil && def.RemovalItem != "" { - g.World.AddGroundItem(st.RoomID, def.RemovalItem, 1) - } - } - } -} - -func (g *Game) cancelStokers(roomID int) { - for _, other := range g.Hub.PlayersInRoom(roomID) { - op := other.Player - if op != nil && op.Action != nil && op.Action.Type == action.TypeStoke { - other.WriteLine("The fire went out!") - g.cancelAction(op) - g.writePrompt(other) - } - } -} - -func (g *Game) resolveBurnTarget(p *player.Player, input string) (itemID string, fromGround bool, ambiguous bool) { - if input != "" { - return g.namedBurnTarget(p, input) - } - return g.defaultBurnTarget(p) -} - -func (g *Game) burnableGround(roomID int, name string) []string { - var out []string - for itemID := range g.World.GroundItems(roomID) { - def, err := g.ItemStore.Load(itemID) - if err != nil || def.BurnTicks <= 0 { - continue - } - if name == "" || def.MatchesName(name) { - out = append(out, itemID) - } - } - return out -} - -func (g *Game) burnableInv(p *player.Player, name string) []string { - var out []string - seen := make(map[string]bool) - for _, slot := range p.Inventory { - if slot == nil || slot.Quantity <= 0 { - continue - } - def, err := g.ItemStore.Load(slot.ItemID) - if err != nil || def.BurnTicks <= 0 || seen[slot.ItemID] { - continue - } - if name == "" || def.MatchesName(name) { - seen[slot.ItemID] = true - out = append(out, slot.ItemID) - } - } - return out -} - -func (g *Game) namedBurnTarget(p *player.Player, input string) (itemID string, fromGround bool, ambiguous bool) { - groundMatches := g.burnableGround(p.RoomID, input) - if len(groundMatches) > 1 { - return "", false, true - } - if len(groundMatches) == 1 { - return groundMatches[0], true, false - } - - invMatches := g.burnableInv(p, input) - if len(invMatches) > 1 { - return "", false, true - } - if len(invMatches) == 1 { - return invMatches[0], false, false - } - - return "", false, false -} - -func (g *Game) defaultBurnTarget(p *player.Player) (itemID string, fromGround bool, ambiguous bool) { - groundBurnable := g.burnableGround(p.RoomID, "") - if len(groundBurnable) == 1 { - return groundBurnable[0], true, false - } - if len(groundBurnable) > 1 { - return "", false, true - } - - invBurnable := g.burnableInv(p, "") - if len(invBurnable) == 1 { - return invBurnable[0], false, false - } - if len(invBurnable) > 1 { - return "", false, true - } - - return "", false, false -} - -func (g *Game) resolveStokeTarget(p *player.Player, input string) (string, bool) { - invBurnable := g.burnableInv(p, input) - if len(invBurnable) == 1 { - return invBurnable[0], false - } - if len(invBurnable) > 1 { - return "", true - } - return "", false -} |
