Jump to content

Doom Monster Death Tally/Death Counter


Recommended Posts

This is probably a Newbie Question and all, but at this point i don't care, so il'l just explain my problem and hope someone could perhaps give me the answer i'm looking for. Anyways so I've been working on a doom wad for quite a bit, and came up with the idea of making a monster-battling arena, and well the map part of this is finished, though sadly the death counter seems to have an issue, though first il'l explain how it works. Basically your'e supposed to fight 4 waves of demons, with each wave dead lowering the height of the acid, and the final miniboss lowering the gates leading to a path further. This gate is below the acid if it helps. The death tally almost works perfectly. Each time you kill a monster, the monster count gets printed on the screen (i will make this a bit more detailed later), and when it reaches the needed count the acid does lower and the next wave teleports in. All fine and dandy. Well i came into a tad bit of a problem, this problem being that if you kill two monsters at once it registers the double-kill as one single point, not two. I'm pretty sure the solution for this just flew over my head considering i'm quite new to scripting in zdoom ACS, or hell, any other coding language. Here's the script btw

 

 

script 6 (void)
{
    points = points + 1;
    print(i:points);
       if (points == 9)
    {
    Ceiling_RaiseByValueTimes8 (145, 8, 20);
    Ceiling_LowerByValue (147, 2, 20);
    }
}

script 7 (void)
{
    points = points + 1;
    print(i:points);
       if (points == 18)
    {
    Ceiling_RaiseByValueTimes8 (150, 8, 16);
    Ceiling_LowerByValue (147, 2, 20);

    }
}

script 8 (void)
{
    points = points + 1;
    print(i:points);
       if (points == 27)
    {
    Ceiling_RaiseByValueTimes8 (151, 8, 16);
    Ceiling_LowerByValue (147, 2, 20);

    }
}

script 9 (void)
{
    points = points + 1;
    print(i:points);
       if (points == 36)
    {
    Ceiling_RaiseByValueTimes8 (152, 8, 20);
    Ceiling_LowerByValue (147, 2, 40);
    Floor_LowerByValueTimes8 (153, 2, 12);
    }
}


each script is used for a new wave of monsters. The miniboss thing isn't set up yet due to this problem making it near-impossible to even get to that point if you don't give it attention. The ceiling raise by value is simply for the doors in my monster spawner closets. The ceiling lower by value is for the acid pit, and the floor lower by value at the end is for that gate. I will make sure to also add some pictures as a reference.

Screenshot_Doom_20230824_211334.png

Screenshot_Doom_20230824_211342.png

Screenshot_Doom_20230824_211349.png

Share this post


Link to post

Pretty "heavy" way to deal with this thing x)

 

You have several solutions:

  1. If you want to stick to this way: if you use ACS_ExecuteAlways on the monsters (I believe you're calling the script from each monster for every wave), should fix the problem.

Otherwise, if you want cleaner way to do things:

  1. Just give the monsters a different tid for each wave (for example: monsters of the 1st wave with tid of 1, monsters of 2nd wave tid of 2 etc.), then you could just call a script with multiple loops like this:
    script "Waves" (void) { //You can let the player activate the script by crossing a line or whatever
    	int points = 0;
    	while (ThingCount(T_NONE, 1) > 0) { //until there are at least 1 monster with a tid of 1 alive
    		points++; //better than points = points + 1;
    		Print(i:points);
    		Delay(35); //wait and repeat every second (change the tcs to whatever you like)
        	}
    	Ceiling_RaiseByValueTimes8(....); //when everyone's dead, do your stuff
    	//Fall straight through the next wave loop
    	while (ThingCount(T_NONE, 2) > 0) { //until there are at least 1 monster with a tid of 2 alive
    		points++;
    		Print(i:points);
    		Delay(35); //wait and repeat every second
        	}
    	...etc.
    }

     

  2. Just use the Doom monster counter:
     

    script "Waves" (void) {
    	int points = GetLevelInfo(LEVELINFO_KILLED_MONSTERS); //it directly retrieves the monster count
    	while(points < GetLevelInfo(LEVELINFO_TOTAL_MONSTERS)) { //while points is lower than the total number of monsters in the map
    		Print(i:points);
    		if(points == X) { //with X being the number of dead monsters of your choice
    			Ceiling_LowerByValueTimes8(); //do your stuff;
            	}
    		if(points == Y) {
    			Ceiling_LowerByValueTimes8(); //do more stuff;
            	}
    		etc.
        	}
    	Floor_LowerByValueTimes8(); //When everyone's dead, do the end stuff
    }

     

Share this post


Link to post

Thanks a lot for responding! Though sorry for bothering you again... i ran into a problem. Again somehow. The script compiles, and i keep getting the runaway script error message when setting it off, but i got the runaway script error. So i added the delay, the error message doesen't pop up, but sadly none of the if statements run. Here's the code

 

script 6 (void) {
     int points = GetLevelInfo(LEVELINFO_KILLED_MONSTERS); //it directly retrieves the monster count
     while(points < GetLevelInfo(LEVELINFO_TOTAL_MONSTERS))
     delay (1);
     {
        if(points == 9)
        {
            Ceiling_LowerByValueTimes8(147, 2, 20);
            Ceiling_RaiseByValueTimes8(145, 8, 20);
            }
        if(points == 18) {
            Ceiling_LowerByValueTimes8(147, 2, 20);
            Ceiling_RaiseByValueTimes8(150, 2, 20);
            }
        if(points == 27) {
            Ceiling_LowerByValueTimes8(147, 2, 20);
            Ceiling_RaiseByValueTimes8(151, 2, 20);
            }
            }
            }

Thanks a lot again for helping.

Share this post


Link to post

Delay() needs to be called inside the while loop, you can't "open" the loop if you call stuff before opening the brackets.

Also, sorry, I made a mistake in the scripts, dumb me.

You also have to set the points value inside the while loop or it won't update.

So something like this:

script 6 (void) {
     int points = 0; 
     while(points < GetLevelInfo(LEVELINFO_TOTAL_MONSTERS))
     {
       	points = GetLevelInfo(LEVELINFO_KILLED_MONSTERS);
        if(points == 9)
        {
            Ceiling_LowerByValueTimes8(147, 2, 20);
            Ceiling_RaiseByValueTimes8(145, 8, 20);
            }
        if(points == 18) {
            Ceiling_LowerByValueTimes8(147, 2, 20);
            Ceiling_RaiseByValueTimes8(150, 2, 20);
            }
        if(points == 27) {
            Ceiling_LowerByValueTimes8(147, 2, 20);
            Ceiling_RaiseByValueTimes8(151, 2, 20);
    	}
       Delay(35); //No need to call it every tic.
    }
}

Untested again, I hope I didn't write something else wrong D:

Share this post


Link to post
18 hours ago, Kan3 said:

script 6 (void) {
     int points = 0; 
     while(points < GetLevelInfo(LEVELINFO_TOTAL_MONSTERS))
     {
       	points = GetLevelInfo(LEVELINFO_KILLED_MONSTERS);
        if(points == 9)
        {
            Ceiling_LowerByValueTimes8(147, 2, 20);
            Ceiling_RaiseByValueTimes8(145, 8, 20);
            }
        if(points == 18) {
            Ceiling_LowerByValueTimes8(147, 2, 20);
            Ceiling_RaiseByValueTimes8(150, 2, 20);
            }
        if(points == 27) {
            Ceiling_LowerByValueTimes8(147, 2, 20);
            Ceiling_RaiseByValueTimes8(151, 2, 20);
    	}
       Delay(35); //No need to call it every tic.
    }
}

Untested again, I hope I didn't write something else wrong D:

This script has a couple of potential problems:

  • The points conditions have to match the exact amount for the actions to take place. So if for example 8 monsters are killed, and then before the next check (after 35 tics) two more are killed, points will be 10, and the condition for 9 points will never happen.
  • The actions will trigger multiple times if the points amount stays valid. So if for example 9 monsters have been killed, and the player does not kill any more, then the actions for points 9 condition will keep repeating every second.
  • In case any Arch-viles or Pain Elementals are used, then revived monsters or spawned lost souls could make these kill counts get reached sooner than planned.

I think it would be safer to use a script with ThingCount and tagged monsters, like this for example:
 

Spoiler

// Monster tags/tids for each wave.
#define TID_WAVE_1 1
#define TID_WAVE_2 2
#define TID_WAVE_3 3

script 6 OPEN // Wave script
{
	// Wait for 1. Wave to die
	while(ThingCount(T_NONE, TID_WAVE_1) > 0) Delay(35);

	Ceiling_LowerByValueTimes8(147, 2, 20);
	Ceiling_RaiseByValueTimes8(145, 8, 20);

	// Wait for 2. Wave to die
	while(ThingCount(T_NONE, TID_WAVE_2) > 0) Delay(35);

	Ceiling_LowerByValueTimes8(147, 2, 20);
	Ceiling_RaiseByValueTimes8(150, 2, 20);

	// Wait for 3. Wave to die
	while(ThingCount(T_NONE, TID_WAVE_3) > 0) Delay(35);

	Ceiling_LowerByValueTimes8(147, 2, 20);
	Ceiling_RaiseByValueTimes8(151, 2, 20);
}

script 7 OPEN //Death tally script - Change this from OPEN to (void) if you don't want the tally to display from the beginning of the map.
{
	bool w1done = FALSE;
	bool w2done = FALSE;
	bool w3done = FALSE;
	int previous_points = 0;
	int points = 0;

	while(TRUE)
	{
		points = GetLevelInfo(LEVELINFO_KILLED_MONSTERS);

		if (points != previous_points) // If points have changed
		{
			previous_points = points; // Update previous_points

			if ((w1done == FALSE) && (ThingCount(T_NONE, TID_WAVE_1) == 0))
			{
				w1done = TRUE;
				PrintBold(s:"Wave 1 Clear!\n", s:"Points: ", d:points);
			}
			else if ((w2done == FALSE) && (ThingCount(T_NONE, TID_WAVE_2) == 0))
			{
				w2done = TRUE;
				PrintBold(s:"Wave 2 Clear!\n", s:"Points: ", d:points);
			}
			else if ((w3done == FALSE) && (ThingCount(T_NONE, TID_WAVE_3) == 0))
			{
				w3done = TRUE;
				PrintBold(s:"Wave 3 Clear!\n", s:"Points: ", d:points);
			}
			else
			{
				PrintBold(s:"Points: ", d:points);
			}
		}

		Delay(35);
	}
}

 

 

Share this post


Link to post

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...