src/shoot.go (view raw)
1package src
2
3import (
4 "fmt"
5 "time"
6
7 "github.com/bwmarrin/discordgo"
8 "golang.org/x/exp/rand"
9)
10
11type Magazine struct {
12 size uint
13 left uint
14 last time.Time
15}
16
17var magazines = map[string]*Magazine{}
18
19func NewMagazine(size uint) *Magazine {
20 return &Magazine{size: size, left: size, last: time.Now()}
21}
22
23func (m *Magazine) Update() {
24 now := time.Now()
25 if m.last.YearDay() != now.YearDay() || m.last.Year() != now.Year() {
26 m.left = m.size
27 }
28}
29
30func (m *Magazine) Left() uint {
31 m.Update()
32 return m.left
33}
34
35func (m Magazine) Size() uint {
36 return m.size
37}
38
39func (m *Magazine) Shoot() bool {
40 if m.Left() <= 0 {
41 return false
42 }
43
44 m.last = time.Now()
45 m.left--
46 return true
47}
48
49func (m *Magazine) String() string {
50 return fmt.Sprintf("_%d/%d bullets left in your magazine._", m.Left(), m.Size())
51}
52
53func GetMagazine(userID string) (q *Magazine) {
54 q, ok := magazines[userID]
55 if ok {
56 return
57 }
58
59 q = NewMagazine(Config.Values.MagazineSize)
60 magazines[userID] = q
61 return
62}
63
64func handleShoot(args []string, s *discordgo.Session, m *discordgo.MessageCreate) string {
65 const bustProbability = 50
66
67 response, guild, voiceChannelID := getVoiceChannelID(s, m)
68 if voiceChannelID == "" {
69 return response
70 }
71
72 killerID := m.Author.ID
73 var allMembers []string
74 for _, vs := range guild.VoiceStates {
75 logger.Debug(vs.UserID)
76 if vs.ChannelID == voiceChannelID && vs.UserID != killerID {
77 member, err := s.State.Member(guild.ID, vs.UserID)
78 if err != nil {
79 logger.Errorf("could not get member info: %s", err)
80 continue
81 }
82 if !member.User.Bot {
83 allMembers = append(allMembers, vs.UserID)
84 }
85 }
86 }
87
88 if len(allMembers) == 0 {
89 return "There is no one else to shoot in your voice channel."
90 }
91
92 magazine := GetMagazine(killerID)
93 if !magazine.Shoot() {
94 return "💨 Too bad... You're out of bullets."
95 }
96
97 var victimID string
98 if rand.Intn(100) < bustProbability {
99 victimID = killerID
100 } else {
101 victimID = allMembers[rand.Intn(len(allMembers))]
102 }
103
104 err := s.GuildMemberMove(m.GuildID, victimID, nil)
105 if err != nil {
106 logger.Errorf("could not kick user: %s", err)
107 return "Failed to kick the user from the voice channel."
108 }
109
110 return "💥 *Bang!* <@" + victimID + "> was shot. " + magazine.String()
111}