I Need Help with Modifying the DarkRP Notifications

Basically I want to make my own DarkRP Notifications (e.g. “Payday! You received $45!”).
What I tried so far works fine if there is only one notification but as soon as there is more than one it bugs out.
I spent about 8 hours trying to make it work properly but now I got no more ideas and I hope some of you can help me.

[video]https://youtu.be/vsrvmw0snxE[/video]

I apologize for the messy code but I hope it is not too hard to read. :smile:


/*---------------------------------------------------------------------------
Display notifications
---------------------------------------------------------------------------*/
NotifyText={}
panelNoti={}

local function DisplayNotify(msg)
    local txt = msg:ReadString()

    




table.insert(NotifyText,txt)


PrintTable(NotifyText) -- debug

   for k,v in pairs(NotifyText) do
         


    if CLIENT then 


    
    panelNotiTex= v
    panelNotiLen = string.len(panelNotiTex)*5+50
    --print(panelNotiLen) -- debug

     panelNoti = vgui.Create( "DPanel") 
    panelNoti:SetSize(panelNotiLen,60)
    panelNoti:SetPos(30,30)
    function panelNoti:Paint(w,h)

    
    if IsValid(panelNoti) then 

    --panelNoti:Remove()
    --hook.Remove( "Think", "ProgBar1" )
    --panelNoti:Remove()
    --table.remove(NotifyText,k)
    panelNoti:SetPos(30,k*30)
    end  -- if IsValid(panelNoti)
    



    surface.SetDrawColor(255,255,55)
    surface.DrawRect(30,30,panelNotiLen,60)

    surface.SetTextColor(255,0,0)
    surface.SetTextPos(40,35)
    surface.DrawText(panelNotiTex)
    end -- function panelNoti:Paint
        
    timer.Create( "panelNotiTime", 3, 1, function ()

     for k,v in pairs(NotifyText) do
    if IsValid(panelNoti) then panelNoti:Remove() end

     table.remove(NotifyText,k)
     table.remove(NotifyText,k-1)

    if IsValid(panelNotiB) then panelNotiB:Remove() end

    if not IsValid(panelNotiB) then hook.Remove( "Think", "ProgBar1" ) end
    end--for k,v (line 429)
     end) --timer.Create( "panelNotiTime"...


if timer.TimeLeft( "panelNotiTime" ) > 0 and IsValid(panelNoti) and panelNoti:IsVisible() then
function ProgBar1 ()
    NotProg = timer.TimeLeft( "panelNotiTime" )/3

        local panelNotiB = vgui.Create( "DProgress",panelNoti )
    panelNotiB:SetPos( 30, 55 )
    panelNotiB:SetSize(panelNotiLen,5)
    panelNotiB:SetFraction( NotProg )
    panelNotiB:SetParent(panelNoti)
    function panelNotiB:Paint(w,h)
surface.SetDrawColor(255,0,0)
surface.DrawRect(0,0,NotProg*panelNotiLen,h)


    end --function panelNotiB:Paint(w,h)


    end --function ProgBar1 ()

hook.Add("Think", "ProgBar1", ProgBar1)
end -- if timer.TimeLeft( "panelNotiTime" )
      end  -- if client
 end -- for k,v (line 389)

    surface.PlaySound("buttons/lightswitch2.wav")

    -- Log to client console
    MsgC(Color(255, 20, 20, 255), "[DarkRP] ", Color(200, 200, 200, 255), txt, "
")
end --function DisplayNotify(msg)
usermessage.Hook("_Notify", DisplayNotify)


Bump

Don’t use timers. When you create a timer with the same name, the previous timers with that name stop working.

How am I supposed to do it instead?

Here is a good example: https://github.com/garrynewman/garrysmod/blob/master/garrysmod/lua/includes/modules/notification.lua#L88-L131

Thanks. I decided to use that example to modify all notifications first.
But I need some help with the progress bars (time left) which I want to add to every notification.
I managed to add a progress bar to every notification but if there are multiple notifications on the screen, all progress bars are using the time of the last notification that appeared.

The part I edited starts at “function Progbar2()”




surface.CreateFont( "GModNotify", {
	font	= "marlett",
	size	= 19,
	weight	= 1000
	} )

NOTIFY_GENERIC	= 0
NOTIFY_ERROR	= 1
NOTIFY_UNDO		= 2
NOTIFY_HINT		= 3
NOTIFY_CLEANUP	= 4

module( "notification", package.seeall )

local NoticeMaterial = {}

NoticeMaterial[ NOTIFY_GENERIC ]	= Material( "vgui/notices/generic" )
NoticeMaterial[ NOTIFY_ERROR ]		= Material( "vgui/notices/error" )
NoticeMaterial[ NOTIFY_UNDO ]		= Material( "vgui/notices/undo" )
NoticeMaterial[ NOTIFY_HINT ]		= Material( "vgui/notices/hint" )
NoticeMaterial[ NOTIFY_CLEANUP ]	= Material( "vgui/notices/cleanup" )

local Notices = {}

function AddProgress( uid, text )

	if ( IsValid( Notices[ uid ] ) ) then

		Notices[ uid ].StartTime = SysTime()
		Notices[ uid ].Length = 1000000
		Notices[ uid ]:SetText( text )
		Notices[ uid ]:SetProgress()
		return

	end

	local parent = nil
	if ( GetOverlayPanel ) then parent = GetOverlayPanel() end

	local Panel = vgui.Create( "NoticePanel", parent )
	Panel.StartTime = SysTime()
	Panel.Length = 1000000
	Panel.VelX = -5
	Panel.VelY = 0
	Panel.fx = ScrW() + 200
	Panel.fy = ScrH()
	Panel:SetAlpha( 255 )
	Panel:SetText( text )
	Panel:SetPos( Panel.fx, Panel.fy )
	Panel:SetProgress()

	Notices[ uid ] = Panel

end

function Kill( uid )

	if ( !IsValid( Notices[ uid ] ) ) then return end

	Notices[ uid ].StartTime = SysTime()
	Notices[ uid ].Length = 0.8

end

function AddLegacy( text, type, length )

	local parent = nil
	if ( GetOverlayPanel ) then parent = GetOverlayPanel() end

	local Panel = vgui.Create( "NoticePanel", parent )
	Panel.StartTime = SysTime()
	Panel.Length = length
	Panel.VelX = -5
	Panel.VelY = 0
	Panel.fx = ScrW() + 200
	Panel.fy = ScrH()
	Panel:SetAlpha( 255 )
	Panel:SetText( text )
	Panel:SetLegacyType( type )
	Panel:SetPos( Panel.fx, Panel.fy )

	table.insert( Notices, Panel )

	text123 = text

end

-- This is ugly because it's ripped straight from the old notice system
local function UpdateNotice( i, Panel, Count )

	local x = Panel.fx
	local y = Panel.fy

	local w = Panel:GetWide() + 16
	local h = Panel:GetTall() + 16

	local ideal_y = ScrH() - ( Count - i ) * ( h - 12 ) - 150
	local ideal_x = ScrW() - w - 20

	local timeleft = Panel.StartTime - ( SysTime() - Panel.Length )

	-- Cartoon style about to go thing
	if ( timeleft < 0.7 ) then
		ideal_x = ideal_x - 50
	end

	-- Gone!
	if ( timeleft < 0.2 ) then
		ideal_x = ideal_x + w * 2
	end

	local spd = FrameTime() * 15

	y = y + Panel.VelY * spd
	x = x + Panel.VelX * spd

	local dist = ideal_y - y
	Panel.VelY = Panel.VelY + dist * spd * 1
	if ( math.abs( dist ) < 2 && math.abs( Panel.VelY ) < 0.1 ) then Panel.VelY = 0 end
	dist = ideal_x - x
	Panel.VelX = Panel.VelX + dist * spd * 1
	if ( math.abs( dist ) < 2 && math.abs( Panel.VelX ) < 0.1 ) then Panel.VelX = 0 end

	-- Friction.. kind of FPS independant.
	Panel.VelX = Panel.VelX * ( 0.95 - FrameTime() * 8 )
	Panel.VelY = Panel.VelY * ( 0.95 - FrameTime() * 8 )

	Panel.fx = x
	Panel.fy = y
	Panel:SetPos( Panel.fx, Panel.fy )



	for k, Panel in pairs( Notices ) do
		local timeleft = Panel.StartTime - ( SysTime() - Panel.Length )
		PanelProgBleft = timeleft














	end

	local function Update()

		if ( !Notices ) then return end

		local i = 0
		local Count = table.Count( Notices )
		for key, Panel in pairs( Notices ) do

			i = i + 1
			UpdateNotice( i, Panel, Count )

		end

		for k, Panel in pairs( Notices ) do

			if ( !IsValid( Panel ) || Panel:KillSelf() ) then Notices[ k ] = nil end

		end

	end

	hook.Add( "Think", "NotificationThink", Update )

	local PANEL = {}

--[[---------------------------------------------------------
   Name: Init
   -----------------------------------------------------------]]
   function PANEL:Init()

   	self:DockPadding( 3, 3, 3, 3 )

   	self.Label = vgui.Create( "DLabel", self )
   	self.Label:Dock( FILL )
   	self.Label:SetFont( "GModNotify" )
   	self.Label:SetTextColor( Color( 255, 255, 255, 255 ) )
   	self.Label:SetExpensiveShadow( 1, Color( 0, 0, 0, 200 ) )
   	self.Label:SetContentAlignment( 5 )

   	self:SetBackgroundColor( Color( 20, 20, 20, 255 * 0.9 ) )

   	function self:Paint(w,h)

   		surface.SetDrawColor(75,75,75,255*0.9)
   		surface.DrawRect(0,0,w,h)

   		surface.SetDrawColor(0,100,255,255*0.9)
   		surface.DrawRect(0,0,40,50)

   		function Progbar2()

   			local panelNotiB = vgui.Create( "DProgress",self)
   			panelNotiB:SetPos( 0, 0 )
   			panelNotiB:SetSize(PanelProgBleft*5,10)    --PanelProgBleft=TimeLeft
   			panelNotiB:SetFraction( 0.75 )
   			panelNotiB:SetParent(self)
   			function panelNotiB:Paint(w,h)
   				surface.SetDrawColor(255,0,0)
   				surface.DrawRect(0,0,PanelProgBleft*5,h)

			--print("Test") -- debug
    end 
    print(PanelProgBleft) --debug

end
hook.Add("Think", "Progbar2", Progbar2)


end

end




function PANEL:SetText( txt )

	self.Label:SetText( txt )
	self:SizeToContents()

end

function PANEL:SizeToContents()

	self.Label:SizeToContents()

	local width = self.Label:GetWide()

	if ( IsValid( self.Image ) ) then
		width = width + 32 + 8
	end

	width = width + 20
	self:SetWidth( width )

	self:SetHeight( 32 + 6 )

	self:InvalidateLayout()

end

function PANEL:SetLegacyType( t )

	self.Image = vgui.Create( "DImageButton", self )
	self.Image:SetMaterial( NoticeMaterial[ t ] )
	self.Image:SetSize( 32, 32 )
	self.Image:Dock( LEFT )
	self.Image:DockMargin( 0, 0, 8, 0 )
	self.Image.DoClick = function()
	self.StartTime = 0
end

self:SizeToContents()

end

function PANEL:SetProgress()

	-- Quick and dirty, just how I like it.
	self.Paint = function( s, w, h )

	self.BaseClass.Paint( self, w, h )

	surface.SetDrawColor( 100, 0, 0, 150 )
	surface.DrawRect( 4, self:GetTall() - 10, self:GetWide() - 8, 5 )

	surface.SetDrawColor( 0, 0, 50, 255 )
	surface.DrawRect( 5, self:GetTall() - 9, self:GetWide() - 10, 3 )

	local w = self:GetWide() * 0.25
	local x = math.fmod( SysTime() * 200, self:GetWide() + w ) - w

	if ( x + w > self:GetWide() - 11 ) then w = ( self:GetWide() - 11 ) - x end
	if ( x < 0 ) then w = w + x; x = 0 end

	surface.SetDrawColor( 0, 0, 255, 255 )
	surface.DrawRect( 5 + x, self:GetTall() - 9, w, 3 )

end

end













function PANEL:KillSelf()

	if ( self.StartTime + self.Length < SysTime() ) then

		self:Remove()
		return true

	end

	return false
end

vgui.Register( "NoticePanel", PANEL, "DPanel" )



bump

I have no idea what you’re doing. Do YOU know what you’re doing? I don’t think you know what you’re doing.

I know what I want to do and I try my best to do it but I’m new to lua so I test everything that comes to my mind.

I basically saw that video: https://www.youtube.com/watch?v=MG6cyXrY1KY
And want to make something similar. Thats all.

Take a closer look at the code I linked to (default gmod code). It also has a progress bar which works correctly.