Skip to content

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:

The game with a dark box near the top of the screen that reads: Three in a row: AWP.

It is one module of two files. The server counts the kills and gives the rifle. The player’s game shows the line.

content/mods/killstreak/
modules/
killstreak/
killstreak.server.luau
killstreak.client.luau

Put 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.

-- killstreak.server.luau
player_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 })
end
end)

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.

-- killstreak.client.luau
keyframes("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 += 1
end)
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.

Start a server with the mod and four bots to shoot, then join it:

Terminal window
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.

  • Show the line to those watching the player too: read_by = owner + spectators on the event.
  • Give a reward at five kills as well, with killer.streak == 5.
  • Play the sound to everyone near the player: leave out owner and read_by. Sounds lists every option.