ACS Looping Woes

Ask about ACS, DECORATE, ZScript, or any other scripting questions here!

Moderator: GZDoom Developers

Forum rules
Before asking on how to use a ZDoom feature, read the ZDoom wiki first. If you still don't understand how to use a feature, then ask here.

Please bear in mind that the people helping you do not automatically know how much you know. You may be asked to upload your project file to look at. Don't be afraid to ask questions about what things mean, but also please be patient with the people trying to help you. (And helpers, please be patient with the person you're trying to help!)
User avatar
Doominer441
Posts: 206
Joined: Thu Oct 24, 2013 9:04 pm

ACS Looping Woes

Post by Doominer441 »

Hello

I'm working on a script thats meant to monitor the players sanity (which is measured by an invisible dummy inventory item), and cause effects as it gets lower and lower. Unfortunately, this has turned into a nightmare as the loops I'm using will not behave in the way I intend, no matter what I do.

In short, it consists of a "While" loop that checks the sanity item against a set of 6 "If" statements, then if it meets any of those statements, checks a random variable to determine which effect will be played.

The main "While" loop seems to work fine, its the inner loops that check the SanityEffectWeight variable that are the (current) problem. I set up test messages to play to ensure its cycling through the different effects correctly, but the only problem is it never cycles through them. It only iterates through the first "If" statement, despite my test message showing the SanityEffectWeight should make the other effects play, none of them ever do.

I'm at a complete loss of how to fix this, since it worked before I started adding effects, but the loops should be no different no compared to how they were previously. Could anyone please advise me?

Code: Select all

script "SanityLoop" ENTER
{
	While(TRUE)
		{
			int Sanity = CheckInventory("Sanity");
			int SanityEffectWeight = Random(1, 6);
			Delay(35);
			If(Sanity >= 80)
				{
					Restart;
				}
			If(Sanity < 80 && Sanity >= 60)
				{
					//Delay(35 * 1);
					Print(i:SanityEffectWeight);
					If(SanityEffectWeight == 1 || 2)
						{
							//AmbientSound("sanity/effect/randomsound/minor", 48);
							HudMessage(s:"Baa Baa"; HUDMSG_PLAIN|HUDMSG_LOG, 1, CR_GREEN, 0.5, 0.5, 3.0);
							Restart;
						}
					If(SanityEffectWeight == 3 || 4)
						{
							HudMessage(s:"Black Sheep"; HUDMSG_PLAIN|HUDMSG_LOG, 1, CR_GREEN, 0.5, 0.5, 3.0);
							Restart;
						}
					If(SanityEffectWeight == 5 || 6)
						{
							HudMessage(s:"I aint payed to do this"; HUDMSG_PLAIN|HUDMSG_LOG, 1, CR_GREEN, 0.5, 0.5, 3.0);
							FadeTo(0, 0, 0, 0.25, 1.50);
							Delay(35 * 1.5);
							FadeTo(0, 0, 0, 0.0, 1.50);
							Restart;
						}
				}
			If(Sanity < 60 && Sanity >= 40)
				{
					HudMessage(s:"you have moderate sanity loss"; HUDMSG_PLAIN|HUDMSG_LOG, 1, CR_GREEN, 0.5, 0.5, 3.0);
					AmbientSound("sanity/effect/flicker", 63);
					Restart;
				}
			If(CheckInventory("Sanity") < 40 && CheckInventory("Sanity") >= 20)
				{
					HudMessage(s:"you have major sanity loss"; HUDMSG_PLAIN|HUDMSG_LOG, 1, CR_GREEN, 0.5, 0.5, 3.0);
					AmbientSound("sanity/effect/flicker", 63);
					Restart;
				}
			If(CheckInventory("Sanity") < 20 && CheckInventory("Sanity") >= 1)
				{
					HudMessage(s:"you have severe sanity loss"; HUDMSG_PLAIN|HUDMSG_LOG, 1, CR_GREEN, 0.5, 0.5, 3.0);
					AmbientSound("sanity/effect/flicker", 63);
					Restart;
				}
			If(CheckInventory("Sanity") == 0)
				{
					HudMessage(s:"you have gone insane"; HUDMSG_PLAIN|HUDMSG_LOG, 1, CR_GREEN, 0.5, 0.5, 3.0);
					AmbientSound("sanity/effect/flicker", 63);
					Restart;
				}
		}
}
User avatar
Player701
 
 
Posts: 1697
Joined: Wed May 13, 2009 3:15 am
Graphics Processor: nVidia with Vulkan support

Re: ACS Looping Woes

Post by Player701 »

First of all, you are mixing two loop concepts here: the while loop and a loop implemented via restart statements. While it is most likely going to work, I still suggest that you use either one or the other to avoid potential bugs in the future.

I consider while to be a "cleaner" approach, but in your case restart might actually provide better readability due to less indentation. Note that you only need one restart statement at the end of your script. You can also make use of the else if construct for more clarity and brevity:

Code: Select all

int Sanity = CheckInventory("Sanity");
int SanityEffectWeight = Random(1, 6);
Delay(35);

if (Sanity < 80 && Sanity >= 60)
{
    ...
}
else if (Sanity >= 40)
{
    ...
}
else if (Sanity >= 20)
{
    ...
}
else if (Sanity >= 1)
{
    ...
}
else
{
    ...
}

Restart;
As for why your inner ifs don't work properly, the problem is with your expression syntax:

Code: Select all

If(SanityEffectWeight == 1 || 2)
This will evaluate to "true" if either SanityEffectWeight == 1 or 2 evaluates to true. Since 2 is considered to be a truthy value, this expression always evaluates to "true".

The correct syntax is: If(SanityEffectWeight == 1 || SanityEffectWeight == 2).

Alternatively, use a chain of else ifs like in the previous example, and compare with <=:

Code: Select all

if (SanityEffectWeight <= 2) // 1 or 2
{
    ...
}
else if (SanityEffectWeight <= 4) // 3 or 4
{
    ...
}
else // 5 or 6
{
    ...
}
User avatar
Doominer441
Posts: 206
Joined: Thu Oct 24, 2013 9:04 pm

Re: ACS Looping Woes

Post by Doominer441 »

I'm sorry for how long it took me to get back over this, but thank you, I really appreciated the help! My sanity script is fully functional now!

Return to “Scripting”