Infinite loops error!

I’m in the process of writing a cakescript mod. Basically, I want to create a bit of code that infects the character and does damage, but can be stopped by using an item. My problem is that when I try to loop the damage using a repeat loop, it comes up with an infinite loop error in the console after fps lagging like a bitch. I need help to get it sorted!

[lua]function GM:PlayerHurt( victim, attacker )
local infectchance = math.random (1,5)
infected = 0
if attacker:IsNPC() then
if infectchance == 1 then
infected = 1
repeat
timer.Create(“infection”, 6, 1, Infection)
until (infected == 0)
end
end
end

function Infection()
ply:Takedamage(1)
end[/lua]

Thanks in advance.
Todrak

Here’s what’s happening. (Adding as I go)[lua]
infected = 1 – Infected is now 1
repeat – Start of a loop
timer.Create(“infection”, 6, 1, Infection) – Creating a timer. We’re not waiting for it to end.
until (infected == 0) – Infected has not changed and is still 1, repeat. (For infinity)
[/lua]

I should also point out that when calling the infection function you should do it this way : Infection(victim)
You need the () to tell the game it’s a function, and if you don’t pass the victim the function won’t know who to hurt.
That means the function’s name must be changed to : Infection(ply)
Or else it will say ply is nil.

Oh and also when you create a timer you have to start it later, you should just use Timer.Simple. And since lua is case sensitive the way you wrote it would pop an error.

you might also want to make infected a property that is unique to each player by first creating it in GM:InitialSpawn() and then changing it here. Something like Player.IsInfected

For the infection itself I’m not really sure of the best way to do this… You might want to make a timer calling Infected like now, and in infected add a check to see if the player has been cured (Your item would make Player.IsInfected false). If so end, otherwise apply the damage and create a new timer to call the same function. Don’t forget to set Player.IsInfected to false when the player dies too. And forget about the loop for now. :slight_smile:

Hey Crazy Quebec! Thanks for the response.

[lua]function GM:PlayerHurt( victim, attacker )
local infectchance = math.random (1,2)
if attacker:IsNPC() then
if infectchance == 1 then
infected = true
timer.Create(“infection”, 6, 1, Infection(victim))
end
end
end

function Infection(ply)
if infected == true then
timer.Start(“infection”)
ply:TakeDamage(1)
infected = true
else
end
end

function GM:InitialSpawn(ply)
infected = false
end

function PlayerDeath(ply)
infected = false
end[/lua]

I changed my code to this, but now I am getting a different error.
Time Error: attempt to call a nil value

Any idea how to fix this one?

You still have some of the errors I pointed out. You’re creating a timer without starting it, you’re using a global value (infected) to determine if a particular player should get hurt… Let me try my hand at it real quick.

[lua]function GM:PlayerInitialSpawn(ply) – Our player spawns into the server
ply.Infected = false --Create the Infected value specific to this player, set it to false. It’s ply.Infected and not just Infected because Infected would be true or false for every player at a time. ply.Infected only affects this specific player.
end

function GM:PlayerDeath(ply) – Alas! Our player has died!
ply.Infected = false – At least he’s not infected anymore
end

function GM:PlayerHurt( victim, attacker ) – Ouch!
local infectchance = math.random (1,2) – Creating infectchance

if infectchance == 1 then --If our player has a chance to be infected
	if attacker:IsNPC() then -- And if the attacker is an NPC
			
		victim.Infected = true -- Declare the player infected.
		timer.Simple( 6, Infection(victim) ) -- In 6 seconds, call the function Infection and pass it the victim.
	end
end

end

local function Infection(ply) – This function has been called on a player!
if ply.Infected == true then – If the player is still infected at this time then
ply:TakeDamage(1) – Hurt him.
timer.Simple( 6, Infection(ply) ) – And check again in another 6 seconds.
end
end
[/lua]

Pretty basic and not tested but you can probably expand on this. :slight_smile:
A few things you’ll probably want to add :

  • An entity/command that sets Player.Infected to false so that it’s possible to be cured.
  • Filtering which NPCs should give the disease?
  • Maybe some effects, I dunno. :slight_smile:

Thanks again for the response Crazy Quebec. I am still having a problem with the code however D:

[lua]function GM:PlayerHurt( victim, attacker )
local infectchance = math.random (1,2)
if attacker:IsNPC() then
if infectchance == 1 then
victim.Infected = true
timer.Simple(6, Infection(victim))
end
end
end

function Infection(ply)
if ply.Infected == true then
ply:TakeDamage(1)
timer.Simple(6, Infection(ply))
end
end

function GM:InitialSpawn(ply)
ply.Infected = false
end

function PlayerDeath(ply)
ply.Infected = false
end[/lua]

I get these errors:

ERROR: GAMEMODE:‘EntityTakeDamage’ Failed: stack overflow
ERROR: GAMEMODE:‘EntityTakeDamage’ Failed: stack overflow
error in error handling
error in error handling
error in error handling
ERROR: GAMEMODE:‘PlayerHurt’ Failed: error in error handling

If I make Infection(ply) a local function, then the timer in PlayerHurt sees Infection as a nil value.
This piece of code is one nightmare after another, and I truly appreciate you trying to help me.

Thanks.
Todrak

EDIT:
Also, if this in any way helps, when the stack overflow errors occur, the player is instantly killed. I am assuming this is because the code doesn’t wait for the timer to finish before executing the next piece for some reason, and so kills the player. Thanks again.

bump? It would be really helpful if I could get this D:

Stack overflow is again, an infinate loop. Not sure where though.

Sorry that I didn’t look into it earlier, it was a really simple error coming from me. I was calling Infection the wrong way…
It should’ve been
timer.Simple(6, Infection, victim)
and not
timer.Simple(6, Infection(victim))

A simple matter of reading the wiki really. :frowning:

Tested and working code :
[lua]function GM:PlayerHurt( victim, attacker )
local infectchance = math.random (1,2)
if attacker:IsNPC() then
if infectchance == 1 and !victim.Infected then – Also added a check to see if the player is already infected. If this isn’t there you can get multilple infections at a time, kinda cool incase you want to keep that.
victim.Infected = true
timer.Simple(6, Infection, victim)
end
end
end

function GM:PlayerInitialSpawn(ply)
ply.Infected = false
end

function GM:PlayerDeath(ply)
ply.Infected = false
end

function Infection(ply)
if ply.Infected == true then
ply:TakeDamage(1)
timer.Simple(6, Infection, ply)
end
end[/lua]

Now remember to cure the infection all you need is


Player.Infected = false

Thanks, that works great. This will make my schema much better!