Overheating for a weapon

I’m trying to create a weapon that, well, overheats.
So I set a variable called SWEP.Heat and reset it at 0.
Then, I do this: [lua]if self.Heat >= 255 then
–Create explosion, destroy the gun
return
end

if self.Owner:KeyDown( IN_ATTACK ) and CurTime() > self.Weapon:GetNextPrimaryFire() then
	self.Heat = self.Heat + 1
elseif self.Heat > 0 then
	self.Heat = self.Heat - ( (255-self.Heat)/127 )
	if self.Heat < 0 then self.Heat = 0 end
	if self.Owner:KeyReleased( IN_ATTACK ) and CurTime() > self:GetNextPrimaryFire() then self.Weapon:SetNextPrimaryFire( CurTime() + 2 ) end
end

end[/lua]

But -

  1. Apparently SWEP:Think() is affected by… something, so it doesn’t really fit my needs as I need a static length of time to count on. And I assume there’s a much better way to do this than a timer…
  2. This will mean the “cool down” mechanism won’t work if the weapon isn’t deployed, which really doesn’t fit my needs as that is illogical and makes the weapon lame af
  3. I assume there’s a better way to do all of this that I’m just not aware of…

Firstly, this part:[lua]if self.Owner:KeyDown( IN_ATTACK ) and CurTime() > self.Weapon:GetNextPrimaryFire() then
self.Heat = self.Heat + 1[/lua]should go to PrimaryAttack instead of Think, without the “if” since it naturally works like that anyway.

as for the rest, I’m not sure how foolproof this is but conceptually this is how I’d do it:
[lua]if self.Heat >= 255 then
–Create explosion, destroy the gun
return
end

local lastcool = self.LastCool or CurTime() – just make sure it’s defined, probably best to define self.LastCool in initialize
self.LastCool = CurTime() – for next time

local cooltime = CurTime() - lastcool

– I’m going for linear cooldown here. If you want more elaborate cooldown you would need to calculate it based on dectime and self.Heat
local cooldownamount = cooltime * 0.2 – cool down by 0.2/sec
self.Heat = math.max(self.Heat - cooldownamount, 0)[/lua]

Also note that depending on your plans, you might want to allow the weapon to “cool down” while it’s being fired, as long as the fire rate heats it up faster than it cools down. If not, you can just use the same KeyDown test you did before.

The Think hook is affected by how long it takes the render / process the game logic. Use a constant time function (such as CurTime) to calculate the time between ticks for the weapon. So if they put the gun away for 2 minutes, you should multiply all of your modifications by 120 (assuming your calculations are based off seconds).

Here is some sample code that might guide you in the right direction:

[lua]
SWEP.HeatTimer = 0; – repreents how long they have been shooting
SWEP.OverheatMax = 60; – seconds
SWEP.CooldownRatio = (2 / 1); – 2 seconds of shooting -> 1 second of cooldown
SWEP.LastFrameTime = nil; – when was the last time this code ran?

function SWEP:Think()
– figure out the time it has been since the code last ran
local frameDelta = CurTime() - (SWEP.LastFrameTime or CurTime());

-- are they shooting?
if( self.Owner:KeyDown( IN_ATTACK ) && CurTime() > self.Weapon:GetNextPrimaryFire() )then
	-- update the variable if not set
	self.HeatTimer = (self.HeatTimer or 0) + frameDelta;
	
	-- is it too hot?
	if( self.HeatTimer >= self.OverheatMax )then
		-- EXPLODE
	end
elseif( SWEP.HeatTimer > 0 )then
	-- they stopped shooting, subtract time
	SWEP.HeatTimer = math.Clamp( (self.HeatTimer - (frameDelta * self.CooldownRatio)), 0, self.OverheatMax + 10 );
end

-- update the variable for when this code last ran
SWEP.LastFrameTime = CurTime();

end
[/lua]

This helped a lot, thanks! There’s just 1 thing I didn’t quite understand:
[lua]SWEP.HeatTimer = math.Clamp( (self.HeatTimer - (frameDelta * self.CooldownRatio)), 0, self.OverheatMax + 10 )[/lua] Why is the + 10 there?