ThingCount

Archive of the old editing forum
Forum rules
Before asking on how to use a ZDoom feature, read the ZDoom wiki first. This forum is archived - please use this set of forums to ask new questions.
User avatar
*Viper*
Posts: 88
Joined: Tue Jul 15, 2003 4:47 pm
Contact:

ThingCount

Post by *Viper* »

Is there any way to count the number of things on a map by using their actor names?

Something like ThingCount("StealthDoomImp",0) perhaps?

I've already tried that, and since it needs an integer instead of a string, it doesn't work, of course :)
User avatar
HotWax
Posts: 10002
Joined: Fri Jul 18, 2003 6:18 pm
Location: Idaho Falls, ID

Post by HotWax »

There should be constants defined for most Things somewhere in the ACS library files. I haven't actually used ACS myself, so I can't tell you if the stealth monsters are included or where to find them if they are. Look for lines that look something like this:

#define STEALTHDOOMIMP 187
#define STEALTHDEMON 188
#define STEALTHSPECTRE 189

Yes, I made those numbers and names up. And #define might not be the proper keyword. I'm sure somebody with more intimate knowledge of scripting will be able to help you out. :)

Assuming I was actually right though, the function would look like this:

ThingCount(STEALTHDOOMIMP, 0);

Note the lack of quotes, as we're providing an integer, not a string. At compile time, a defined variable will be replaced with the number it represents. In other words, to the compiler the above looks like:

ThingCount(187, 0);

But you get the benefit of using the easy name, which makes your script much clearer and easier to write.
Cyb
Posts: 912
Joined: Tue Jul 15, 2003 5:12 pm

Post by Cyb »

User avatar
*Viper*
Posts: 88
Joined: Tue Jul 15, 2003 4:47 pm
Contact:

Post by *Viper* »

Yeah, I know about the numbers and #defined names. I guess I should have been more specific. That spawnables list only lists things for doom. I would need to check for things from all games.

What I am trying to do is make some kind of RPG library script and insert it into all the levels of the original IWADs.

So what I would need would be some way to count things that are already on the map (doom, hexen, heretic, or strife) without using tags. Is there any command like thingcount, but it would use the actor strings, like the Spawn() command uses for its first argument?
User avatar
HotWax
Posts: 10002
Joined: Fri Jul 18, 2003 6:18 pm
Location: Idaho Falls, ID

Post by HotWax »

I'm confused. Doesn't the Spawn command take an integer as well?
User avatar
Virgil
Posts: 154
Joined: Sun Sep 28, 2003 10:01 pm

Post by Virgil »

I'm assuming you want to know #1?

Thingcount() can count just about anything. If the TID field is zero, thingcount will disregard TID as a search criteria. Same with monster type. The format is:

int thingcount(int monster type, int TID);

1) count all the monsters CURRENTLY on the map, regardless of type or TID:
thingcount(0, 0);

2) count all the monsters on the map with a specific TID, regardless of what type they are:
thingcount(0, <the specific TID>);

3) count all of a certain type of monster, regardless of TID:
thingcount(<monster type>, 0);

You can easily combine different thingcounts. If I wanted to count all the imps, add to that demons with a TID of 10 and store it into variable x, I'd go:

x = thingcount(T_IMP, 0) + thingcount(T_DEMON, 10);

I swear, this little function can be a lifesaver.
User avatar
*Viper*
Posts: 88
Joined: Tue Jul 15, 2003 4:47 pm
Contact:

Post by *Viper* »

HotWax: There are a few different versions of spawn functions. There's the Thing_Spawn commands, which do take the integer for the monster type, but there are also just Spawn commands (which I believe are new to the 2.x versions). From the editing reference internal function page:
int spawn(str actorType, fixed x, fixed y, fixed z, opt int tid, opt int angle);
Spawns an actor at a specific location on the map. For a list of things you can spawn, type dumpclasses actor
Virgil: I have used the thingcount function plenty of times. What I'm looking for is a function like thingcount, but it will take an actor name string out of the list you get when you type dumpclasses actor in the console, instead of the pre-defined integer constants in zdefs.acs.


I am beginning to think that there is no such function (or nobody knows about it :) )
User avatar
Graf Zahl
Lead GZDoom+Raze Developer
Lead GZDoom+Raze Developer
Posts: 49234
Joined: Sat Jul 19, 2003 10:19 am
Location: Germany

Post by Graf Zahl »

There is none. If you have to count objects of other types you have to do it with Tids. This is a little more complicated, however because you obviously cannot assign Tids to objects that are spawned by actors in the game (like missiles)
User avatar
*Viper*
Posts: 88
Joined: Tue Jul 15, 2003 4:47 pm
Contact:

Post by *Viper* »

I don't suppose a version of thingcount has been implemented that can take the actual actor names yet, has it?

I have scanned through rh-log.txt and the wiki, and I didn't find anything. I decided to post here in case I missed it and someone here knows how (if) it can be done.
User avatar
Graf Zahl
Lead GZDoom+Raze Developer
Lead GZDoom+Raze Developer
Posts: 49234
Joined: Sat Jul 19, 2003 10:19 am
Location: Germany

Post by Graf Zahl »

No, it hasn't.
Maybe this will speed things up. I quickly hacked this together without testing though...

Code: Select all

int DLevelScript::DoThingCount (const TypeInfo * kind, int tid)
{
	AActor *actor;
	int count = 0;

	if (tid)
	{
		FActorIterator iterator (tid);
		while ( (actor = iterator.Next ()) )
		{
			if (actor->health > 0 &&
				(kind == NULL || actor->IsA (kind)))
			{
				count++;
			}
		}
	}
	else
	{
		TThinkerIterator<AActor> iterator;
		while ( (actor = iterator.Next ()) )
		{
			if (actor->health > 0 &&
				(kind == NULL || actor->IsA (kind)))
			{
				count++;
			}
		}
	}
	return count;
}

int DLevelScript::ThingCount (int type, int tid)
{
	AActor *actor;
	const TypeInfo *kind;
	int count = 0;

	if (type >= MAX_SPAWNABLES)
	{
		return 0;
	}
	else if (type > 0)
	{
		kind = SpawnableThings[type];
		if (kind == NULL)
			return 0;
	}
	else
	{
		kind = NULL;
	}
	
    return DoThingCount(kind, tid);
}

int DLevelScript::ThingCountName (const char * type, int tid)
{
    const TypeInfo * info = NULL;

    if (type != NULL && type[0]!=0)
    {

	    info = TypeInfo::FindType (type);
	    if (info == NULL && type[0]!=0)
	    {
		    Printf ("ACS: I don't know what %s is.\n", type);
	    }
    }
    return DoThingCount(info, tid);
}

Code: Select all

		case PCD_THINGCOUNTNAME:
			STACK(2) = ThingCountName (FBehavior::StaticLookupString (STACK(2)), STACK(1));
			sp--;
			break;

Of course it is still missing all header definitions and the function definition in ACC.
User avatar
Chilvence
Posts: 1647
Joined: Mon Aug 11, 2003 6:36 pm
Contact:

Post by Chilvence »

I fudged this together with ACS as well, you may find it useful.

Code: Select all


function int T_GetNumForName ( str Classname ) //nostalgia ;)
{
	switch(Classname)
	{
		case "ZombieMan":	return T_ZOMBIE;
		case "ShotgunGuy":	return T_SHOTGUY;
		case "ChaingunGuy":	return T_CHAINGUY;
		case "DoomImp":		return T_IMP;
		case "Demon":		return T_DEMON ;
		case "Spectre":		return T_SPECTRE;
		case "LostSoul":	return T_LOSTSOUL;
		case "Cacodemon":	return T_CACODEMON;
		case "PainElemental":	return T_PAINELEMENTAL;
		case "Fatso":		return T_MANCUBUS;
		case "Revenant":	return T_REVENANT;
		case "Archvile":	return T_VILE;
		case "BaronOfHell":	return T_BARON;
		case "HellKnight":	return T_HELLKNIGHT;
		case "Cyberdemon":	return T_CYBERDEMON;
		case "Arachnotron":	return T_ARACHNOTRON;
//		case "ADecorateMons":	return 123; 		//like so, just to be clear
	}
	print(s:"What the hell is a ",s:Classname, s:" , eh?"); 	//error you get if you spell it wrong. 
	return 0;
}

function int StringThingCount ( str Classname, int TID )
{
	return ThingCount(T_GetNumForName(Classname), TID);
}
As you can see, I've just matched up the classes I wanted to their spawn id's, so its useless for actors that dont have one. Also, you'll need to do what I've done above for every actor type you need to count.

Apart from that, just use StringThingCount() instead of ThingCount()
User avatar
Graf Zahl
Lead GZDoom+Raze Developer
Lead GZDoom+Raze Developer
Posts: 49234
Joined: Sat Jul 19, 2003 10:19 am
Location: Germany

Post by Graf Zahl »

That doesn't help much because you would use such a function mostly for monsters that do not have a spawn ID.
User avatar
Chilvence
Posts: 1647
Joined: Mon Aug 11, 2003 6:36 pm
Contact:

Post by Chilvence »

Yep, it is pretty much useless. I did actually make good use of it though, because I wanted a script that could keep track of every monster using classname, since I was using spawn() alot.
User avatar
*Viper*
Posts: 88
Joined: Tue Jul 15, 2003 4:47 pm
Contact:

Post by *Viper* »

Yeah... Doesn't quite help for trying to count, for example, Heretic's T_MUMMY in a doom game. You will count Demons instead. :)

I guess all I can do is wait and see if that function gets added or not. I guess one of the main reasons I would like something like this is my Arena 5 level that I made a while back. It uses a separate tag for every type of monster. That is around 80 tags that could be better used elsewhere :)

Also, it would help if you would want to attach a library script to already-made levels. Like some kind of RPG/Experience script.
User avatar
Chilvence
Posts: 1647
Joined: Mon Aug 11, 2003 6:36 pm
Contact:

Post by Chilvence »

If you really need it, you could just make a new mummy class in heretic.
Locked

Return to “Editing (Archive)”