aboutsummaryrefslogtreecommitdiff
path: root/internal/game/utils.go
blob: 969eba480bf90fd049f2521e142cde8ca52613b8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
package game

import (
	"fmt"
	"math/rand"
	"strconv"
	"strings"

	"thirdcollapse/internal/net"
	"thirdcollapse/internal/object"
	"thirdcollapse/internal/player"
	"thirdcollapse/internal/world"
)

var EquipSlots = []object.EquipSlot{
	object.SlotHead, object.SlotNeck, object.SlotTorso, object.SlotLegs,
	object.SlotHands, object.SlotFeet, object.SlotBack, object.SlotAmmo,
	object.SlotMainHand, object.SlotOffHand, object.SlotRing,
}

type itemMatch struct {
	ID   string
	Name string
	Slot int
}

type xpGain struct {
	Skill string
	XP    int
}

type deathDrop struct {
	itemID    string
	quantity  int
	totalVal  int
	isEquip   bool
	equipSlot object.EquipSlot
	invSlot   int
}

func plural(n int) string {
	if n == 1 {
		return ""
	}
	return "s"
}

func parseQty(input string) (int, string) {
	parts := strings.Fields(input)
	if len(parts) > 1 {
		if n, err := strconv.Atoi(parts[0]); err == nil && n > 0 {
			return n, strings.Join(parts[1:], " ")
		}
	}
	return 0, input
}

func parseIndex(s string) (int, error) {
	var idx int
	_, err := fmt.Sscanf(s, "%d", &idx)
	return idx, err
}

func mobDisplayName(m *world.MobInstance, definite bool) string {
	if m.Unique {
		return m.Name
	}
	if definite {
		return "the " + m.Name
	}
	return "a " + m.Name
}

func mobCombatLevel(m *world.MobInstance) int {
	return int(0.25*float64(m.Attack+m.Strength+m.Defense+m.MaxHP) + 0.5)
}

func uniqueItemNames(matches []itemMatch) []string {
	seen := make(map[string]bool)
	var out []string
	for _, m := range matches {
		if !seen[m.Name] {
			seen[m.Name] = true
			out = append(out, m.Name)
		}
	}
	return out
}

func randInt(max int) int {
	if max <= 0 {
		return 0
	}
	return rand.Intn(max)
}

func innerPickupReport(sess *net.Session, picked []string) {
	for i, name := range picked {
		if i == len(picked)-1 {
			sess.WriteLine(name)
		} else if i == len(picked)-2 {
			sess.Write(name + " and ")
		} else {
			sess.Write(name + ", ")
		}
	}
}

func actionDesc(p *player.Player) string {
	if p.Action == nil {
		return ""
	}
	target := p.Action.TargetName
	if idx, ok := p.Action.Data["instance_idx"]; ok {
		target += fmt.Sprintf(" [%d]", idx)
	}
	switch p.Action.Type {
	case "gather":
		return "mining a " + target
	case "talk":
		return "talking to " + target
	case "use":
		return "using a " + target
	case "burn":
		return "trying to start a fire"
	case "stoke":
		return "tending to a fire"
	}
	return ""
}

func (g *Game) newInvSlot(itemID string, qty int) *player.InventorySlot {
	slot := &player.InventorySlot{ItemID: itemID, Quantity: qty}
	if def, err := g.ItemStore.Load(itemID); err == nil && def.MaxQuality > 0 {
		slot.Quality = def.Quality
		slot.MaxQuality = def.MaxQuality
	}
	return slot
}