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