Files
wnsrc/gamemodes/helix/plugins/typing.lua
lifestorm 73479cff9e Upload
2024-08-04 22:55:00 +03:00

261 lines
6.4 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/
--]]
local PLUGIN = PLUGIN
PLUGIN.name = "Typing Indicator"
PLUGIN.description = "Affiche un indicateur lorsque quelqu'un tape."
PLUGIN.author = "`impulse"
PLUGIN.animationTime = 0.5
if (CLIENT) then
local standingOffset = Vector(0, 0, 72)
local crouchingOffset = Vector(0, 0, 38)
local boneOffset = Vector(0, 0, 10)
local textColor = Color(250, 250, 250)
local shadowColor = Color(66, 66, 66)
local currentClass
-- we can't rely on matching non-alphanumeric characters (i.e %W) due to patterns matching single bytes and not UTF-8 chars
local symbolPattern = "[~`!@#$%%%^&*()_%+%-={}%[%]|;:'\",%./<>?]"
function PLUGIN:LoadFonts(font, genericFont)
surface.CreateFont("ixTypingIndicator", {
font = genericFont,
size = 128,
extended = true,
weight = 1000
})
end
function PLUGIN:ChatTextChanged(text)
if (!IsValid(LocalPlayer())) then
return
end
local character = LocalPlayer():GetCharacter()
if (!character) then
return
end
if (text == "") then
currentClass = nil
net.Start("ixTypeClass")
net.WriteString("")
net.SendToServer()
return
end
local newClass = hook.Run("GetTypingIndicator", character, text)
if (newClass != currentClass) then
currentClass = newClass
net.Start("ixTypeClass")
net.WriteString(currentClass or "")
net.SendToServer()
end
end
function PLUGIN:FinishChat()
currentClass = nil
net.Start("ixTypeClass")
net.WriteString("")
net.SendToServer()
end
function PLUGIN:GetTypingIndicator(character, text)
local prefix = text:utf8sub(1, 1)
if (!prefix:find(symbolPattern) and text:utf8len() > 1) then
return "ic"
else
local chatType = ix.chat.Parse(nil, text)
if (chatType and chatType != "ic") then
return !ix.chat.classes[chatType].bNoIndicator and chatType or nil
end
-- some commands will have their own typing indicator, so we'll make sure we're actually typing out a command first
local start, _, commandName = text:find("/(%S+)%s")
if (start == 1) then
for uniqueID, command in pairs(ix.command.list) do
if (command.bNoIndicator) then
continue
end
if (commandName == uniqueID) then
return command.indicator and "@" .. command.indicator or "ooc"
end
end
end
end
end
function PLUGIN:GetTypingIndicatorPosition(client)
if !IsValid(client) then return end
local head
for i = 1, client:GetBoneCount() do
local name = client:GetBoneName(i)
if (string.find(name:lower(), "head")) then
head = i
break
end
end
local position = head and client:GetBonePosition(head) or (client:Crouching() and crouchingOffset or standingOffset)
return position + boneOffset
end
function PLUGIN:PostDrawTranslucentRenderables()
local client = LocalPlayer()
local position = client:GetPos()
for _, v in ipairs(player.GetAll()) do
if (v == client) then
continue
end
local distance = v:GetPos():DistToSqr(position)
local moveType = v:GetMoveType()
if (!IsValid(v) or !v:Alive() or
(moveType != MOVETYPE_WALK and moveType != MOVETYPE_NONE) or
!v.ixChatClassText or
distance >= v.ixChatClassRange) then
continue
end
local text = v.ixChatClassText
local range = v.ixChatClassRange
if (!text) then
continue
end
local bAnimation = !ix.option.Get("disableAnimations", false)
local fraction
if (bAnimation) then
local bComplete = v.ixChatClassTween:update(FrameTime())
if (bComplete and !v.ixChatStarted) then
v.ixChatClassText = nil
v.ixChatClassRange = nil
continue
end
fraction = v.ixChatClassAnimation
else
fraction = 1
end
local angle = EyeAngles()
angle:RotateAroundAxis(angle:Forward(), 90)
angle:RotateAroundAxis(angle:Right(), 90)
cam.Start3D2D(self:GetTypingIndicatorPosition(v), Angle(0, angle.y, 90), 0.05)
surface.SetFont("ixTypingIndicator")
local _, textHeight = surface.GetTextSize(text)
local alpha = bAnimation and ((1 - math.min(distance, range) / range) * 255 * fraction) or 255
draw.SimpleTextOutlined(text, "ixTypingIndicator", 0,
-textHeight * 0.5 * fraction,
ColorAlpha(textColor, alpha),
TEXT_ALIGN_CENTER,
TEXT_ALIGN_CENTER, 4,
ColorAlpha(shadowColor, alpha)
)
cam.End3D2D()
end
end
net.Receive("ixTypeClass", function()
local client = net.ReadEntity()
if (!IsValid(client) or client == LocalPlayer()) then
return
end
local newClass = net.ReadString()
local chatClass = ix.chat.classes[newClass]
local text
local range
if (chatClass) then
text = L(chatClass.indicator or "chatTyping")
range = chatClass.range or math.pow(ix.config.Get("chatRange", 280), 2)
elseif (newClass and newClass:sub(1, 1) == "@") then
text = L(newClass:sub(2))
range = math.pow(ix.config.Get("chatRange", 280), 2)
end
if (ix.option.Get("disableAnimations", false)) then
client.ixChatClassText = text
client.ixChatClassRange = range
else
client.ixChatClassAnimation = tonumber(client.ixChatClassAnimation) or 0
if (text and !client.ixChatStarted) then
client.ixChatClassTween = ix.tween.new(PLUGIN.animationTime, client, {ixChatClassAnimation = 1}, "outCubic")
client.ixChatClassText = text
client.ixChatClassRange = range
client.ixChatStarted = true
elseif (!text and client.ixChatStarted) then
client.ixChatClassTween = ix.tween.new(PLUGIN.animationTime, client, {ixChatClassAnimation = 0}, "inCubic")
client.ixChatStarted = nil
end
end
end)
else
util.AddNetworkString("ixTypeClass")
function PLUGIN:PlayerSpawn(client)
net.Start("ixTypeClass")
net.WriteEntity(client)
net.WriteString("")
net.Broadcast()
end
net.Receive("ixTypeClass", function(length, client)
if ((client.ixNextTypeClass or 0) > RealTime()) then
return
end
local newClass = net.ReadString()
-- send message to players in pvs only since they're the only ones who can see the indicator
-- we'll broadcast if the type class is empty because they might move out of pvs before the ending net message is sent
net.Start("ixTypeClass")
net.WriteEntity(client)
net.WriteString(newClass)
if (newClass == "") then
net.Broadcast()
else
net.SendPVS(client:GetPos())
end
client.ixNextTypeClass = RealTime() + 0.2
end)
end