⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 navigate.cpp

📁 this keik game source
💻 CPP
📖 第 1 页 / 共 4 页
字号:
	Vector	max;

	cell = GetNodesInCell( pos );
	if ( !cell )
		{
		return NULL;
		}

   if ( ent && usebbox )
      {
   	min = ent->mins;
      max = ent->maxs;
      }
   else
      {
   	min = Vector( -16, -16, 12 );
   	max = Vector( 16, 16, 40 );
      }
	
	n = cell->NumNodes();

	if ( ai_debugpath->value )
		{
		gi.dprintf( "NearestNode: Checking %d nodes\n", n );
		}

	bestnode = NULL;
	bestdist = 999999999; // greater than ( 8192 * sqr(2) ) ^ 2 -- maximum squared distance
	for( i = 0; i < n; i++ )
		{
		node = ( PathNode * )cell->GetNode( i );
		if ( !node )
			{
			continue;
			}

		delta = node->worldorigin - pos;
      
		// get the distance squared (faster than getting real distance)
		dist = delta * delta;
      if ( ( dist < bestdist ) && node->CheckMove( ent, pos, min, max, false, false ) )
			{
			bestnode = node;
			bestdist = dist;

         // if we're close enough, early exit
         if ( dist < 16 )
            {
            break;
            }
			}
		}

	return bestnode;
	}

EXPORT_FROM_DLL void PathSearch::Teleport
	(
	Entity *teleportee,
	Vector from,
	Vector to
	)

	{
	PathNode	*node1;
	PathNode	*node2;
	byte maxheight[ NUM_WIDTH_VALUES ];
	int j;

	if ( ai_createnodes->value )
		{
		node1 = new PathNode;
		node1->Setup( from );

		node2 = new PathNode;
		node2->Setup( to );

		// FIXME
		// shouldn't hard-code width and height
		for( j = 0; j < NUM_WIDTH_VALUES; j++ )
			{
			maxheight[ j ] = 72;
			}

		// connect with 0 cost
		node1->ConnectTo( node2, maxheight, 0 );
		}
	}

EXPORT_FROM_DLL void PathSearch::ShowNodes
	(
	void
	)

	{
	if ( ai_showroutes->value || ai_shownodenums->value )
		{
		DrawAllConnections();
		}
	}

EXPORT_FROM_DLL int PathSearch::NumNodes
	(
	void
	)

	{
	return numNodes;
	}

EXPORT_FROM_DLL void PathSearch::Archive
	(
	Archiver &arc
	)

	{
	PathNode *node;
	int i;
	int num;

	num = 0;
	for( i = 0; i < MAX_PATHNODES; i++ )
		{
		node = AI_GetNode( i );
		if ( node )
			{
			num++;
			}
		}

	arc.WriteInteger( num );
	for( i = 0; i < MAX_PATHNODES; i++ )
		{
		node = AI_GetNode( i );
		if ( node )
			{
			arc.WriteObject( node );
			}
		}

	if ( ai_debuginfo->value )
		{
		gi.dprintf( "Wrote %d path nodes\n", num );
		}
	}

EXPORT_FROM_DLL void PathSearch::ClearNodes
	(
	Event *ev
	)

	{
	PathNode *node;
	int i;
	int num;

	num = 0;
	for( i = 0; i < MAX_PATHNODES; i++ )
		{
		node = AI_GetNode( i );
		if ( node )
			{
			node->PostEvent( EV_Remove, 0 );
			num++;
			}
		}

	if ( ai_debuginfo->value )
		{
		gi.dprintf( "Deleted %d path nodes\n", num );
		}
	}

EXPORT_FROM_DLL void PathSearch::Unarchive
	(
	Archiver &arc
	)

	{
	int num;
	int i;
   int x;
   int y;

	numNodes = 0;
	NodeList = NULL;
	loadingarchive = true;

	// Get rid of the nodes that were spawned by the map
	AI_ResetNodes();

   // Init the grid
	for( x = 0; x < PATHMAP_GRIDSIZE; x++ )
		{
		for( y = 0; y < PATHMAP_GRIDSIZE; y++ )
			{
			PathMap[ x ][ y ].Init();
			}
		}

	num = arc.ReadInteger();

	assert( num <= MAX_PATHNODES );
	if ( num > MAX_PATHNODES )
		{
		arc.FileError( "Exceeded max path nodes" );
		}

	for( i = 0; i < num; i++ )
		{
		arc.ReadObject();
		}

	if ( ai_debuginfo->value )
		{
		gi.dprintf( "Path nodes loaded: %d\n", NumNodes() );
		}

   loadingarchive = false;
	}

EXPORT_FROM_DLL void PathSearch::SetNodeFlagsEvent
	(
	Event *ev
	)
	
	{
   const char * token;
   int i, argnum, flags;
   int mask;
   int action;
   int nodenum;
   PathNode *node;

#define FLAG_IGNORE  0
#define FLAG_SET     1
#define FLAG_CLEAR   2
#define FLAG_ADD     3

   nodenum = ev->GetInteger( 1 );
   node = AI_GetNode( nodenum );

   if ( !node )
      {
      ev->Error( "Node not found." );
      return;
      }

   flags = 0;
   argnum = 2;
   for ( i = argnum; i <= ev->NumArgs() ; i++ )
      {
      token = ev->GetString( i );
      action = 0;
      switch( token[0] )
         {
         case '+':
            action = FLAG_ADD;
            token++;
            break;
         case '-':
            action = FLAG_CLEAR;
            token++;
            break;
         default:
            action = FLAG_SET;
            break;
         }

      if (!strcmpi( token, "flee"))
         {
         mask = AI_FLEE;
         }
      else if (!strcmpi (token, "duck"))
         {
         mask = AI_DUCK;
         }
      else if (!strcmpi (token, "cover"))
         {
         mask = AI_COVER;
         }
      else if (!strcmpi (token, "door"))
         {
         mask = AI_DOOR;
         }
      else if (!strcmpi (token, "jump"))
         {
         mask = AI_JUMP;
         }
      else if (!strcmpi (token, "ladder"))
         {
         mask = AI_LADDER;
         }
      else if (!strcmpi (token, "action"))
         {
         mask = AI_ACTION;
         }
      else
         {
         action = FLAG_IGNORE;
         ev->Error( "Unknown token %s.", token );
         }

      switch (action)
         {
         case FLAG_SET:
            node->nodeflags = 0;

         case FLAG_ADD:
            node->nodeflags |= mask;
            break;

         case FLAG_CLEAR:
            node->nodeflags &= ~mask;
            break;

         case FLAG_IGNORE:
            break;
         }
      }
	}

EXPORT_FROM_DLL void PathSearch::CalcPathEvent
	(
	Event *ev
	)

	{
   int nodenum;
   PathNode *node;
   PathNode *node2;
   int j;
	byte maxheight[ NUM_WIDTH_VALUES ];

   nodenum = ev->GetInteger( 1 );
   node = AI_GetNode( nodenum );

   nodenum = ev->GetInteger( 2 );
   node2 = AI_GetNode( nodenum );

   if ( !node || !node2 )
      {
      ev->Error( "Node not found." );
      return;
      }

   if ( ( node->numChildren < NUM_PATHSPERNODE ) && !node->ConnectedTo( node2 ) )
      {
      if ( node->ClearPathTo( node2, maxheight, false ) || node->LadderTo( node2, maxheight ) )
			{
			node->ConnectTo( node2, maxheight );
			}
		else if ( ( node->nodeflags & AI_JUMP ) && ( node->target == node2->targetname ) )
			{
			//FIXME
			// don't hardcode size
			for( j = 0; j < NUM_WIDTH_VALUES; j++ )
				{
				maxheight[ j ] = MAX_HEIGHT;
				}
			node->ConnectTo( node2, maxheight );
			}
      }

	if ( ( node2->numChildren < NUM_PATHSPERNODE ) && !node2->ConnectedTo( node ) )
      {
		if ( node2->ClearPathTo( node, maxheight, false ) || node2->LadderTo( node, maxheight ) )
			{
			node2->ConnectTo( node, maxheight );
			}
      else if ( ( node2->nodeflags & AI_JUMP ) && ( node2->target == node->targetname ) )
			{
			//FIXME
			// don't hardcode size
			for( j = 0; j < NUM_WIDTH_VALUES; j++ )
				{
				maxheight[ j ] = MAX_HEIGHT;
				}
			node2->ConnectTo( node, maxheight );
			}
      }
	}

EXPORT_FROM_DLL void PathSearch::DisconnectPathEvent
	(
	Event *ev
	)

	{
   int nodenum;
   PathNode *node;
   PathNode *node2;

   nodenum = ev->GetInteger( 1 );
   node = AI_GetNode( nodenum );

   nodenum = ev->GetInteger( 2 );
   node2 = AI_GetNode( nodenum );

   if ( !node || !node2 )
      {
      ev->Error( "Node not found." );
      return;
      }

	if ( node->ConnectedTo( node2 ) )
		{
		node->Disconnect( node2 );
		}

   if ( node2->ConnectedTo( node ) )
		{
		node2->Disconnect( node );
		}
	}

EXPORT_FROM_DLL void PathSearch::RecalcPathsEvent
	(
	Event *ev
	)

	{
   int nodenum;
   PathNode *node;

   nodenum = ev->GetInteger( 1 );
   node = AI_GetNode( nodenum );
   if ( node )
      {
      UpdateNode( node );
      }
   else
      {
      ev->Error( "Node not found." );
      }
   }

EXPORT_FROM_DLL void PathSearch::SaveNodes
	(
	Event *ev
	)

	{
	Archiver arc;
	str name;

	if ( ev->NumArgs() != 1 )
		{
		gi.printf( "Usage: ai_save [filename]\n" );
		return;
		}
	
	name = ev->GetString( 1 );

	gi.printf( "Archiving\n" );

	arc.Create( name );
	arc.WriteInteger( PATHFILE_VERSION );
	arc.WriteObject( this );
	arc.Close();

	gi.printf( "done.\n" );
	}

EXPORT_FROM_DLL void PathSearch::LoadNodes
	(
	Event *ev
	)

	{
	Archiver arc;
	str		name;
	int		version;

	if ( ev->NumArgs() != 1 )
		{
		gi.printf( "Usage: ai_load [filename]\n" );
		return;
		}
	
	gi.printf( "Loading nodes...\n" );

	name = ev->GetString( 1 );

	arc.Read( name );
	version = arc.ReadInteger();
	if ( version == PATHFILE_VERSION )
		{
		arc.ReadObject( this );
		arc.Close();

		gi.printf( "done.\n" );
		}
	else
		{
		arc.Close();

		gi.printf( "Expecting version %d path file.  Path file is version %d.", PATHFILE_VERSION, version );

		// Only replace the file if this event was called from our init function (as opposed to the user
		// calling us from the console) and the version number is older than our current version.
		if ( ( ev->GetSource() == EV_FROM_CODE ) && ( version < PATHFILE_VERSION ) )
			{
			gi.printf( "Replacing file.\n\n" );

			// At this point, the nodes are still scheduled to find their neighbors, because we posted this event
			// before we the nodes were spawned.  Post the event with 0 delay so that it gets processed after all 
			// the nodes find their neighbors.
			PostEvent( EV_AI_SavePaths, 0 );
			}
		else
			{
			// otherwise, just let them know that the path file needs to be replaced.
			gi.printf( "Type 'ai_savepaths' at the console to replace the current path file.\n" );
			}

      // Print out something fairly obvious
      gi.dprintf( "***********************************\n"
                  "***********************************\n"
                  "\n"
                  "Creating paths...\n"
                  "\n"
                  "***********************************\n"
                  "***********************************\n" );
		}
	}

EXPORT_FROM_DLL void PathSearch::SavePaths
	(
	void
	)

	{
	str filename;
	Event *ev;

	if ( loadingarchive )
		{
		// force it to zero since we probably had an error
		gi.cvar_set( "ai_createnodes", "0" );
		}

	if ( !loadingarchive && ai_createnodes && ai_createnodes->value )
		{
		filename = gi.GameDir();
		filename += "/maps/";
		filename += level.mapname;
		filename += ".pth";

		gi.dprintf( "Saving path nodes to '%s'\n", filename.c_str() );

		ev = new Event( EV_AI_SaveNodes );
		ev->AddString( filename );
		ProcessEvent( ev );
		}
	}

EXPORT_FROM_DLL void PathSearch::SavePathsEvent
	(
	Event *ev
	)

	{
	str temp;

	temp = ai_createnodes->string;
	gi.cvar_set( "ai_createnodes", "1" );

	SavePaths();

	gi.cvar_set( "ai_createnodes", temp.c_str() );
	}

EXPORT_FROM_DLL void PathSearch::Init
	(
	const char *mapname
	)

	{
	int x;
	int y;
	str filename;
	Event *ev;

	ai_createnodes		= gi.cvar ("ai_createnodes", "0", 0);
	ai_showpath			= gi.cvar ("ai_showpath", "0", 0);
	ai_debugpath		= gi.cvar ("ai_debugpath", "0", 0);
	ai_debuginfo		= gi.cvar ("ai_debuginfo", "0", 0);
	ai_showroutes		= gi.cvar ("ai_showroutes", "0", 0);
   ai_shownodenums   = gi.cvar ("ai_shownodenums", "0", 0);
   ai_timepaths      = gi.cvar ("ai_timepaths", "0", 0);

	numNodes = 0;
	NodeList = NULL;
	loadingarchive = false;

	// Get rid of the nodes that were spawned by the map
	AI_ResetNodes();

   // Init the grid
	for( x = 0; x < PATHMAP_GRIDSIZE; x++ )
		{
		for( y = 0; y < PATHMAP_GRIDSIZE; y++ )
			{
			PathMap[ x ][ y ].Init();
			}
		}

   if ( mapname )
      {
      filename = "maps/";
	   filename += mapname;
	   filename += ".pth";
      if ( gi.LoadFile( filename.c_str(), NULL, 0 ) != -1 )
         {
		   ev = new Event( EV_AI_LoadNodes );
		   ev->AddString( filename );

		   // This can't happen until the world is spawned
		   PostEvent( ev, 0 );
         }
      else
         {
         // Print out something fairly obvious
         gi.dprintf( "***********************************\n"
                     "***********************************\n"
                     "\n"
                     "No paths found.  Creating paths...\n"
                     "\n"
                     "***********************************\n"
                     "***********************************\n" );
         }
      }
   }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -