A killstreak
Three kills in a row, without dying, give a player the AWP. They hear the rifle loaded, and their screen shows a line for a few seconds:

It is one module of two files. The server counts the kills and gives the rifle. The player’s game shows the line.
The files
Section titled “The files”content/mods/killstreak/ modules/ killstreak/ killstreak.server.luau killstreak.client.luauPut the mod beside content/mods/stock/. Everything it does not have, the game modes, the weapons and the rest of the HUD, comes from the stock mod.
The server’s half
Section titled “The server’s half”-- killstreak.server.luauplayer_state("streak", t.int, 0)event("streak_reward", t.record { player = t.player }, { read_by = owner })
preload("weapon", "weapons/awp")preload("sound", "awp_reload")
on("killed", function(e) e.victim.streak = 0 local killer = e.killer if killer == nil or killer.npc or killer == e.victim then return end killer.streak += 1 if killer.streak == 3 then killer:give("weapons/awp") play_sound("awp_reload", { follow = killer, owner = killer, read_by = owner }) emit("streak_reward", { player = killer }) endend)player_state gives every player a whole number, streak, starting at 0. It has no read_by, so it stays on the server: no player’s game is sent it.
event declares what the server tells a player when they earn the reward. Its read_by = owner sends it to the player its player field names, and to no one else. See who sees what.
preload names the rifle and the sound as the module loads, so players load them while they join instead of in the middle of a fight.
on("killed", ...) runs on every death. The victim’s streak goes back to 0. A kill counts when there is a killer, it is a player rather than an NPC, and it is not the victim themselves. At the third, the killer gets the AWP, hears it loaded, and is told.
The client’s half
Section titled “The client’s half”-- killstreak.client.luaukeyframes("streak_line", { from = { opacity = 0 }, ["10%"] = { opacity = 1 }, ["80%"] = { opacity = 1 }, to = { opacity = 0 },})
local shown = store { count = 0 }
on("streak_reward", function() shown.count += 1end)
mount(function() if shown.count == 0 then return nil end return Box { Box { "Three in a row: AWP", key = shown.count, style = { padding = "8px 20px", fontSize = 34, fontWeight = "bold", color = "#ffcc33", background = "rgba(10, 12, 16, 0.7)", borderRadius = 4, animation = "streak_line 4s forwards", }, }, style = { left = 0, right = 0, top = "28%", display = "flex", justifyContent = "center" }, }end)keyframes defines an animation as CSS’s @keyframes does: the line fades in, stays, and fades out.
store holds the script’s own data. on("streak_reward", ...) hears the server’s event and counts it.
mount puts the HUD on the screen. It draws again whenever something it read changes, here shown.count. The outer box spans the screen 28% of the way down and centres the line in it. The line’s key changes with every reward, which makes it a new box, so its animation starts again.
Styles are CSS, with keys as JavaScript writes them (fontSize) and numbers as pixels of a 1080-line screen.
Try it
Section titled “Try it”Start a server with the mod and four bots to shoot, then join it:
server --mod content/mods/killstreak --bots 4 --reload --set 'masters=[]'client --connect 127.0.0.1:28960--reload loads your edits while you play. masters=[] keeps your test server off the public server list.
Where to go from here
Section titled “Where to go from here”- Show the line to those watching the player too:
read_by = owner + spectatorson the event. - Give a reward at five kills as well, with
killer.streak == 5. - Play the sound to everyone near the player: leave out
ownerandread_by. Sounds lists every option.