How could I make a timer that pauses and saves if a player leaves?
22 replies, posted
So, I need a timer that pauses and saves when a player leaves, and starts right back up from where it left off when the player joins, I have no clue where to even start with creating something like this.
I am acutely aware that I am asking to (basically) be spoonfed, but my poor little 2 IQ brain has no idea how timers, or time in general works XD
You can use the on-board Source database.
You could also save the value of the timer to a flat file in your server's data directory.
I will be back with some links that will give you a general idea of how to store this information.
Alright, thanks man
you cant after posting the post
Are mods able to switch it for me?
Source's SQL database method:
Player/SetPData
Lets you set a simple value with a key identifier on a player's account on your server.
Player/GetPData
Lets you retrieve set data.
Using a flat file:
file.Write
file.Read
you can store the value as a simple "1337" if there are 1337 seconds left on the timer at the time of player disconnect, in a file under "data/nameOfYourTimer/playerID.txt
You can detect when to store the timer with GM/PlayerDisconnected
and when to set the timer with GM/PlayerInitialSpawn
For someone like you I would probably use the SetPData method.
there is.
Don't use string names. Try passing the player object itself as an argument to the timer. Remember this is Lua.
You can also describe the timer with "HourTimer"..Player:GetSteamID, then override that timer every time the player reconnects in a given server session.
So what exactly is the problem with string names? I don't think they would make a difference, they're just used to identify that timer, Is using "TimerNameHere"..LocalPlayer():GetSteamID() any better? and if so how? since this timer is being ran clientside, i'm assuming the timer would already attach to the player.
If you're wanting to do saving data by a timer you don't even need to. Just make it save on key functions you can even do one for PlayerDisconnected so when they do leave it'll save their data BUT I would also suggest saving in certain functions like if you have a shop / money save after they purchase etc..
That's not the point. I want to create a timer that starts when a player joins, and saves its position when the player disconnects, and when the player re-joins the timer will pick up from where it last left off.
Wait why is it being run clientside? Shouldn't it be run serverside?
Well, I use the server side to tell the client that either a player spawned or disconnected, Its ease of use tbh. The timer gives the client 1 coin every hour, and i hate networking variables XD
Well this is just poor application design. I could easily give myself unlimited coins by just running a clientside script.
Networking variables is very easy. Just run the timers on the server, and every tick, update the networked variable on the player by setting a networked value on them. Then if the user needs to see it display it then on their HUD or in a DPanel, whatever you're already doing. It's really very easy to network this.
"and every tick, update the networked variable on the player by setting a networked value on them."
I'd rather not... I don't feel like taking up my server's CPU to do that.
Quick question:
I'm getting this error when trying to use ply:GetNWInt("StaffPoints") on the client, any reasons why?
[ERROR] addons/responsible_promoter/lua/autorun/cl_points.lua:9: attempt to call method 'GetNWInt' (a nil value)
1. unknown - addons/responsible_promoter/lua/autorun/cl_points.lua:9
What is line 9
Could you post the whole file?
AddCSLuaFile("points.lua")
AddCSLuaFile("config.lua")
include("points.lua")
include("config.lua")
local ply = FindMetaTable("Player")
local staffCoinAmount = ply:GetNWInt("StaffPoints") or ply:GetPData("StaffPoints")
net.Receive("pointsgoingtoclientoriginal", function()
-- Ready
levelingFrame = vgui.Create("DFrame")
levelingFrame.Main = vgui.Create("DScrollPanel", levelingFrame)
levelingFrame.List = vgui.Create("DListLayout", levelingFrame.Main)
levelingFrame.Points = vgui.Create("DPanel",levelingFrame)
levelingFrame.Points.Text = vgui.Create("DLabel",levelingFrame.Points)
if userPoints == true then
levelingFrame.Points.UText = vgui.Create("DLabel",levelingFrame.Points)
end
levelingFrame.Notify = vgui.Create("DNotify")
--Set
levelingFrame:SetTitle("THIS IS A TEST, AND ONLY A TEST OF THE INVALIDS THANG")
levelingFrame:SetSize(512,512)
levelingFrame:SetPos(ScrW() / 2 - 256, ScrH() / 2 -256)
levelingFrame:MakePopup()
levelingFrame:SetDraggable(true)
levelingFrame:SetDeleteOnClose(true)
levelingFrame.Main:SetBackgroundColor(Color(0,0,0,255))
levelingFrame.Main:SetSize(512, 512-25)
levelingFrame.Main:SetPos(0,25)
levelingFrame.List:SetPaintBackground(false)
levelingFrame.List:SetBackgroundColor(Color(0,100,100))
levelingFrame.List:SetSize( 100, 100 )
levelingFrame.List:SetPos(20,50)
levelingFrame.Points:SetSize(120,50)
levelingFrame.Points:SetPos(392,25)
levelingFrame.Points.Text:SetText(staffPointName..": "..tostring(staffCoinAmount or 0))
levelingFrame.Points.Text:SetContentAlignment( 5 )
levelingFrame.Points.Text:SizeToContents()
levelingFrame.Points.Text:CenterHorizontal(0.5)
levelingFrame.Points.Text:CenterVertical(0.3)
if userPoints == true then
levelingFrame.Points.UText:SetText(userPointName..": "..tostring(userCoinAmount or 0))
levelingFrame.Points.UText:SetContentAlignment( 5 )
levelingFrame.Points.UText:SizeToContents()
levelingFrame.Points.UText:CenterHorizontal(0.5)
levelingFrame.Points.UText:CenterVertical(0.7)
end
local blur = Material("pp/blurscreen")
local function DrawBlur(panel, amount)
local x, y = panel:LocalToScreen(0, 0)
local scrW, scrH = ScrW(), ScrH()
surface.SetDrawColor(255, 255, 255)
surface.SetMaterial(blur)
for i = 1, 3 do
blur:SetFloat("$blur", (i / 3) * (amount or 6))
blur:Recompute()
render.UpdateScreenEffectTexture()
surface.DrawTexturedRect(x * -1, y * -1, scrW, scrH)
end
end
levelingFrame.Paint = function(self,w,h)
DrawBlur(self, 9)
draw.RoundedBox(0,0,0,w,h,Color(100,100,100,60))
draw.RoundedBox(0,0,0,512,25,Color(255,255,255,255))
end
levelingFrame.Points.Paint = function(self,w,h)
DrawBlur(self, 3)
draw.RoundedBox(0,0,0,w,h,Color(50,50,50,200))
end
--Do the do
local function getleaves(root)
local leaves = {}
for k,v in pairs(root) do
local tbllen = 0
for k,v in pairs(v) do
tbllen = tbllen + 1
end
if tbllen == 0 then
leaves[#leaves + 1] = k
else
local newleaves = getleaves(v)
for i,j in pairs(newleaves) do
leaves[#leaves + 1] = j
end
end
end
return leaves
end
local ranks = getleaves(ULib.ucl.getInheritanceTree())
for k,v in pairs(ranks) do
levelingFrame.List:Add( Label(v) )
print(v)
end
end)
You should be doing this inside of some hook that provides a player entity - you can't just run methods on the player metatable.
What do you mean by that? do you want me to do something like this?:
local ply = LocalPlayer()
?
Sure, just make sure to do it inside of the net.Receive
okay, yep its working, The timer has no way to check if it is properly, but i'll do what I can to do some tests on it, but I do believe that everything is working. I'll keep you updated
Sorry, you need to Log In to post a reply to this thread.