Void() NextLevel

Discuss programming in the QuakeC language.
Post Reply
Stealth Kill
Posts: 83
Joined: Fri Dec 29, 2006 12:34 pm

Void() NextLevel

Post by Stealth Kill »

Hi,

I need some help my maps arent changing when aim_aztec ends
it changes to aim_usp but when aim_usp ends it changes again to aim_aztec.

Code: Select all

void() NextLevel =
{
	local entity o;

	if (mapname == "aim_aztec")
	{
		if (!cvar("registered"))
		{
			mapname = "aim_usp";
		}
		else if (!(serverflags & 1))
		{
			mapname = "aim_usp";
			serverflags = serverflags | 1;
		}
		else if (!(serverflags & 2))
		{
			mapname = "gg_mini_dust2";
			serverflags = serverflags | 2;
		}
		else if (!(serverflags & 4))
		{
			mapname = "fy_snow";
			serverflags = serverflags | 4;
		}

		else if (!(serverflags & 8))
		{
			mapname = "fy_iceworld";
			serverflags = serverflags | 8;
		}
		else if (!(serverflags & 10))
		{
			mapname = "aim_ak_colt";
			serverflags = serverflags | 10;
		}
		else if (!(serverflags & 12))
		{
			mapname = "aim_ak_colt";
			serverflags = serverflags | 12;
		}
		else if (!(serverflags & 14))
		{
			mapname = "de_dust2";
			serverflags = serverflags | 14;
		}
		o = spawn();
		o.map = mapname;
	}
	else
	{
		// find a trigger changelevel
		o = find(world, classname, "trigger_changelevel");

		// go back to start if no trigger_changelevel
		if (!o)
		{
			mapname = "aim_aztec";
			o = spawn();
			o.map = mapname;
		}
	}

	nextmap = o.map;
	gameover = TRUE; 
	
	if (o.nextthink < time)
	{
		o.think = execute_changelevel;
		o.nextthink = time + 0.1;
	}
};
Preach
Posts: 122
Joined: Thu Nov 25, 2004 7:20 pm

Post by Preach »

Ok, the problem here is that you need to understand what the & operator does - it's called the AND operator. It's more like an operation like + or * than a comparison like <, because it takes two input numbers and returns a third as an output. It first converts the numbers on either side of it to binary(for purposes of the calculation). It then takes the first binary digit of each input number. If both digits are equal to 1, then it puts a 1 in the first digit of the output number.

This process is repeated for each digit of the input numbers, then the output is sent back. Then when you apply the ! operation, if the output number was non zero then it sends a zero to the if statement, and if the output was zero then it changes to one. As usual, a 0 means false and a 1 means true.

The important thing to notice is what's different about the first four tests of serverflags than the remaining ones. When you convert 1,2,4 and 8 to binary, they each only have a single digit which is 1, the first, second, third and fourth digit respectively. So the statement

Code: Select all

      else if (!(serverflags & 1))
      {
         mapname = "aim_usp";
         serverflags = serverflags | 1;
      } 
Means "If the first digit of serverflags is not set to 1, make the mapname aim_usp, and set the first digit of serverflags to 1."

(It should be mentioned that the | operation is called OR, and is very similar to &. The difference is that it sets a digit to 1 if either of the input digits are 1.)


The problem with the later comparisons is that 10, 12 and 14 are not single digits in binary. 10 = 8 + 2, so when you get to that point in the rotation, the digits of 10 have already be added to serverflags. You could change these numbers to 16, 32 and 64(the next single digit numbers in binary) and your rotation should work, at least until you get aztec, when you might need to reset the serverflags to 0.


[pedants who are going to tell me that comparisons like > also takes two values and returns a third - the real point is that they only return boolean values, but & can return any integer]
Stealth Kill
Posts: 83
Joined: Fri Dec 29, 2006 12:34 pm

Post by Stealth Kill »

Thanks for the fast answer :D :D
Spike
Posts: 2914
Joined: Fri Nov 05, 2004 3:12 am
Location: UK
Contact:

Post by Spike »

Preach wrote: [pedants who are going to tell me that comparisons like > also takes two values and returns a third - the real point is that they only return boolean values, but & can return any integer]
(var&1) that returns a boolean too - the exact same values that > will give you. :P

And what is a boolean anyway? something that is true or false, that is, something that is non-zero or zero. If fact, in many basics, 'true' is actually -1.
*Everything* is a boolean (in QuakeC - same is true in C except for structs), but remembering the truth of that will not make you a good coder. Logic like: if (a = (!!b != c) < d) will have you shot, even if it is valid and does what you may desire in any specific case.

((!!a) & (!!b)) == (a && b)
(!!(a | b)) == (a || b)

Readability is king! :P
FrikaC
Site Admin
Posts: 1026
Joined: Fri Oct 08, 2004 11:19 pm

Post by FrikaC »

Does fteqcc have a double OP_NOT optimization, Spike? I suppose it's not technically identical, maybe only want to do it for triple nots.
mh
Posts: 2292
Joined: Sat Jan 12, 2008 1:38 am

Post by mh »

Structs can be boolean too. :P (Or at least pointers to structs, but that's not the same data type...)

A few more important things:

If you're testing a single flag using bitwise comparison, then stick with powers or 2. A non power of 2 (like 10 or 14) is still a valid test, but represents combinations of flags.

Let me explain better.

In binary, 14 is 1110. This is the equivalent of 1000 + 100 + 10, or (converting back to decimal) 8 + 4 + 2. 14. So a test for & 14 is a shorthand way for testing if it's all 3 of & 8, & 4 and & 2.

Any binary number with a single 1 in it is always a power of 2 (even 1 is just 2 to the power of 0).
We had the power, we had the space, we had a sense of time and place
We knew the words, we knew the score, we knew what we were fighting for
redrum
Posts: 410
Joined: Wed Mar 28, 2007 11:35 pm
Location: Long Island, New York

Post by redrum »

Is there a way to set up code for map changes depending on the number of clients that are in the game?
Welcome to the Overlook Hotel: The-Overlook-Hotel.game-server.cc
Spike
Posts: 2914
Joined: Fri Nov 05, 2004 3:12 am
Location: UK
Contact:

Post by Spike »

FrikaC wrote:Does fteqcc have a double OP_NOT optimization, Spike? I suppose it's not technically identical, maybe only want to do it for triple nots.
It doesn't (I think..). :(

However, you can use hexenc notation:
if not (blah) {}

but just !!blah without an if statement... no. but its not very common either.
just detect type and expand into (a != 0) as apropriate I guess. The not operator is type specific, so switching it for a type specific equality comparison of some kind should be safe.
Is there a way to set up code for map changes depending on the number of clients that are in the game?
Urm... count the number of players?
scar3crow
InsideQC Staff
Posts: 1054
Joined: Tue Jan 18, 2005 8:54 pm
Location: Alabama

Post by scar3crow »

Is there a way to set up code for map changes depending on the number of clients that are in the game?
I'd say when the intermission screen hits, check the client load that aren't spectators, and then have that divided up into categories, with the maps your server runs in categories as well. If there are 1-3 players on the server, pick a random map from the 1-3player list, which could include maps like dm1, dm4, e1m7... If theres 4-8, dm2, dm5, dm6, If theres 8-16, dm2, dm3, e4m8 so on.

I believe the NQ server quake.shmack.net does this. Granted its with the rarely fun RuneQuake with tons of new runes, but it is nice to see the server adjust to the player load.
Post Reply