Ejemplo n.º 1
0
///////////////////////////////////////////////////////////////////////
// Check for adding ladder nodes
///////////////////////////////////////////////////////////////////////
qboolean ACEND_CheckForLadder(edict_t *self)
{
	int closest_node;

	// If there is a ladder and we are moving up, see if we should add a ladder node
	if (gi.pointcontents(self->s.origin) & CONTENTS_LADDER && self->velocity[2] > 0)
	{
		//debug_printf("contents: %x\n",tr.contents);

		closest_node = ACEND_FindClosestReachableNode(self,NODE_DENSITY,NODE_LADDER); 
		if(closest_node == -1)
		{
			closest_node = ACEND_AddNode(self,NODE_LADDER);
	
			// Now add link
		    ACEND_UpdateNodeEdge(self->last_node,closest_node);	   
			
			// Set current to last
			self->last_node = closest_node;
		}
		else
		{
			ACEND_UpdateNodeEdge(self->last_node,closest_node);	   
			self->last_node = closest_node; // set visited to last
		}
		return true;
	}
	return false;
}
Ejemplo n.º 2
0
///////////////////////////////////////////////////////////////////////
// Capture when the grappling hook has been fired for mapping purposes.
///////////////////////////////////////////////////////////////////////
void ACEND_GrapFired(edict_t *self)
{
	int closest_node;
	
	if(!self->owner)
		return; // should not be here
	
	// Check to see if the grapple is in pull mode
	if(self->owner->client->ctf_grapplestate == CTF_GRAPPLE_STATE_PULL)
	{
		// Look for the closest node of type grapple
		closest_node = ACEND_FindClosestReachableNode(self,NODE_DENSITY,NODE_GRAPPLE);
		if(closest_node == -1 ) // we need to drop a node
		{	
			closest_node = ACEND_AddNode(self,NODE_GRAPPLE);
			 
			// Add an edge
			ACEND_UpdateNodeEdge(self->owner->last_node,closest_node);
		
			self->owner->last_node = closest_node;
		}
		else
			self->owner->last_node = closest_node; // zero out so other nodes will not be linked
	}
}
Ejemplo n.º 3
0
///////////////////////////////////////////////////////////////////////
// Special command processor
///////////////////////////////////////////////////////////////////////
qboolean ACECM_Commands(edict_t *ent)
{
    char *cmd;
    int  node;

    cmd = gi.argv(0);

    if ((Q_strcasecmp(cmd, "addnode") == 0) && debug_mode)
    {
        ent->last_node = ACEND_AddNode(ent, atoi(gi.argv(1)));
    }

    else if ((Q_strcasecmp(cmd, "removelink") == 0) && debug_mode)
    {
        ACEND_RemoveNodeEdge(ent, atoi(gi.argv(1)), atoi(gi.argv(2)));
    }

    else if ((Q_strcasecmp(cmd, "addlink") == 0) && debug_mode)
    {
        ACEND_UpdateNodeEdge(atoi(gi.argv(1)), atoi(gi.argv(2)));
    }

    else if ((Q_strcasecmp(cmd, "showpath") == 0) && debug_mode)
    {
        ACEND_ShowPath(ent, atoi(gi.argv(1)));
    }

    else if ((Q_strcasecmp(cmd, "findnode") == 0) && debug_mode)
    {
        node = ACEND_FindClosestReachableNode(ent, NODE_DENSITY, NODE_ALL);
        safe_bprintf(PRINT_MEDIUM, "node: %d type: %d x: %f y: %f z %f\n", node, nodes[node].type, nodes[node].origin[0], nodes[node].origin[1], nodes[node].origin[2]);
    }

    else if ((Q_strcasecmp(cmd, "movenode") == 0) && debug_mode)
    {
        node = atoi(gi.argv(1));
        nodes[node].origin[0] = atof(gi.argv(2));
        nodes[node].origin[1] = atof(gi.argv(3));
        nodes[node].origin[2] = atof(gi.argv(4));
        safe_bprintf(PRINT_MEDIUM, "node: %d moved to x: %f y: %f z %f\n", node, nodes[node].origin[0], nodes[node].origin[1], nodes[node].origin[2]);
    }

    else
    {
        return false;
    }

    return true;
}
Ejemplo n.º 4
0
///////////////////////////////////////////////////////////////////////
// Only called once per level, when saved will not be called again
//
// Downside of the routine is that items can not move about. If the level
// has been saved before and reloaded, it could cause a problem if there
// are items that spawn at random locations.
//
//#define DEBUG // uncomment to write out items to a file.
///////////////////////////////////////////////////////////////////////
void ACEIT_BuildItemNodeTable (qboolean rebuild)
{
	edict_t *items;
	int i,item_index;
	vec3_t v,v1,v2;
	int j;

#ifdef DEBUG
	FILE *pOut; // for testing
	if((pOut = fopen("items.txt","wt"))==NULL)
		return;
#endif
	
	num_items = 0;

	// Add game items
	//for (items = g_edicts; items < &g_edicts[globals.num_edicts]; items++)
	items = g_edicts+1; // skip the worldspawn
	for (j = 1; j < globals.num_edicts; j++, items++)
	{
		// filter out crap
		if (!items->inuse) // Knightmare added
			continue;
		if (!items->classname)
			continue;
		if (items->solid == SOLID_NOT)
			continue;
		
		
		/////////////////////////////////////////////////////////////////
		// Items
		/////////////////////////////////////////////////////////////////
		item_index = ACEIT_ClassnameToIndex(items->classname);
		
		////////////////////////////////////////////////////////////////
		// SPECIAL NAV NODE DROPPING CODE
		////////////////////////////////////////////////////////////////
		// Special node dropping for platforms
		if(strcmp(items->classname,"func_plat")==0)
		{
			if(!rebuild)
				ACEND_AddNode(items,NODE_PLATFORM);
			item_index = 99; // to allow to pass the item index test
		}
		
		// Special node dropping for teleporters
		if(strcmp(items->classname,"misc_teleporter_dest")==0 || strcmp(items->classname,"misc_teleporter")==0)
		{
			if(!rebuild)
				ACEND_AddNode(items,NODE_TELEPORTER);
			item_index = 99;
		}
		
		#ifdef DEBUG
		if(item_index == INVALID)
			fprintf(pOut,"Rejected item: %s node: %d pos: %f %f %f\n",items->classname,item_table[num_items].node,items->s.origin[0],items->s.origin[1],items->s.origin[2]);
		else
			fprintf(pOut,"item: %s node: %d pos: %f %f %f\n",items->classname,item_table[num_items].node,items->s.origin[0],items->s.origin[1],items->s.origin[2]);
		#endif		
	
		if (item_index == INVALID)
			continue;

		// add a pointer to the item entity
		item_table[num_items].ent = items;
		item_table[num_items].item = item_index;
	
		// If new, add nodes for items
		if(!rebuild)
		{
			// Add a new node at the item's location.
			item_table[num_items].node = ACEND_AddNode(items,NODE_ITEM);
			num_items++;
		}
		else // Now if rebuilding, just relink ent structures 
		{
			// Find stored location
			for(i=0;i<numnodes;i++)
			{
				if(nodes[i].type == NODE_ITEM ||
				   nodes[i].type == NODE_PLATFORM ||
				   nodes[i].type == NODE_TELEPORTER) // valid types
				{
					VectorCopy(items->s.origin,v);
					
					// Add 16 to item type nodes
					if(nodes[i].type == NODE_ITEM)
						v[2] += 16;
					
					// Add 32 to teleporter
					if(nodes[i].type == NODE_TELEPORTER)
						v[2] += 32;
					
					if(nodes[i].type == NODE_PLATFORM)
					{
						VectorCopy(items->maxs,v1);
						VectorCopy(items->mins,v2);
		
						// To get the center
						v[0] = (v1[0] - v2[0]) / 2 + v2[0];
						v[1] = (v1[1] - v2[1]) / 2 + v2[1];
						v[2] = items->mins[2]+64;
					}

					if(v[0] == nodes[i].origin[0] &&
 					   v[1] == nodes[i].origin[1] &&
					   v[2] == nodes[i].origin[2])
					{
						// found a match now link to facts
						item_table[num_items].node = i;
			
#ifdef DEBUG
						fprintf(pOut,"Relink item: %s node: %d pos: %f %f %f\n",items->classname,item_table[num_items].node,items->s.origin[0],items->s.origin[1],items->s.origin[2]);
#endif							
						num_items++;
					}
				}
			}
		}
		

	}

#ifdef DEBUG
	fclose(pOut);
#endif

}
Ejemplo n.º 5
0
// Only called once per level, when saved will not be called again
//
// Downside of the routine is that items can not move about. If the level
// has been saved before and reloaded, it could cause a problem if there
// are items that spawn at random locations.
void
ACEIT_BuildItemNodeTable(qboolean rebuild)
{
  int i;
  gentity_t *ent;
  vec3_t v, v1, v2;
  int nodeType;

  for(i = 0, ent = &g_entities[0];i < level.num_entities;i++, ent++)
  {
    if (!ent->inuse)
      continue;

    /*
     // special node dropping for platforms
     if(!Q_stricmp(ent->item->classname, "func_plat"))
     {
     if(!rebuild)
     ACEND_AddNode(ent, NODE_PLATFORM);
     item_index = 99; // to allow to pass the item index test
     }

     // special node dropping for teleporters
     if(!Q_stricmp(ent->item->classname, "misc_teleporter_dest") || !Q_stricmp(ent->item->classname, "trigger_teleport"))
     {
     if(!rebuild)
     ACEND_AddNode(ent, NODE_TELEPORTER);
     item_index = 99;
     }
     */

    /*if(ent->item)
     {
     // FIXME: ignore dropped items for now, because they would create too many nodes
     // it would be necessary to remove nodes if we want to support them
     if(ent->flags & FL_DROPPED_ITEM)
     continue;

     nodeType = NODE_ITEM;
     }
     else*/
    if (!Q_stricmp(ent->classname, "trigger_teleport"))
    {
      nodeType = NODE_TRIGGER_TELEPORT;
    }
    /*
     else if(!Q_stricmp(ent->classname, "misc_teleporter_dest"))
     {
     nodeType = NODE_TARGET_TELEPORT;
     }
     */
    else if (!Q_stricmp(ent->classname, "trigger_push"))
    {
      nodeType = NODE_JUMPPAD;
    }
    else
    {
      // entity does not matter
      continue;
    }

    // if new, add nodes for items
    if (!rebuild)
    {
      // add a new node at the item's location.
      G_Printf("Node Added from buildItemNodeTable");
      ent->node = ACEND_AddNode(ent, nodeType);
    }
    else
    {
      // find stored location
      for(i = 0;i < numNodes;i++)
      {
        if (nodes[i].type == NODE_ITEM || nodes[i].type == NODE_PLATFORM || nodes[i].type
            == NODE_TRIGGER_TELEPORT || nodes[i].type == NODE_JUMPPAD) // valid types
        {
          if (nodes[i].type == NODE_ITEM)
          {
            VectorCopy(ent->s.origin, v);
            //v[2] += 16;
          }
          else if (nodes[i].type == NODE_TRIGGER_TELEPORT)
          {
            VectorAdd(ent->r.absmin, ent->r.absmax, v);
            VectorScale(v, 0.5, v);
          }
          /*
           else if(nodes[i].type == NODE_TARGET_TELEPORT)
           {
           v[2] += 32;
           }
           */
          else if (nodes[i].type == NODE_JUMPPAD)
          {
            VectorAdd(ent->r.absmin, ent->r.absmax, v);
            VectorScale(v, 0.5, v);

            // add jumppad target offset
            VectorNormalize2(ent->s.origin2, v2);
            VectorMA(v, 32, v2, v);
          }
          else /*if(nodes[i].type == NODE_PLATFORM) */
          {
            VectorCopy(ent->r.maxs, v1);
            VectorCopy(ent->r.mins, v2);

            // to get the center
            v[0] = (v1[0] - v2[0]) / 2 + v2[0];
            v[1] = (v1[1] - v2[1]) / 2 + v2[1];
            v[2] = ent->r.mins[2] + 64;
          }

          SnapVector(v);

          if ( /*ent->node != INVALID || */VectorCompare(v, nodes[i].origin))
          {
            /*
             if(!VectorCompare(v, nodes[i].origin))
             {
             // update node origin
             VectorCopy(v, nodes[i].origin);
             }
             else
             */
            {
              // found a match now link to facts
              ent->node = i;
            }

#if 0							//defined(_DEBUG)
            if(ent->item)
            {
              G_Printf("relink item: %s node: %d pos: %f %f %f\n", ent->item->classname, ent->node,
                  ent->s.origin[0], ent->s.origin[1], ent->s.origin[2]);
            }
            else
            {
              G_Printf("relink entity: %s node: %d pos: %f %f %f\n", ent->classname, ent->node,
                  ent->s.origin[0], ent->s.origin[1], ent->s.origin[2]);
            }
#endif
            break;
          }
        }
      }

      if (i == numNodes)
      {
        // add a new node at the item's location.
        ent->node = ACEND_AddNode(ent, nodeType);
      }
    }

#if 0							//defined(_DEBUG)
    //if(item_index == INVALID)
    //  fprintf(pOut, "Rejected item: %s node: %d pos: %f %f %f\n", ent->item->classname, ent->node,
    //          ent->s.origin[0], ent->s.origin[1], ent->s.origin[2]);
    //else
    if(ent->item)
    {
      G_Printf("accepted item: %s node: %d pos: %f %f %f\n", ent->item->classname, ent->node, ent->s.origin[0],
          ent->s.origin[1], ent->s.origin[2]);
    }
    else
    {
      G_Printf("accepted entity: %s node: %d pos: %f %f %f\n", ent->classname, ent->node, ent->s.origin[0],
          ent->s.origin[1], ent->s.origin[2]);
    }
#endif

  }

}
Ejemplo n.º 6
0
///////////////////////////////////////////////////////////////////////
// This routine is called to hook in the pathing code and sets
// the current node if valid.
///////////////////////////////////////////////////////////////////////
void ACEND_PathMap(edict_t *self)
{
	int closest_node;
	static float last_update=0; // start off low
	vec3_t v;

	if(level.time < last_update)
		return;

	last_update = level.time + 0.15; // slow down updates a bit

	// Special node drawing code for debugging
    if(show_path_to != -1)
		ACEND_DrawPath();
	
	////////////////////////////////////////////////////////
	// Special check for ladder nodes
	///////////////////////////////////////////////////////
	if(ACEND_CheckForLadder(self)) // check for ladder nodes
		return;

	// Not on ground, and not in the water, so bail
    if(!self->groundentity && !self->waterlevel)
		return;

	////////////////////////////////////////////////////////
	// Lava/Slime
	////////////////////////////////////////////////////////
	VectorCopy(self->s.origin,v);
	v[2] -= 18;
	if(gi.pointcontents(v) & (CONTENTS_LAVA|CONTENTS_SLIME))
		return; // no nodes in slime
	
    ////////////////////////////////////////////////////////
	// Jumping
	///////////////////////////////////////////////////////
	if(self->is_jumping)
	{
	   // See if there is a closeby jump landing node (prevent adding too many)
		closest_node = ACEND_FindClosestReachableNode(self, 64, NODE_JUMP);

		if(closest_node == INVALID)
			closest_node = ACEND_AddNode(self,NODE_JUMP);
		
		// Now add link
		if(self->last_node != -1)
			ACEND_UpdateNodeEdge(self->last_node, closest_node);	   

		self->is_jumping = false;
		return;
	}

	////////////////////////////////////////////////////////////
	// Grapple
	// Do not add nodes during grapple, added elsewhere manually
	////////////////////////////////////////////////////////////
	if(ctf->value && self->client->ctf_grapplestate == CTF_GRAPPLE_STATE_PULL)
		return;
	 
	// Iterate through all nodes to make sure far enough apart
	closest_node = ACEND_FindClosestReachableNode(self, NODE_DENSITY, NODE_ALL);

	////////////////////////////////////////////////////////
	// Special Check for Platforms
	////////////////////////////////////////////////////////
	if(self->groundentity && self->groundentity->use == Use_Plat)
	{
		if(closest_node == INVALID)
			return; // Do not want to do anything here.

		// Here we want to add links
		if(closest_node != self->last_node && self->last_node != INVALID)
			ACEND_UpdateNodeEdge(self->last_node,closest_node);	   

		self->last_node = closest_node; // set visited to last
		return;
	}
	 
	 ////////////////////////////////////////////////////////
	 // Add Nodes as needed
	 ////////////////////////////////////////////////////////
	 if(closest_node == INVALID)
	 {
		// Add nodes in the water as needed
		if(self->waterlevel)
			closest_node = ACEND_AddNode(self,NODE_WATER);
		else
		    closest_node = ACEND_AddNode(self,NODE_MOVE);
		
		// Now add link
		if(self->last_node != -1)
			ACEND_UpdateNodeEdge(self->last_node, closest_node);	   
			
	 }
	 else if(closest_node != self->last_node && self->last_node != INVALID)
	 	ACEND_UpdateNodeEdge(self->last_node,closest_node);	   
	
	 self->last_node = closest_node; // set visited to last
	
}
Ejemplo n.º 7
0
// This routine is called to hook in the pathing code and sets
// the current node if valid.
void ACEND_PathMap(gentity_t * self)
{
	int             closestNode;
	static float    lastUpdate = 0;	// start off low
	vec3_t          v;
	//qboolean        isJumping;
	//int             i;

#if 0
	if(level.time < lastUpdate)
		return;
#endif

	lastUpdate = level.time + 150;	// slow down updates a bit

#if 0
	if(self->r.svFlags & SVF_BOT)
		return;
#endif

	// don't add links when you went into a trap
	if(self->health <= 0)
		return;

#if 1
	if(self->s.groundEntityNum == ENTITYNUM_NONE && !(self->r.svFlags & SVF_BOT))
	{
#if 0
		isJumping = qfalse;
		for(i = 0; i < self->client->ps.eventSequence; i++)
		{
			if(self->client->ps.events[i] == EV_JUMP)
				isJumping = qtrue;
		}

		if(isJumping)
#else
		if((self->client->ps.pm_flags & PMF_JUMP_HELD))
#endif
		{
			if(ace_debug.integer)
				trap_SendServerCommand(-1, va("print \"%s: jumping\n\"", self->client->pers.netname));

			// see if there is a closeby jump landing node (prevent adding too many)
			closestNode = ACEND_FindClosestReachableNode(self, 64, NODE_JUMP);

			if(closestNode == INVALID)
				closestNode = ACEND_AddNode(self, NODE_JUMP);

			// now add link
			if(self->bs.lastNode != INVALID)
				ACEND_UpdateNodeEdge(self->bs.lastNode, closestNode);

			self->bs.isJumping = qfalse;
			return;
		}
	}
#endif

	// not on ground, and not in the water, so bail
	if(self->s.groundEntityNum == ENTITYNUM_NONE)
	{
		/*
		   if(self->bs.lastNode != INVALID)
		   {
		   // we might have been pushed by a jump pad
		   if(nodes[self->bs.lastNode].type != NODE_JUMPPAD)
		   return;
		   }
		   else if(!self->waterlevel)
		   {
		   return;
		   }
		 */
	}


	// lava / slime
	VectorCopy(self->client->ps.origin, v);
	v[2] -= 18;

	if(trap_PointContents(self->client->ps.origin, -1) & (CONTENTS_LAVA | CONTENTS_SLIME))
		return;					// no nodes in slime

	// Grapple
	// Do not add nodes during grapple, added elsewhere manually

	/*
	   if(ctf->value && self->client->ctf_grapplestate == CTF_GRAPPLE_STATE_PULL)
	   return;
	 */

	// iterate through all nodes to make sure far enough apart
	closestNode = ACEND_FindClosestReachableNode(self, NODE_DENSITY, NODE_ALL);


	// Special Check for Platforms
	/* FIXME
	   if(self->groundentity && self->groundentity->use == Use_Plat)
	   {
	   if(closestNode == INVALID)
	   return;              // Do not want to do anything here.

	   // Here we want to add links
	   if(closestNode != self->lastNode && self->lastNode != INVALID)
	   ACEND_UpdateNodeEdge(self->lastNode, closestNode);

	   self->lastNode = closestNode;    // set visited to last
	   return;
	   }
	 */


	if(closestNode != INVALID)
	{
		// add automatically some links between nodes

		if(closestNode != self->bs.lastNode && self->bs.lastNode != INVALID)
		{
			ACEND_UpdateNodeEdge(self->bs.lastNode, closestNode);
			if(ace_showLinks.integer)
				ACEND_DrawPath(self->bs.lastNode, closestNode);
		}

		self->bs.lastNode = closestNode;	// set visited to last
	}
#if 1
	else if(closestNode == INVALID && self->s.groundEntityNum != ENTITYNUM_NONE)
	{
		// add nodes in the water as needed
		if(self->waterlevel)
			closestNode = ACEND_AddNode(self, NODE_WATER);
		else
			closestNode = ACEND_AddNode(self, NODE_MOVE);

		// now add link
		if(self->bs.lastNode != INVALID)
		{
			ACEND_UpdateNodeEdge(self->bs.lastNode, closestNode);

			if(ace_showLinks.integer)
				ACEND_DrawPath(self->bs.lastNode, closestNode);
		}

		self->bs.lastNode = closestNode;	// set visited to last
	}
#endif
}