.:: Bots United ::.  
filebase forums discord server github wiki web
cubebot epodbot fritzbot gravebot grogbot hpbbot ivpbot jkbotti joebot
meanmod podbotmm racc rcbot realbot sandbot shrikebot soulfathermaps yapb

Go Back   .:: Bots United ::. > Developer's Farm > General Bot Coding
General Bot Coding See what a pain it is to get those little mechs shooting around

Reply
 
Thread Tools
Traceline navigation
Old
  (#1)
Lazy
Member
 
Lazy's Avatar
 
Status: Offline
Posts: 236
Join Date: Jan 2004
Location: Toronto, Ontario, Canada
Default Traceline navigation - 12-03-2004

I've been thinking about this for a while now and need some input from you bot coders...

My idea is to have 4 tracelines fire out of the bot in every direction ( front, back, left, right ) at the head, chest, knees and feet of the bot. That should be a good way to determine wether a hit is actually a set of stairs instead of a wall.

The problem is this, I have drawn up some demos in paint by making a simple map and drawing lines from the bot start to the bomb site.
What I've noticed is that when I add several boxes or obstacles the bot could potentially get stuck and go in circles looking for a way out.
It does however work on simple maps with little obstacles such as hallways and doors.

In the end I hope to just use this method to drop down waypoints for them to use later on so that this wouldn't have to be done every time.

Any ideas or thoughts on this?
  
Reply With Quote
Re: Traceline navigation
Old
  (#2)
Rick
Council Member
 
Rick's Avatar
 
Status: Offline
Posts: 690
Join Date: Dec 2003
Location: Holland
Default Re: Traceline navigation - 12-03-2004

For good traceline navigation you should check out Pierre's racc bot template
  
Reply With Quote
Re: Traceline navigation
Old
  (#3)
Pierre-Marie Baty
Roi de France
 
Pierre-Marie Baty's Avatar
 
Status: Offline
Posts: 5,049
Join Date: Nov 2003
Location: 46°43'60N 0°43'0W 0.187A
Default Re: Traceline navigation - 13-03-2004

hehe, I *am* the TraceLine specialist here

If you only want immediate obstacle detection, you can use a few TraceLines like this:
Code:
void BotCheckForObstaclesAtFeet (player_t *pPlayer)
{
   // this function fills an integer bitmap describing the presence and quality of any
   // obstacle right around the bot. Useful for low walls over which the bot has to jump,
   // or for determining if the bot should duck to pass a low ceiling. This function is
   // called every frame, systematically, in BotSense(), so that the bot knows, when
   // it starts thinking, the quality of the terrain in front of it. First it checks if
   // it is about to hit something when walking forward, and if so, it checks if the bot's
   // look hits a wall when looking straight horizontally. If so, then the bot might be
   // able to duck over something to pass by ; if not, then the bot might be able to
   // jump over the obstacle ; we do the appropriate checks.
   // NOTE: player's origin is 37 units above the ground (standing height)
   //	   player is 36 units high when ducking
   //	   max stair height is 18 units
   //	   max jump height is 45 units
   //	   max jump height is 63 units when doing a duck-jump
   TraceResult tr1, tr2, tr3, tr4, tr5;
   Vector v_feet;
   float angle_diff, check_distance;
   float left_check_dst, front_check_dst, right_check_dst;
   pPlayer->Bot.BotBody.hit_state = OBSTACLE_NONE; // first off, reset the hit state bitmap
   // given the bot's velocity, bot will check closer or further forward (range 60-120 units)
   check_distance = 0.4 * pPlayer->pEntity->v.velocity.Length2D ();
   angle_diff = UTIL_VecToAngles (pPlayer->pEntity->v.velocity).y - pPlayer->v_angle.y;
   // we gotta transpose this distance to both sides of the bot (and also forward)
   // left distance
   pPlayer->Bot.BotBody.left_check_dst = check_distance * sin (angle_diff);
   if (pPlayer->Bot.BotBody.left_check_dst < 60)
	  pPlayer->Bot.BotBody.left_check_dst = 60; // bound it to 60 units minimum
   else if (pPlayer->Bot.BotBody.left_check_dst > 120)
	  pPlayer->Bot.BotBody.left_check_dst = 120; // and 120 units maximum
   // forward distance
   pPlayer->Bot.BotBody.front_check_dst = check_distance * cos (angle_diff);
   if (pPlayer->Bot.BotBody.front_check_dst < 60)
	  pPlayer->Bot.BotBody.front_check_dst = 60; // bound it to 60 units minimum
   else if (pPlayer->Bot.BotBody.front_check_dst > 120)
	  pPlayer->Bot.BotBody.front_check_dst = 120; // and 120 units maximum
   // right distance
   pPlayer->Bot.BotBody.right_check_dst = check_distance * -sin (angle_diff);
   if (pPlayer->Bot.BotBody.right_check_dst < 60)
	  pPlayer->Bot.BotBody.right_check_dst = 60; // bound it to 60 units minimum
   else if (pPlayer->Bot.BotBody.right_check_dst > 120)
	  pPlayer->Bot.BotBody.right_check_dst = 120; // and 120 units maximum
   // get a quick access to these three
   left_check_dst = pPlayer->Bot.BotBody.left_check_dst;
   front_check_dst = pPlayer->Bot.BotBody.front_check_dst;
   right_check_dst = pPlayer->Bot.BotBody.right_check_dst;
   // get the bot's feet position
   v_feet = pPlayer->v_origin; // take the origin...
   v_feet.z = pPlayer->pEntity->v.absmin.z; // and lower it at the bottom of the bounding box
   // check on the left
   // do a trace 17 units above max stair height left...
   UTIL_TraceHull (v_feet + Vector (0, 0, 18 + 18 + 17),
				   v_feet + Vector (0, 0, 18 + 18 + 17) - (pPlayer->v_right * left_check_dst),
				   ignore_monsters, head_hull, pPlayer->pEntity, &tr1);
   // do a trace one unit above max jump height left...
   UTIL_TraceHull (v_feet + Vector (0, 0, 18 + 64),
				   v_feet + Vector (0, 0, 18 + 64) - (pPlayer->v_right * left_check_dst),
				   ignore_monsters, head_hull, pPlayer->pEntity, &tr2);
   // do a trace one unit lower than max stair height left...
   UTIL_TraceHull (v_feet + Vector (0, 0, 18 + 17),
				   v_feet + Vector (0, 0, 18 + 17) - (pPlayer->v_right * left_check_dst),
				   ignore_monsters, head_hull, pPlayer->pEntity, &tr3);
   // is there something in the way at feet level that is not a slope AND nothing in the way at eye level ?
   if ((tr3.flFraction < 1.0) && (tr3.vecPlaneNormal.z < 0.5) && (tr2.flFraction == 1.0))
	  pPlayer->Bot.BotBody.hit_state |= OBSTACLE_LEFT_LOWWALL; // bot can jump over this obstacle
   // is there something in the way at eye level AND nothing in the way at knee level ?
   if ((tr2.flFraction < 1.0) && (tr1.flFraction == 1.0) && IsOnFloor (pPlayer->pEntity))
	  pPlayer->Bot.BotBody.hit_state |= OBSTACLE_LEFT_LOWCEILING; // bot can duck under this obstacle
   // is there something in the way at eye level AND something in the way at knee level ?
   if ((tr2.flFraction < 1.0) && (tr1.flFraction < 1.0))
	  pPlayer->Bot.BotBody.hit_state |= OBSTACLE_LEFT_WALL; // bot will definitely hit something
   // if the area is clear on the left at head level, trace down to check for a possible fall
   if (tr2.flFraction == 1.0)
   {
	  UTIL_TraceHull (v_feet + Vector (0, 0, 18 + 64) - (pPlayer->v_right * left_check_dst),
					  v_feet + Vector (0, 0, 18 + 64) - (pPlayer->v_right * left_check_dst) + Vector (0, 0, -250),
					  ignore_monsters, head_hull, pPlayer->pEntity, &tr4);
	  // did the trace hit nothing OR some water ?
	  if ((tr4.flFraction == 1.0) || (POINT_CONTENTS (tr4.vecEndPos) == CONTENTS_WATER))
		 pPlayer->Bot.BotBody.hit_state |= OBSTACLE_LEFT_FALL; // bot can fall on the left
   }
   // check in front
   // do a trace 17 units above max stair height forward...
   UTIL_TraceHull (v_feet + Vector (0, 0, 18 + 18 + 17),
				   v_feet + Vector (0, 0, 18 + 18 + 17) + (pPlayer->v_forward * front_check_dst),
				   ignore_monsters, head_hull, pPlayer->pEntity, &tr1);
   // do a trace one unit above max jump height forward...
   UTIL_TraceHull (v_feet + Vector (0, 0, 18 + 64),
				   v_feet + Vector (0, 0, 18 + 64) + (pPlayer->v_forward * front_check_dst),
				   ignore_monsters, head_hull, pPlayer->pEntity, &tr2);
   // do a trace one unit lower than max stair height forward...
   UTIL_TraceHull (v_feet + Vector (0, 0, 18 + 17),
				   v_feet + Vector (0, 0, 18 + 17) + (pPlayer->v_forward * front_check_dst),
				   ignore_monsters, head_hull, pPlayer->pEntity, &tr3);
   // is there something in the way at feet level that is not a slope AND nothing in the way at eye level ?
   if ((tr3.flFraction < 1.0) && (tr3.vecPlaneNormal.z < 0.5) && (tr2.flFraction == 1.0))
	  pPlayer->Bot.BotBody.hit_state |= OBSTACLE_FRONT_LOWWALL; // bot can jump over this obstacle
   // is there something in the way at eye level AND nothing in the way at knee level ?
   if ((tr2.flFraction < 1.0) && (tr1.flFraction == 1.0) && IsOnFloor (pPlayer->pEntity))
	  pPlayer->Bot.BotBody.hit_state |= OBSTACLE_FRONT_LOWCEILING; // bot can duck under this obstacle
   // is there something in the way at eye level AND something in the way at knee level ?
   if ((tr2.flFraction < 1.0) && (tr1.flFraction < 1.0))
	  pPlayer->Bot.BotBody.hit_state |= OBSTACLE_FRONT_WALL; // bot will definitely hit something
   // if the area is clear in front at head level, trace down to check for a possible fall
   if (tr2.flFraction == 1.0)
   {
	  UTIL_TraceHull (v_feet + Vector (0, 0, 18 + 64) + (pPlayer->v_forward * front_check_dst),
					  v_feet + Vector (0, 0, 18 + 64) + (pPlayer->v_forward * front_check_dst) + Vector (0, 0, -250),
					  ignore_monsters, head_hull, pPlayer->pEntity, &tr4);
	  // did the trace hit nothing OR some water ?
	  if ((tr4.flFraction == 1.0) || (POINT_CONTENTS (tr4.vecEndPos) == CONTENTS_WATER))
	  {
		 pPlayer->Bot.BotBody.hit_state |= OBSTACLE_FRONT_FALL; // bot can fall in front
		 pPlayer->Bot.f_reach_time = server.time + 1.5; // reflex : don't reach point for 1.5 second
		 // trace backwards in front of the bot 17 units down to find the edge plane
		 TRACE_LINE (v_feet + Vector (0, 0, -10) + pPlayer->v_forward * (front_check_dst + 20.0),
					 v_feet + Vector (0, 0, -10) + pPlayer->v_forward * (front_check_dst + 20.0) - pPlayer->v_forward * 300,
					 ignore_monsters, pPlayer->pEntity, &tr5);
		 // did the trace hit something ?
		 if (tr5.flFraction < 1.0)
			pPlayer->Bot.BotBody.v_fall_plane_normal = tr5.vecPlaneNormal; // if so, then we found the edge plane
		 else
		 {
			// Houston, we have a problem. The bot is about to fall but we did NOT found the
			// edge plane. Make it jump as a reflex to reach the opposite side (if any)
			pPlayer->Bot.BotLegs.f_forward_time = server.time + 0.5; // run forward
			pPlayer->Bot.BotLegs.f_jump_time = server.time + 0.3; // banzaiii...
		 }
	  }
	  else
		 pPlayer->Bot.BotBody.v_fall_plane_normal = g_vecZero; // else no fall, so reset the edge plane
   }
   // check on the right
   // do a trace 17 units above max stair height right...
   UTIL_TraceHull (v_feet + Vector (0, 0, 18 + 18 + 17),
				   v_feet + Vector (0, 0, 18 + 18 + 17) + (pPlayer->v_right * right_check_dst),
				   ignore_monsters, head_hull, pPlayer->pEntity, &tr1);
   // do a trace one unit above max jump height right...
   UTIL_TraceHull (v_feet + Vector (0, 0, 18 + 64),
				   v_feet + Vector (0, 0, 18 + 64) + (pPlayer->v_right * right_check_dst),
				   ignore_monsters, head_hull, pPlayer->pEntity, &tr2);
   // do a trace one unit lower than max stair height right...
   UTIL_TraceHull (v_feet + Vector (0, 0, 18 + 17),
				   v_feet + Vector (0, 0, 18 + 17) + (pPlayer->v_right * right_check_dst),
				   ignore_monsters, head_hull, pPlayer->pEntity, &tr3);
   // is there something in the way at feet level that is not a slope AND nothing in the way at eye level ?
   if ((tr3.flFraction < 1.0) && (tr3.vecPlaneNormal.z < 0.5) && (tr2.flFraction == 1.0))
	  pPlayer->Bot.BotBody.hit_state |= OBSTACLE_RIGHT_LOWWALL; // bot can jump over this obstacle
   // is there something in the way at eye level AND nothing in the way at knee level ?
   if ((tr2.flFraction < 1.0) && (tr1.flFraction == 1.0) && IsOnFloor (pPlayer->pEntity))
	  pPlayer->Bot.BotBody.hit_state |= OBSTACLE_RIGHT_LOWCEILING; // bot can duck under this obstacle
   // is there something in the way at eye level AND something in the way at knee level ?
   if ((tr2.flFraction < 1.0) && (tr1.flFraction < 1.0))
	  pPlayer->Bot.BotBody.hit_state |= OBSTACLE_RIGHT_WALL; // bot will definitely hit something
   // if the area is clear on the right at head level, trace down to check for a possible fall
   if (tr2.flFraction == 1.0)
   {
	  UTIL_TraceHull (v_feet + Vector (0, 0, 18 + 64) + (pPlayer->v_right * right_check_dst),
					  v_feet + Vector (0, 0, 18 + 64) + (pPlayer->v_right * right_check_dst) + Vector (0, 0, -250),
					  ignore_monsters, head_hull, pPlayer->pEntity, &tr4);
	  // did the trace hit nothing OR some water ?
	  if ((tr4.flFraction == 1.0) || (POINT_CONTENTS (tr4.vecEndPos) == CONTENTS_WATER))
		 pPlayer->Bot.BotBody.hit_state |= OBSTACLE_RIGHT_FALL; // bot can fall on the right
   }
   return; // finished, surrounding obstacles bitmap is filled
}
but definitely what works best is the flat scan. Fire up TraceLines at flat from the left of the bot's field of view, incrementing by 1 degree to the right each time, and send the results to an array. You can then use these distance to build a very convincing navigation.

Code:
void BotSee (player_t *pPlayer)
{
   // this is the function that makes the bot see. It fires bursts of TraceLines, incrementing
   // the trace angle each iteration, and store the results of the scan in an array, which
   // median index corresponds to the direction the bot is facing. This is a logic modeling
   // of the human eye. Unfortunately, the processing power required for a 3D scan is too high,
   // so here we just do a flat scan. The idea is not perfect, though. The list of potential
   // entities in sight is built from the engine's own list, then each of them is replaced in
   // its context, i.e. a corresponding is made between it and the right scan angle.
   // And finally, the bot keeps an eye on the chat messages on its screen...
   bot_eyes_t *pBotEyes;
   float angle, distance;
   int fov_index, entity_index, entity_count;
   Vector v_forward, v_groundslope, v_originalangle, v_viewangle;
   TraceResult tr1, tr2, tr3;
   edict_t *pEntity;
   if (DebugLevel.eyes_disabled)
	  return; // cancel if we don't want the AI to see
   pBotEyes = &pPlayer->Bot.BotEyes; // quick access to bot eyes
   if (!pPlayer->is_alive)
	  return; // cancel if bot is dead (saves tracelines)
   if (pBotEyes->blinded_time > server.time)
	  return; // cancel if bot is blinded
   // ask the engine for the entity list
   // erase the previous array
   memset (pBotEyes->pEntitiesInSight, NULL, sizeof (pBotEyes->pEntitiesInSight));
   // cycle through all entities in game
   entity_count = 0;
   for (entity_index = 0; entity_index < gpGlobals->maxEntities; entity_index++)
   {
	  pEntity = INDEXENT (entity_index + 1); // bind that entity number
	  if (FNullEnt (pEntity))
		 continue; // if unregistered, skip it
	  if (BotCanSeeOfEntity (pPlayer, pEntity) == g_vecZero)
		 continue; // if not in sight, discard this item
	  pBotEyes->pEntitiesInSight[entity_count] = pEntity; // bot can see this entity
	  entity_count++; // we know now one entity more
	  if (entity_count == BOT_EYE_SENSITIVITY)
		 break; // if too much entities in sight, stop
   }
   pBotEyes->entity_count = entity_count; // keep track of how many entity this bot sees
   if (pBotEyes->sample_time > server.time)
	  return; // don't go further if not time to sample the field of view yet
   // figure out the ground slope
   v_forward = Vector (pPlayer->v_forward.x, pPlayer->v_forward.y, 0); // build base vector
   TRACE_LINE (pPlayer->v_origin,
			   pPlayer->v_origin + Vector (0, 0, -9999),
			   ignore_monsters, pPlayer->pEntity, &tr1);
   TRACE_LINE (pPlayer->v_origin + (v_forward * 15),
			   pPlayer->v_origin + (v_forward * 15) + Vector (0, 0, -9999),
			   ignore_monsters, pPlayer->pEntity, &tr2);
   v_groundslope = tr2.vecEndPos - tr1.vecEndPos;
   // now figure out a corresponding angle and clamp its X component (pitch) in bounds
   v_originalangle = UTIL_VecToAngles (v_groundslope);
   v_originalangle.x = -v_originalangle.x * 0.75; // fakeclient aim bug fix + temperate pitch
   if (v_originalangle.x < -45)
	  v_originalangle.x = -45;
   else if (v_originalangle.x > 45)
	  v_originalangle.x = 45;
   // store the capture point
   pBotEyes->v_capture_point = pPlayer->v_eyeposition;
   // scan 100 degrees of bot's field of view from LEFT to RIGHT (yaw angles are inverted)...
   fov_index = 0;
   for (angle = 50; angle >= -50; angle -= (angle * angle) / 1500 + 1.5)
   {
	  v_viewangle = v_originalangle; // restore bot's current v_angle
	  v_viewangle.y = WrapAngle (v_viewangle.y + angle); // pan it from left to right
	  MAKE_VECTORS (v_viewangle); // build base vectors in that direction
	  // trace line slightly under eyes level
	  TRACE_LINE (pPlayer->v_eyeposition,
				  pPlayer->v_eyeposition + (gpGlobals->v_forward * 10000),
				  ignore_monsters, pPlayer->pEntity, &tr1);
	  // if debug level is high, draw the field of view of this bot
	  if (pPlayer->is_watched && (DebugLevel.eyes > 1))
		 UTIL_DrawLine (pListenserverPlayer,
						pPlayer->v_eyeposition,
						pPlayer->v_eyeposition + ((gpGlobals->v_forward * 10000) * tr1.flFraction),
						1, 255, 0, 0);
	  distance = tr1.flFraction * 10000; // store distance to obstacle
	  // if this plane is a slope that is smooth enough for bot to climb it or a slope that goes down...
	  if ((AngleOfVectors (tr1.vecPlaneNormal, Vector (0, 0, 1)) < 30) || (AngleOfVectors (tr1.vecPlaneNormal, Vector (0, 0, -1)) < 30))
	  {
		 // trace line parallel to previous starting a bit lower to get a new hit point
		 TRACE_LINE (pPlayer->v_eyeposition + Vector (0, 0, -5),
					 (pPlayer->v_eyeposition + Vector (0, 0, -5)) + (gpGlobals->v_forward * 10000),
					 ignore_monsters, pPlayer->pEntity, &tr2);
		 // compute a normalized vector parallel to slope
		 Vector v_parallel = (tr1.vecEndPos - tr2.vecEndPos).Normalize ();
		 // trace line parallel to slope so that the bot 'sees' up or down the slope
		 TRACE_LINE (pPlayer->v_eyeposition + (((gpGlobals->v_forward * 10000) * tr1.flFraction) * 0.99),
					 (pPlayer->v_eyeposition + (((gpGlobals->v_forward * 10000) * tr1.flFraction) * 0.99)) + (v_parallel * 10000),
					 ignore_monsters, pPlayer->pEntity, &tr3);
		 // if debug level is high, draw the field of view of this bot
		 if (pPlayer->is_watched && (DebugLevel.eyes > 1))
			UTIL_DrawLine (pListenserverPlayer,
						   pPlayer->v_eyeposition + (((gpGlobals->v_forward * 10000) * tr1.flFraction) * 0.99),
						   (pPlayer->v_eyeposition + (((gpGlobals->v_forward * 10000) * tr1.flFraction) * 0.99)) + ((v_parallel * 10000) * tr3.flFraction),
						   1, 255, 0, 0);
		 // add distance from this traceline to the first one so that bot 'sees' up or down the slope
		 distance += tr3.flFraction * 10000;
	  }
 
	  // store the results of the scan in bot's FOV array
	  pBotEyes->BotFOV[fov_index].scan_angles = v_viewangle;
	  pBotEyes->BotFOV[fov_index].distance = distance;
	  pBotEyes->BotFOV[fov_index].vecEndPos = tr1.vecEndPos;
	  pBotEyes->BotFOV[fov_index].Normal = tr1.vecPlaneNormal;
	  pBotEyes->BotFOV[fov_index].pHit = tr1.pHit;
	  fov_index++; // increment FOV array index
   }
   // we just can't match up with the human eye's refresh rate... bots will sample less often
   pBotEyes->sample_time = server.time + 0.20; // next sampling in 200 ms
   return;
}



RACC home - Bots-United: beer, babies & bots (especially the latter)
"Learn to think by yourself, else others will do it for you."
  
Reply With Quote
Re: Traceline navigation
Old
  (#4)
Lazy
Member
 
Lazy's Avatar
 
Status: Offline
Posts: 236
Join Date: Jan 2004
Location: Toronto, Ontario, Canada
Default Re: Traceline navigation - 13-03-2004

I see, I'm just wondering now about how to get them in the right direction.

The target may be on the other side of the wall, but it could be a huge maze to get there.
  
Reply With Quote
Re: Traceline navigation
Old
  (#5)
Lazy
Member
 
Lazy's Avatar
 
Status: Offline
Posts: 236
Join Date: Jan 2004
Location: Toronto, Ontario, Canada
Default Re: Traceline navigation - 16-03-2004

Seeing as how this thread is fairly new I'll post a new question in it rather than make a new one.

===========================

I've been looking over my code for a while now and I cannot see anything wrong with it.
It's supposed to hurt people who decide to stand ontop of the hive and attack it ( NS ) but it only works for the first map, then becomes unreliable.

I may just be tired, but heres what I have...

Code:
#include <extdll.h>
#include <meta_api.h>
#include <cbase.h>
#include <player.h>
#include <progdefs.h>
float g_flNextDamageTime[ 33 ];
float g_flNextWarnTime[ 33 ];
int DispatchSpawn( edict_t* pEdict )
{
   if ( FClassnameIs( pEdict, "worldspawn" ) )
   {
	  memset( g_flNextWarnTime, 0, sizeof( float ) * 33 );
	  memset( g_flNextDamageTime, 0, sizeof( float ) * 33 );
   }
   RETURN_META_VALUE( MRES_IGNORED, 0 );
}
void PlayerPostThink( edict_t* pEdict )
{
   int iIndex = ENTINDEX( pEdict );   
   CBasePlayer* pPlayer = NULL;
   CBaseEntity* pEntity = NULL;
   TraceResult tr;
   pPlayer = ( CBasePlayer* ) CBaseEntity::Instance( pEdict );
   if ( pPlayer &&						   // Null pointer check
		pPlayer->pev &&					  // ^^
		pPlayer->pev->iuser3 == 1 &&		 // Are we a marine?
		pPlayer->pev->deadflag == DEAD_NO	// Are we alive?
	  )
   {
	  pEntity = CBaseEntity::Instance( pPlayer->pev->groundentity );
	  if ( pEntity &&
		   pEntity->pev &&
		   FClassnameIs( pEntity->pev, "team_hive" ) &&  // A Hive? ( Dont worry about unstarted hives )
		 )
	  {
		 // Trace down to make sure we are still ontop of the hive
		 TRACE_LINE( pPlayer->pev->origin, pPlayer->pev->origin + Vector( 0, 0, -64 ), dont_ignore_monsters, ENT( pPlayer->pev ), &tr );
		 if ( tr.pHit &&
			  tr.pHit == pEntity->edict( )
			)
		 {
			if ( gpGlobals->time >= g_flNextDamageTime[ iIndex ] )
			{
			   // Cause pain sometime in the future
			   g_flNextDamageTime[ iIndex ] = gpGlobals->time + RANDOM_FLOAT( 0.1f, 0.5f );  
			   // Do the damage
			   pPlayer->TakeDamage( VARS( pEntity->pev->owner ), VARS( pEntity->pev ), RANDOM_FLOAT( 15.0f, 50.0f ), DMG_NERVEGAS ); 
			}
			if ( gpGlobals->time >= g_flNextWarnTime[ iIndex ] )
			{
			   g_flNextWarnTime[ iIndex ] = gpGlobals->time + 3.0f;
			   MESSAGE_BEGIN( MSG_ONE_UNRELIABLE, GET_USER_MSG_ID( PLID, "SayText", NULL ), NULL, pPlayer->pev );
				  WRITE_BYTE( -1 );
				  WRITE_STRING( "> You cannot stand ontop of the hive!\n" );
			   MESSAGE_END( );
			}
		 }
	  }
   }
   
   RETURN_META( MRES_IGNORED );
}
  
Reply With Quote
Re: Traceline navigation
Old
  (#6)
Pierre-Marie Baty
Roi de France
 
Pierre-Marie Baty's Avatar
 
Status: Offline
Posts: 5,049
Join Date: Nov 2003
Location: 46°43'60N 0°43'0W 0.187A
Default Re: Traceline navigation - 16-03-2004

erm, several reasons to crash here...

Before doing ANYTHING with an edict_t pointer, test it with FNullEnt(). From my own experience a null pointer test is never enough. FNullEnt() actually makes sure the address the pointer points to is really the address of a registered, active, entity.

You have to do this for:
pPlayer->pev->groundentity (can be null)
pEntity->pev->owner (can be null too: what if the owner dies ?)

Also you can save yourself the cost of the TraceLine: if the player is standing on the ground, his flags will be FL_ONGROUND (standing completely, i.e. origin is above) or FL_PARTIALGROUND (standing partially, one foot aside but one foot on it. Here the TraceLine would fail)
And pev->groundentity is reliable, when it is not NULL. If (ground flags && pev->groundentity && groundentity is hive) then you can inflict your player some damage.



RACC home - Bots-United: beer, babies & bots (especially the latter)
"Learn to think by yourself, else others will do it for you."
  
Reply With Quote
Re: Traceline navigation
Old
  (#7)
Lazy
Member
 
Lazy's Avatar
 
Status: Offline
Posts: 236
Join Date: Jan 2004
Location: Toronto, Ontario, Canada
Default Re: Traceline navigation - 16-03-2004

Hmm, I re-wrote that earlier and I guess I forgot to add the FNullEnt checks which are usually done after the pointer is verified to be not null.

The traceline however is necissary, groundentity will stay the same until you touch another entity. For example, I would fly onto the hive, take some damage and keep getting hurt until I landed on the ground.

My other code behaved the same way, it would work the first map and then fail.
  
Reply With Quote
Re: Traceline navigation
Old
  (#8)
Pierre-Marie Baty
Roi de France
 
Pierre-Marie Baty's Avatar
 
Status: Offline
Posts: 5,049
Join Date: Nov 2003
Location: 46°43'60N 0°43'0W 0.187A
Default Re: Traceline navigation - 16-03-2004

yes, that's what I was saying: to save your traceline, check whether groundentity is non null AND your client has the FL_ONGROUND flag

It works, that's what I use for my bots to build their navmeshes



RACC home - Bots-United: beer, babies & bots (especially the latter)
"Learn to think by yourself, else others will do it for you."
  
Reply With Quote
Re: Traceline navigation
Old
  (#9)
Lazy
Member
 
Lazy's Avatar
 
Status: Offline
Posts: 236
Join Date: Jan 2004
Location: Toronto, Ontario, Canada
Default Re: Traceline navigation - 16-03-2004

Thanks for the info on FL_ONGROUND, I never thought it worked on entities though. The traceline has been removed and the cause of the bug fixed ( I forgot to hook DispatchSpawn ( oops ) ).
  
Reply With Quote
Reply


Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump



Powered by vBulletin® Version 3.8.2
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
vBulletin Skin developed by: vBStyles.com