Files
wnsrc/gamemodes/terrortown/gamemode/cl_msgstack.lua
lifestorm 94063e4369 Upload
2024-08-04 22:55:00 +03:00

247 lines
6.1 KiB
Lua

--[[
| This file was obtained through the combined efforts
| of Madbluntz & Plymouth Antiquarian Society.
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
| Maloy, DrPepper10 @ RIP, Atle!
|
| Visit for more: https://plymouth.thetwilightzone.ru/
--]]
---- HUD stuff similar to weapon/ammo pickups but for game status messages
-- This is some of the oldest TTT code, and some of the first Lua code I ever
-- wrote. It's not the greatest.
MSTACK = {}
MSTACK.msgs = {}
MSTACK.last = 0
-- Localise some libs
local table = table
local surface = surface
local draw = draw
local pairs = pairs
-- Constants for configuration
local msgfont = "DefaultBold"
local margin = 6
local msg_width = 400
local text_width = msg_width - (margin * 3) -- three margins for a little more room
local text_height = draw.GetFontHeight(msgfont)
local top_y = margin
local top_x = ScrW() - margin - msg_width
local staytime = 12
local max_items = 8
local fadein = 0.1
local fadeout = 0.6
local movespeed = 2
-- Text colors to render the messages in
local msgcolors = {
traitor_text = COLOR_RED,
generic_text = COLOR_WHITE,
generic_bg = Color(0, 0, 0, 200)
};
-- Total width we take up on screen, for other elements to read
MSTACK.width = msg_width + margin
function MSTACK:AddColoredMessage(text, clr)
local item = {}
item.text = text
item.col = clr
item.bg = msgcolors.generic_bg
self:AddMessageEx(item)
end
function MSTACK:AddColoredBgMessage(text, bg_clr)
local item = {}
item.text = text
item.col = msgcolors.generic_text
item.bg = bg_clr
self:AddMessageEx(item)
end
local ttt_msg_soundcue = CreateClientConVar("ttt_cl_msg_soundcue", "0", true)
-- Internal
function MSTACK:AddMessageEx(item)
item.col = table.Copy(item.col or msgcolors.generic_text)
item.col.a_max = item.col.a
item.bg = table.Copy(item.bg or msgcolors.generic_bg)
item.bg.a_max = item.bg.a
item.text = self:WrapText(item.text, text_width)
-- Height depends on number of lines, which is equal to number of table
-- elements of the wrapped item.text
item.height = (#item.text * text_height) + (margin * (1 + #item.text))
item.time = CurTime()
item.sounded = not ttt_msg_soundcue:GetBool()
item.move_y = -item.height
-- Stagger the fading a bit
if self.last > (item.time - 1) then
item.time = self.last + 1 --item.time + 1
end
-- Insert at the top
table.insert(self.msgs, 1, item)
self.last = item.time
end
-- Add a given message to the stack, will be rendered in a different color if it
-- is a special traitor-only message that traitors should pay attention to.
-- Use the newer AddColoredMessage if you want special colours.
function MSTACK:AddMessage(text, traitor_only)
self:AddColoredBgMessage(text, traitor_only and msgcolors.traitor_bg or msgcolors.generic_bg)
end
-- Oh joy, I get to write my own wrapping function. Thanks Lua!
-- Splits a string into a table of strings that are under the given width.
function MSTACK:WrapText(text, width)
surface.SetFont(msgfont)
-- Any wrapping required?
local w, _ = surface.GetTextSize(text)
if w <= width then
return {text} -- Nope, but wrap in table for uniformity
end
local lines = {""}
for i, wrd in ipairs(string.Explode(" ", text)) do -- No spaces means you're screwed
local l = #lines
local added = lines[l] .. " " .. wrd
w, _ = surface.GetTextSize(added)
if w > text_width then
-- New line needed
table.insert(lines, wrd)
else
-- Safe to tack it on
lines[l] = added
end
end
return lines
end
sound.Add({
name = "TTT.MessageCue",
channel = CHAN_STATIC,
volume = 1.0,
level = SNDLVL_NONE,
pitch = 100,
sound = "ui/hint.wav"
})
local msg_sound = Sound("TTT.MessageCue")
local base_spec = {
font = msgfont,
xalign = TEXT_ALIGN_CENTER,
yalign = TEXT_ALIGN_TOP
};
function MSTACK:Draw(client)
if next(self.msgs) == nil then return end -- fast empty check
local running_y = top_y
for k, item in pairs(self.msgs) do
if item.time < CurTime() then
if item.sounded == false then
client:EmitSound(msg_sound, 80, 250)
item.sounded = true
end
-- Apply move effects to y
local y = running_y + margin + item.move_y
item.move_y = (item.move_y < 0) and item.move_y + movespeed or 0
local delta = (item.time + staytime) - CurTime()
delta = delta / staytime -- pct of staytime left
-- Hurry up if we have too many
if k >= max_items then
delta = delta / 2
end
local alpha = 255
-- These somewhat arcane delta and alpha equations are from gmod's
-- HUDPickup stuff
if delta > 1 - fadein then
alpha = math.Clamp( (1.0 - delta) * (255 / fadein), 0, 255)
elseif delta < fadeout then
alpha = math.Clamp( delta * (255 / fadeout), 0, 255)
end
local height = item.height
-- Background box
item.bg.a = math.Clamp(alpha, 0, item.bg.a_max)
draw.RoundedBox(8, top_x, y, msg_width, height, item.bg)
-- Text
item.col.a = math.Clamp(alpha, 0, item.col.a_max)
local spec = base_spec
spec.color = item.col
for i = 1, #item.text do
spec.text=item.text[i]
local tx = top_x + (msg_width / 2)
local ty = y + margin + (i - 1) * (text_height + margin)
spec.pos={tx, ty}
draw.TextShadow(spec, 1, alpha)
end
if alpha == 0 then
self.msgs[k] = nil
end
running_y = y + height
end
end
end
-- Game state message channel
local function ReceiveGameMsg()
local text = net.ReadString()
local special = net.ReadBit() == 1
print(text)
MSTACK:AddMessage(text, special)
end
net.Receive("TTT_GameMsg", ReceiveGameMsg)
local function ReceiveCustomMsg()
local text = net.ReadString()
local clr = Color(255, 255, 255)
clr.r = net.ReadUInt(8)
clr.g = net.ReadUInt(8)
clr.b = net.ReadUInt(8)
print(text)
MSTACK:AddColoredMessage(text, clr)
end
net.Receive("TTT_GameMsgColor", ReceiveCustomMsg)