Hold to use

What I want to do is make it so player has to hold down the USE key (and not move their mouse or whatever away from it) for a certain time until a variable gets to a certain amount, then something will be triggered. This is my code so far, not working:
ent_drill
[lua]AddCSLuaFile( “cl_init.lua” ) – Make sure clientside
AddCSLuaFile( “shared.lua” ) – and shared scripts are sent.

include(‘shared.lua’)

//
// Money Pallet models/props/cs_assault/MoneyPallet.mdl
// ATM models/props/cs_assault/TicketMachine.mdl
// Banded Money models/props/cs_assault/Money.mdl
// Table models/props/CS_militia/wood_table.mdl
// Getaway Van models/props/de_nuke/truck_nuke.mdl
// Security Camera models/props/cs_assault/camera.mdl
//

function ENT:Initialize()

util.AddNetworkString( "drillsync" )
drilltime = 0
self:SetModel( "models/props/de_nuke/truck_nuke.mdl" )
self:PhysicsInit( SOLID_VPHYSICS )      -- Make us work with physics,
self:SetMoveType( MOVETYPE_VPHYSICS )   -- after all, gmod is a physics
self:SetSolid( SOLID_VPHYSICS )         -- Toolbox

local phys = self:GetPhysicsObject()
if (phys:IsValid()) then
	phys:Wake()
end

timer.Create( "DrillUse", 1, 1, function()
	if drilltime < 1 then
		drilltime = drilltime + 0.25
	end
end)
timer.Stop( "DrillUse" )

end

function ENT:Use( activator, caller )
timer.Start(“DrillUse”)
end

function ENT:Think()
if drilltime > 0.99 then
print(“Well done!”)
end

net.Start( "drillsync" )         // start writing the net message
       net.WriteInt( drilltime, 32 )   // anything under roughly 2^31 - 1 
   net.Broadcast()                 // send the message to all connected players

end[/lua]

shared
[lua]ddrilltime = 0

net.Receive( “drillsync”, function( int )

   ddrilltime = ddrilltime + net.ReadInt(32)

end )[/lua]

cl_init
[lua]concommand.Add(“printdrill”, function()
print(ddrilltime)
end)[/lua]

Pressing E on it does nothing, no well done, printdrill yields 0. Help?

Move this out of the Initialize function:
[LUA]
util.AddNetworkString( “drillsync” )
[/LUA]
Ent:Use() is only called once, so you can’t really detect if the player is still pressing E using that alone.
It gets called as soon as you start pressing though, so you should store the player that used the entity and then in the think function keep checking if the player is still pressing the use key (use Player:KeyDown()) and if he is still pressing it increase drilltime by FrameTime().

Don’t sync the timer each tick. Only sync the time when the player started and stopped pressing E. Everything in between can be calculated on the clientside.

[lua]function ENT:Use( activator, caller )
timer.Start(“DrillUse”)
activatorply = activator
end

function ENT:Think()
– We don’t need to think, we are just a prop after all!
if drilltime > 0.99 then
print(“Well done!”)
end

if activatorply:KeyDown( IN_USE ) then
	-- Code
end

net.Start( "drillsync" )         // start writing the net message
       net.WriteInt( drilltime, 32 )   // anything under roughly 2^31 - 1 
   net.Broadcast()                 // send the message to all connected players

end[/lua]
Would that work?

Although, I don’t know what you mean by increasing drilltime by FrameTime(), would it be using built in timers like timer.Simple or timer.Create, or is it a completely different kind of thing?

Nevermind the FrameTime() part.
This could work:
[LUA]function ENT:Use( activator, caller )
net.Start(“DrillStartUse”) //You need to AddNetworkString this
net.WriteFloat(CurTime())
net.Broadcast()
activatorply = activator
drilltime = 0 //You might want to store this on the entity instead
end

function ENT:Think()
local difference = CurTime()-(self.LastThink or CurTime())
– We don’t need to think, we are just a prop after all!
if drilltime > 0.99 then
print(“Well done!”)
end

if IsValid(activatorply) && activatorply:KeyDown( IN_USE ) then
	drilltime = drilltime + difference
elseif(activatorply) then
	activatorply = nil
	net.Start("DrillEnd")
	net.Broadcast()
end
self.LastThink = CurTime()

end[/LUA]

I don’t get what I’d do in shared.lua/cl_init.lua. Modified it a bit to match network strings and more printing, not really doing anything…

Does it print ‘Well done!’ now?
Regarding your questions. That totally depends on what you want to do with the time ddrilltime you had.

Sorry for the bump but I just noticed that [lua]AddCSLuaFile( “cl_init.lua” ) – Make sure clientside
AddCSLuaFile( “shared.lua” ) – and shared scripts are sent.

include(‘shared.lua’)

//
// Money Pallet models/props/cs_assault/MoneyPallet.mdl
// ATM models/props/cs_assault/TicketMachine.mdl
// Banded Money models/props/cs_assault/Money.mdl
// Table models/props/CS_militia/wood_table.mdl
// Getaway Van models/props/de_nuke/truck_nuke.mdl
// Security Camera models/props/cs_assault/camera.mdl
// Gate/Drill models/props_c17/gate_door02a.mdl
//

function ENT:Initialize()

util.AddNetworkString( "DrillStartUse" )
util.AddNetworkString( "DrillStartEnd" )
drilltime = 0
self:SetModel( "models/props_c17/gate_door02a.mdl" )
self:PhysicsInit( SOLID_VPHYSICS )      -- Make us work with physics,
self:SetMoveType( MOVETYPE_VPHYSICS )   -- after all, gmod is a physics
self:SetSolid( SOLID_VPHYSICS )         -- Toolbox

local phys = self:GetPhysicsObject()
if (phys:IsValid()) then
	phys:Wake()
end

timer.Create( "DrillUse", 1, 1, function()
	if drilltime < 1 then
		drilltime = drilltime + 0.25
	end
end)
timer.Stop( "DrillUse" )

end

function ENT:Use( activator, caller )
net.Start(“DrillStartUse”) //You need to AddNetworkString this
net.WriteFloat(CurTime())
net.Broadcast()
activatorply = activator
drilltime = 0 //You might want to store this on the entity instead
end

function ENT:Think()
local difference = CurTime()-(self.LastThink or CurTime())
– We don’t need to think, we are just a prop after all!
if drilltime > 0.99 then
print(“Well done!”)
end

if IsValid(activatorply) && activatorply:KeyDown( IN_USE ) then
	drilltime = drilltime + difference
elseif(activatorply) then
	activatorply = nil
	net.Start("DrillStartEnd")
	net.Broadcast()
	drilltime = 0
end
self.LastThink = CurTime()

end[/lua]
it prints Well Done when I’m close to it 100% of the time not when I hold use on it

Edit: Seems to increase when I just look at it in use range

Edit: It’s as if DrillStartUse is being sent every frame that drilltime/ddrill time = 1

Put a print(“debug”) in certain lines to find out what exactly is going wrong.
the Use method should only be called once. Start there, if it’s called more often you probably have to change your UseType using ent:SetUseType(SIMPLE_USE)

Also, I just found out that there is a way to change the use method to be continuous.
Unfortunately I don’t think there is a way built in to detect when the player releases the key…
Ent:Use() also comes with a parameter called value. I have no idea what it is exactly and what value it has, but maybe that would be useful for you.
As always there is little documentation on this kind of stuff. Quite pathetic for a game that sole purpose is for coders to create mods for it…

There are many ways you can accomplish Hold to use… I’ve made systems which use a timer ( on simple use start timer, on -Use destroy timer, if the timer executes then a quick check to verify use is still pressed means the user held the button the entire time… Because -use destroys the timer, and +use starts a new time, it works very well and is EASY to implement.

If you want to show a progress bar, you can simple set up the equations necessary to get the fraction and display on screen…

Here are the time equations:
Delay = X; in seconds == Total Time
StartTime = CurTime( );…
EndTime = StartTime + Delay;

TimeElapsed = CurTime( ) - StartTime;
TimeRemaining = Delay - ( TimeElapsed ); == Delay - ( CurTime( ) - StartTime );
TimeFraction = TimeElapsed / Delay;

Something similar without the bar, but using the equations: https://dl.dropboxusercontent.com/u/26074909/tutoring/vgui/sh_hud_countdown.lua.html

VGUI Progress bar uses SetFraction, that could work, or you could draw your own… Unfortunately I don’t have the example ready yet for that; the draw extensions I added will be out soon ( draw.ProgressBar ), but it is as easy as setting a width or height for the bar at 100% ( with fraction 0-1; clamp it ) such as 250 pixels… ( MaxWidth * math.Clamp( TimeFraction, 0, 1 ) ); The equations do the rest…

Ok, so… I want to do the absolute opposite. I’ve been trying to figure out a way to stop ‘hold to use’ so that it only works once…

***AddCSLuaFile(“cl_init.lua”)
AddCSLuaFile(“shared.lua”)

include(“shared.lua”)

function ENT:Initialize()

self:SetModel("models/props_wasteland/cargo_container01.mdl")
self:PhysicsInit(SOLID_VPHYSICS)
self:SetMoveType(MOVETYPE_VPHYSICS)
self:SetSolid(SOLID_VPHYSICS)

local phys = self:GetPhysicsObject()

if phys:IsValid() then

    ******phys******:Wake******()
    
end

end

function ENT:Use(a , c, SIMPLE_USE)***

local vehicle = ents.Create( “sent_spitfire_p” )

vehicle:SetPos( Vector( 0, 0, 100 ) )
vehicle:Spawn()

end

I also want to make it spawn the entity in, and then delete itself leaving the entity in it’s place instead of dropping the spawned entity out fo the air but that’s not my priority right now