Node graphs for deathmatch maps

From Valve Developer Community
Revision as of 12:30, 23 April 2008 by Winston (talk | contribs)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

If a mod wishes to use maps that have no nodegraph (e.g. HL2DM maps), and has no access to the uncompiled .vmf map (e.g. HL2DM maps), then any NPCs they spawn are going to be severely limited in their navigation ability. This article describes a technique for creating a node graph for an already-compiled map, by manually saving node coordinates to a text file, then building a complete .ain node graph from that text file when reloading the map.

It is designed not to interfere with existing node graphs, or the map_edit node placement process. The first section will describe how to load a text file containing coordinates, create nodes at each specified point, then build & save a node graph. The second section will cover how to create the text file list of coordinates in the first place.


Graph creation

At the end of the public section of ai_networkmanager.h, add the following function:

void	SetRebuildNeeded(bool b=true) { m_bNeedGraphRebuild = b; }

We are going to need a way of specifying a rebuild (and save) are needed from a static context, so this function is required.

Around line 892 of ai_networkmanager.cpp, you should see the following if block:

	if ( CAI_NetworkManager::IsAIFileCurrent( STRING( gpGlobals->mapname ) ) )
	{
		pNetwork->LoadNetworkGraph(); 
		if ( !g_bAIDisabledByUser )
		{
			CAI_BaseNPC::m_nDebugBits &= ~bits_debugDisableAI;
		}
	}

Immediately after this block, add this else block:

	else
	{
		char szNodeTextFilename[MAX_PATH];// text node coordinate filename
		Q_snprintf( szNodeTextFilename, sizeof( szNodeTextFilename ),
				"maps/graphs/%s%s.txt", STRING( gpGlobals->mapname ), GetPlatformExt() );

		CUtlBuffer buf( 0, 0, CUtlBuffer::TEXT_BUFFER );
		if ( filesystem->ReadFile( szNodeTextFilename, "game", buf ) )
		{
			Msg("Parsing .txt node file!\n");		
			if (!buf.Size())
				return;

			const int maxLen = 64;
			char line[ maxLen ];
			CUtlVector<char*> floats;
			int num = 0;

			// loop through every line of the file, read it in
			while( true )
			{
				buf.GetLine( line, maxLen );
				if ( Q_strlen(line) <= 0 )
					break; // reached the end of the file

				// we've read in a string containing 3 tab separated floats
				// we need to split this into 3 floats, which we put in a vector
				V_SplitString( line, "	", floats );
				Vector origin( atof( floats[0] ), atof( floats[1] ), atof( floats[2] ) );
				//Msg("Parsed Vector(%.2f, %.2f, %.2f)\n",origin.x,origin.y,origin.z);

				floats.PurgeAndDeleteElements();

				// now we want to create a CNodeEnt (info_node) at the location these coordinates describe
				CBaseEntity *pNode = CreateNoSpawn( "info_node", origin, vec3_angle, NULL );
				pNode->Spawn(); // spawning it adds it into the node graph
				num ++;

				if ( !buf.IsValid() )
					break;
			}

			// when the DelayedInit is reached, will rebuild the graph from these nodes,
			// and save it out in the .ain file so we don't need to do this next time
			pNetwork->SetRebuildNeeded();
			Msg("Created %i nodes from text file\n",num);
		}
	}

If no .ain nodegraph is found, or if the current one is out of date, it will look for a .txt file in the maps/graphs/ folder, and if found, will create info_nodes at every point it specifies. A rebuild (and save) of the nodegraph will then be scheduled.

Manual Coordinate Specification

The code will now create a node graph based upon the coordinates of a .txt file, but a method is needed of populating that text file with reliable coordinates. The method listed here will require the user to set sv_cheats 1, and then use new cheat commands addnode and delnode to add/remove nodes where they are currently standing. The text file will be saved when the user enters the savenodes command.

Code coming soon!

Warning message

Currently when building the graph, a warning message will be shown in the console:

******* MAP CONTAINS DUPLICATE HAMMER NODE IDS! CHECK FOR PROBLEMS IN HAMMER TO CORRECT *******

It will then list every node, telling you that its hammer ID is already assigned. This error only occurs when building the graph from the text file, and it is believed that it is harmless - it can be commented out if desired. It would appear to only be relevant to node graph building when in map_edit mode.

Conculsion

Once a graph is created, NPCs should be able to navigate any map without problems. A pack of .ain files created using this technique will be released soon (work is ongoing), and while the use of these graphs will not require the implementation of any of the changes described here, creating nodegraphs for any other maps certainly will. Note that for any maps for which you or a member of your team is the author, the node graph should still be created in the original manner, by filling the map with info_nodes.