示例#1
0
// Swaps 2 soldier positions...
void SwapMercPositions( SOLDIERTYPE *pSoldier1, SOLDIERTYPE *pSoldier2 )
{
	INT16 sGridNo1, sGridNo2;

	// OK, save positions...
	sGridNo1 = pSoldier1->sGridNo;
	sGridNo2 = pSoldier2->sGridNo;

	// OK, remove each.....
	RemoveSoldierFromGridNo( pSoldier1 );
	RemoveSoldierFromGridNo( pSoldier2 );

	// OK, test OK destination for each.......
	if ( NewOKDestination( pSoldier1, sGridNo2, TRUE, 0 ) && NewOKDestination( pSoldier2, sGridNo1, TRUE, 0 ) )
	{
		// OK, call teleport function for each.......
		TeleportSoldier( pSoldier1, sGridNo2, FALSE );
		TeleportSoldier( pSoldier2, sGridNo1, FALSE );
	}
	else
	{
		// Place back...
		TeleportSoldier( pSoldier1, sGridNo1, TRUE );
		TeleportSoldier( pSoldier2, sGridNo2, TRUE );
	}
}
示例#2
0
UINT16 FindRandomGridNoFromSweetSpotExcludingSweetSpot( SOLDIERTYPE *pSoldier, INT16 sSweetGridNo, INT8 ubRadius, UINT8 *pubDirection )
{
	INT16		sX, sY;
	INT16		sGridNo;
	INT32					leftmost;
	BOOLEAN	fFound = FALSE;
	UINT32		cnt = 0;

	do
	{
		sX = (UINT16)Random( ubRadius );
		sY = (UINT16)Random( ubRadius );

		leftmost = ( ( sSweetGridNo + ( WORLD_COLS * sY ) )/ WORLD_COLS ) * WORLD_COLS;

		sGridNo = sSweetGridNo + ( WORLD_COLS * sY ) + sX;

		if ( sGridNo == sSweetGridNo )
		{
			continue;
		}

		if ( sGridNo >=0 && sGridNo < WORLD_MAX && 
				 sGridNo >= leftmost && sGridNo < ( leftmost + WORLD_COLS ) )
		{
			// Go on sweet stop
			if ( NewOKDestination( pSoldier, sGridNo, TRUE, pSoldier->bLevel ) )
			{
				fFound = TRUE;
			}
		}

		cnt++;

		if ( cnt > 2000 )
		{
			return( NOWHERE );
		}

	} while( !fFound );

	// Set direction to center of map!
	*pubDirection =  (UINT8)GetDirectionToGridNoFromGridNo( sGridNo, ( ( ( WORLD_ROWS / 2 ) * WORLD_COLS ) + ( WORLD_COLS / 2 ) ) );

	return( sGridNo );

}
示例#3
0
BOOLEAN TeleportSoldier( SOLDIERTYPE *pSoldier, INT16 sGridNo, BOOLEAN fForce )
{
	INT16 sX, sY;

	// Check dest...
	if ( NewOKDestination( pSoldier, sGridNo, TRUE, 0 ) || fForce )
	{
		// TELEPORT TO THIS LOCATION!
		sX = CenterX( sGridNo );
		sY = CenterY( sGridNo );
		EVENT_SetSoldierPosition( pSoldier, (FLOAT) sX, (FLOAT) sY );	

		pSoldier->sFinalDestination = sGridNo;

		// Make call to FOV to update items...
		RevealRoofsAndItems(pSoldier, TRUE, TRUE, pSoldier->bLevel, TRUE );
	
		// Handle sight!
		HandleSight(pSoldier,SIGHT_LOOK | SIGHT_RADIO);

		// Cancel services...
		GivingSoldierCancelServices( pSoldier );

		// Change light....
		if ( pSoldier->bLevel == 0 )
		{
			if(pSoldier->iLight!=(-1))
				LightSpriteRoofStatus(pSoldier->iLight, FALSE );
		}
		else
		{
			if(pSoldier->iLight!=(-1))
				LightSpriteRoofStatus(pSoldier->iLight, TRUE );
		}
		return( TRUE );
	}

	return( FALSE );
}
示例#4
0
文件: Movement.c 项目: bowlofstew/ja2
int LegalNPCDestination(SOLDIERTYPE *pSoldier, INT16 sGridno, UINT8 ubPathMode, UINT8 ubWaterOK, UINT8 fFlags)
{
	BOOLEAN fSkipTilesWithMercs;
 
	if ((sGridno < 0) || (sGridno >= GRIDSIZE))
  {
#ifdef RECORDNET
   fprintf(NetDebugFile,"LegalNPC->sDestination: ERROR - rcvd invalid gridno %d",gridno);
#endif

#ifdef BETAVERSION
   NumMessage("LegalNPC->sDestination: ERROR - rcvd invalid gridno ",gridno);
#endif

   return(FALSE);
  }

	// return false if gridno on different level from merc
	if ( GridNoOnVisibleWorldTile( pSoldier->sGridNo ) && gpWorldLevelData[ pSoldier->sGridNo ].sHeight != gpWorldLevelData[ sGridno ].sHeight )
	{
		return( FALSE );
	}


	// skip mercs if turnbased and adjacent AND not doing an IGNORE_PATH check (which is used almost exclusively by GoAsFarAsPossibleTowards)
	fSkipTilesWithMercs = (gfTurnBasedAI && ubPathMode != IGNORE_PATH && SpacesAway( pSoldier->sGridNo, sGridno ) == 1 );

 // if this gridno is an OK destination
 // AND the gridno is NOT in a tear-gassed tile when we have no gas mask
 // AND someone is NOT already standing there
 // AND we're NOT already standing at that gridno
 // AND the gridno hasn't been black-listed for us

 // Nov 28 98: skip people in destination tile if in turnbased
 if ( ( NewOKDestination(pSoldier, sGridno, fSkipTilesWithMercs, pSoldier->bLevel ) ) &&
				( !InGas( pSoldier, sGridno ) ) &&
				( sGridno != pSoldier->sGridNo ) &&
				( sGridno != pSoldier->sBlackList ) )
 /*
 if ( ( NewOKDestination(pSoldier, sGridno, FALSE, pSoldier->bLevel ) ) &&
				( !(gpWorldLevelData[ sGridno ].ubExtFlags[0] & (MAPELEMENT_EXT_SMOKE | MAPELEMENT_EXT_TEARGAS | MAPELEMENT_EXT_MUSTARDGAS)) || ( pSoldier->inv[ HEAD1POS ].usItem == GASMASK || pSoldier->inv[ HEAD2POS ].usItem == GASMASK ) ) &&
				( sGridno != pSoldier->sGridNo ) &&
				( sGridno != pSoldier->sBlackList ) )*/
 /*
 if ( ( NewOKDestination(pSoldier,sGridno,ALLPEOPLE, pSoldier->bLevel ) ) &&
				( !(gpWorldLevelData[ sGridno ].ubExtFlags[0] & (MAPELEMENT_EXT_SMOKE | MAPELEMENT_EXT_TEARGAS | MAPELEMENT_EXT_MUSTARDGAS)) || ( pSoldier->inv[ HEAD1POS ].usItem == GASMASK || pSoldier->inv[ HEAD2POS ].usItem == GASMASK ) ) &&
				( sGridno != pSoldier->sGridNo ) &&
				( sGridno != pSoldier->sBlackList ) )
				*/
   {
    
	  // if water's a problem, and gridno is in a water tile (bridges are OK)
		if (!ubWaterOK && Water(sGridno))
		  return(FALSE);

    // passed all checks, now try to make sure we can get there!
    switch (ubPathMode)
     {
      // if finding a path wasn't asked for (could have already been done,
      // for example), don't bother
      case IGNORE_PATH     :	return(TRUE);

      case ENSURE_PATH     :	if ( FindBestPath( pSoldier, sGridno, pSoldier->bLevel, WALKING, COPYROUTE, fFlags ) )
															{
			   												return(TRUE);        // legal destination
															}
      												else // got this far, but found no clear path,
															{
																// so test fails
        												return(FALSE);
															}
															// *** NOTE: movement mode hardcoded to WALKING !!!!!
			case ENSURE_PATH_COST:	return(PlotPath(pSoldier,sGridno,FALSE,FALSE,FALSE,WALKING,FALSE,FALSE,0));

      default              :
#ifdef BETAVERSION
			     NumMessage("LegalNPC->sDestination: ERROR - illegal pathMode = ",ubPathMode);
#endif
			     return(FALSE);
     }
   }
 else  // something failed - didn't even have to test path
   return(FALSE);       	// illegal destination
}
示例#5
0
文件: Movement.c 项目: bowlofstew/ja2
INT8 PointPatrolAI(SOLDIERTYPE *pSoldier)
{
 INT16 sPatrolPoint;
 INT8  bOldOrders;


 sPatrolPoint = pSoldier->usPatrolGrid[pSoldier->bNextPatrolPnt];

 // if we're already there, advance next patrol point
 if (pSoldier->sGridNo == sPatrolPoint || pSoldier->bNextPatrolPnt == 0)
  {
   // find next valid patrol point
   do
    {
     sPatrolPoint = NextPatrolPoint(pSoldier);
    }
   while ((sPatrolPoint != NOWHERE) && (NewOKDestination(pSoldier,sPatrolPoint,IGNOREPEOPLE, pSoldier->bLevel) < 1));

   // if we're back where we started, then ALL other patrol points are junk!
   if (pSoldier->sGridNo == sPatrolPoint)
    {
#ifdef BETAVERSION
     NumMessage("PROBLEM WITH SCENARIO: All other patrol points are invalid for guynum ",pSoldier->ubID);
#endif
     // force change of orders & an abort
     sPatrolPoint = NOWHERE;
    }
  }

 // if we don't have a legal patrol point
 if (sPatrolPoint == NOWHERE)
  {
#ifdef BETAVERSION
   NumMessage("PointPatrolAI: ERROR - no legal patrol point for %d",pSoldier->ubID);
#endif

   // over-ride orders to something safer
   pSoldier->bOrders = FARPATROL;
   return(FALSE);
  }


 // make sure we can get there from here at this time, if we can't get all
 // the way there, at least do our best to get close
 if (LegalNPCDestination(pSoldier,sPatrolPoint,ENSURE_PATH,WATEROK,0))
  {
   pSoldier->bPathStored = TRUE;	    // optimization - Ian
   pSoldier->usActionData = sPatrolPoint;
  }
 else
  {
   // temporarily extend roaming range to infinity by changing orders, else
   // this won't work if the next patrol point is > 10 tiles away!
   bOldOrders					= pSoldier->bOrders;
   pSoldier->bOrders	= ONCALL;

   pSoldier->usActionData = GoAsFarAsPossibleTowards(pSoldier,sPatrolPoint,pSoldier->bAction);

   pSoldier->bOrders = bOldOrders;

   // if it's not possible to get any closer, that's OK, but fail this call
   if (pSoldier->usActionData == NOWHERE)
     return(FALSE);
  }


 // passed all tests - start moving towards next patrol point
#ifdef DEBUGDECISIONS
 sprintf(tempstr,"%s - POINT PATROL to grid %d",pSoldier->name,pSoldier->usActionData);
 AIPopMessage(tempstr);
#endif

 return(TRUE);
}
示例#6
0
UINT16 FindRandomGridNoFromSweetSpot( SOLDIERTYPE *pSoldier, INT16 sSweetGridNo, INT8 ubRadius, UINT8 *pubDirection )
{
	INT16		sX, sY;
	INT16		sGridNo;
	INT32					leftmost;
	BOOLEAN	fFound = FALSE;
	UINT32		cnt = 0;
	SOLDIERTYPE soldier;
	UINT8 ubSaveNPCAPBudget;
	UINT8 ubSaveNPCDistLimit;
	UINT8	ubBestDirection=0;
	INT16  sTop, sBottom;
	INT16  sLeft, sRight;
	INT16  cnt1, cnt2;
	UINT8	 ubRoomNum;

	//Save AI pathing vars.  changing the distlimit restricts how 
	//far away the pathing will consider.
	ubSaveNPCAPBudget = gubNPCAPBudget;
	ubSaveNPCDistLimit = gubNPCDistLimit;
	gubNPCAPBudget = 0;
	gubNPCDistLimit = ubRadius;

	//create dummy soldier, and use the pathing to determine which nearby slots are
	//reachable.
	memset( &soldier, 0, sizeof( SOLDIERTYPE ) );
	soldier.bLevel = 0;
	soldier.bTeam = 1;
	soldier.sGridNo = sSweetGridNo;

	sTop		= ubRadius;
	sBottom = -ubRadius;
	sLeft   = - ubRadius;
	sRight  = ubRadius;

	// ATE: CHECK FOR BOUNDARIES!!!!!!
	for( cnt1 = sBottom; cnt1 <= sTop; cnt1++ )
	{
		leftmost = ( ( sSweetGridNo + ( WORLD_COLS * cnt1 ) )/ WORLD_COLS ) * WORLD_COLS;

		for( cnt2 = sLeft; cnt2 <= sRight; cnt2++ )
		{
			sGridNo = sSweetGridNo + ( WORLD_COLS * cnt1 ) + cnt2;
			if( sGridNo >=0 && sGridNo < WORLD_MAX && sGridNo >= leftmost && sGridNo < ( leftmost + WORLD_COLS ) )
			{
				gpWorldLevelData[ sGridNo ].uiFlags &= (~MAPELEMENT_REACHABLE);
			}
		}
	}

	//Now, find out which of these gridnos are reachable 
	//(use the fake soldier and the pathing settings)
	FindBestPath( &soldier, NOWHERE, 0, WALKING, COPYREACHABLE, ( PATH_IGNORE_PERSON_AT_DEST | PATH_THROUGH_PEOPLE ) );

	do
	{
		sX = (UINT16)Random( ubRadius );
		sY = (UINT16)Random( ubRadius );

		leftmost = ( ( sSweetGridNo + ( WORLD_COLS * sY ) )/ WORLD_COLS ) * WORLD_COLS;

		sGridNo = sSweetGridNo + ( WORLD_COLS * sY ) + sX;

		if ( sGridNo >=0 && sGridNo < WORLD_MAX && 
				 sGridNo >= leftmost && sGridNo < ( leftmost + WORLD_COLS ) 
				&& gpWorldLevelData[ sGridNo ].uiFlags & MAPELEMENT_REACHABLE )
		{
			// Go on sweet stop
			if ( NewOKDestination( pSoldier, sGridNo, TRUE , pSoldier->bLevel) )
			{
				// If we are a crow, we need this additional check
				if ( pSoldier->ubBodyType == CROW )
				{
					if ( !InARoom( sGridNo, &ubRoomNum ) )
					{
						fFound = TRUE;
					}
				}
				else
				{
					fFound = TRUE;
				}
			}
		}

		cnt++;

		if ( cnt > 2000 )
		{
			return( NOWHERE );
		}

	} while( !fFound );

	// Set direction to center of map!
	*pubDirection =  (UINT8)GetDirectionToGridNoFromGridNo( sGridNo, ( ( ( WORLD_ROWS / 2 ) * WORLD_COLS ) + ( WORLD_COLS / 2 ) ) );

	gubNPCAPBudget = ubSaveNPCAPBudget;
	gubNPCDistLimit = ubSaveNPCDistLimit;

	return( sGridNo );

}
示例#7
0
UINT16 FindGridNoFromSweetSpotExcludingSweetSpotInQuardent( SOLDIERTYPE *pSoldier, INT16 sSweetGridNo, INT8 ubRadius, UINT8 *pubDirection, INT8 ubQuardentDir )
{
	INT16  sTop, sBottom;
	INT16  sLeft, sRight;
	INT16  cnt1, cnt2;
	INT16		sGridNo;
	INT32		uiRange, uiLowestRange = 999999;
	INT16		sLowestGridNo=-1;
	INT32					leftmost;
	BOOLEAN	fFound = FALSE;


	sTop		= ubRadius;
	sBottom = -ubRadius;
	sLeft   = - ubRadius;
	sRight  = ubRadius;

	// Switch on quadrent
	if ( ubQuardentDir == SOUTHEAST )
	{
		sBottom = 0;
		sLeft = 0;
	}

	uiLowestRange = 999999;	

	for( cnt1 = sBottom; cnt1 <= sTop; cnt1++ )
	{
		leftmost = ( ( sSweetGridNo + ( WORLD_COLS * cnt1 ) )/ WORLD_COLS ) * WORLD_COLS;

		for( cnt2 = sLeft; cnt2 <= sRight; cnt2++ )
		{
			sGridNo = sSweetGridNo + ( WORLD_COLS * cnt1 ) + cnt2;

			if ( sSweetGridNo == sGridNo )
			{
				continue;
			}

			if ( sGridNo >=0 && sGridNo < WORLD_MAX && 
					 sGridNo >= leftmost && sGridNo < ( leftmost + WORLD_COLS ) )
			{

					// Go on sweet stop
					if ( NewOKDestination( pSoldier, sGridNo, TRUE, pSoldier->bLevel ) )
					{
						uiRange = GetRangeInCellCoordsFromGridNoDiff( sSweetGridNo, sGridNo );

						if ( uiRange < uiLowestRange )
						{
							sLowestGridNo = sGridNo;
							uiLowestRange = uiRange;
							fFound = TRUE;
						}
					}
			}
		}

	}

	if ( fFound )
	{
		// Set direction to center of map!
		*pubDirection =  (UINT8)GetDirectionToGridNoFromGridNo( sLowestGridNo, ( ( ( WORLD_ROWS / 2 ) * WORLD_COLS ) + ( WORLD_COLS / 2 ) ) );

		return( sLowestGridNo );
	}
	else
	{
		return( NOWHERE );
	}
}
示例#8
0
UINT16 FindGridNoFromSweetSpotWithStructDataFromSoldier( SOLDIERTYPE *pSoldier, UINT16 usAnimState, INT8 ubRadius, UINT8 *pubDirection, BOOLEAN fClosestToMerc, SOLDIERTYPE *pSrcSoldier )
{
	INT16  sTop, sBottom;
	INT16  sLeft, sRight;
	INT16  cnt1, cnt2, cnt3;
	INT16		sGridNo;
	INT32		uiRange, uiLowestRange = 999999;
	INT16		sLowestGridNo=-1;
	INT32					leftmost;
	BOOLEAN	fFound = FALSE;
	UINT8 ubSaveNPCAPBudget;
	UINT8 ubSaveNPCDistLimit;
	UINT8	ubBestDirection=0;
	INT16 sSweetGridNo;
	SOLDIERTYPE soldier;
	
	sSweetGridNo = pSrcSoldier->sGridNo;


	//Save AI pathing vars.  changing the distlimit restricts how 
	//far away the pathing will consider.
	ubSaveNPCAPBudget = gubNPCAPBudget;
	ubSaveNPCDistLimit = gubNPCDistLimit;
	gubNPCAPBudget = 0;
	gubNPCDistLimit = ubRadius;

	//create dummy soldier, and use the pathing to determine which nearby slots are
	//reachable.
	memset( &soldier, 0, sizeof( SOLDIERTYPE ) );
	soldier.bLevel = 0;
	soldier.bTeam = 1;
	soldier.sGridNo = sSweetGridNo;

	sTop		= ubRadius;
	sBottom = -ubRadius;
	sLeft   = - ubRadius;
	sRight  = ubRadius;

	//clear the mapelements of potential residue MAPELEMENT_REACHABLE flags
	//in the square region.
	// ATE: CHECK FOR BOUNDARIES!!!!!!
	for( cnt1 = sBottom; cnt1 <= sTop; cnt1++ )
	{
		leftmost = ( ( sSweetGridNo + ( WORLD_COLS * cnt1 ) )/ WORLD_COLS ) * WORLD_COLS;

		for( cnt2 = sLeft; cnt2 <= sRight; cnt2++ )
		{
			sGridNo = sSweetGridNo + ( WORLD_COLS * cnt1 ) + cnt2;
			if( sGridNo >=0 && sGridNo < WORLD_MAX && sGridNo >= leftmost && sGridNo < ( leftmost + WORLD_COLS ) )
			{
				gpWorldLevelData[ sGridNo ].uiFlags &= (~MAPELEMENT_REACHABLE);
			}
		}
	}

	//Now, find out which of these gridnos are reachable 
	FindBestPath( &soldier, NOWHERE, 0, WALKING, COPYREACHABLE, ( PATH_IGNORE_PERSON_AT_DEST | PATH_THROUGH_PEOPLE ) );
	
	uiLowestRange = 999999;	

	for( cnt1 = sBottom; cnt1 <= sTop; cnt1++ )
	{
		leftmost = ( ( sSweetGridNo + ( WORLD_COLS * cnt1 ) )/ WORLD_COLS ) * WORLD_COLS;

		for( cnt2 = sLeft; cnt2 <= sRight; cnt2++ )
		{
			sGridNo = sSweetGridNo + ( WORLD_COLS * cnt1 ) + cnt2;
			if( sGridNo >=0 && sGridNo < WORLD_MAX && sGridNo >= leftmost && sGridNo < ( leftmost + WORLD_COLS ) 
				&& gpWorldLevelData[ sGridNo ].uiFlags & MAPELEMENT_REACHABLE )
			{
				// Go on sweet stop
				if ( NewOKDestination( pSoldier, sGridNo, TRUE, pSoldier->bLevel ) )
				{
					BOOLEAN fDirectionFound = FALSE;
					UINT16	usOKToAddStructID;
					STRUCTURE_FILE_REF * pStructureFileRef;
					UINT16							 usAnimSurface;

					if ( fClosestToMerc != 3 )
					{
						if ( pSoldier->pLevelNode != NULL && pSoldier->pLevelNode->pStructureData != NULL )
						{
							usOKToAddStructID = pSoldier->pLevelNode->pStructureData->usStructureID;
						}
						else
						{
							usOKToAddStructID = INVALID_STRUCTURE_ID;
						}

						// Get animation surface...
			 			usAnimSurface = DetermineSoldierAnimationSurface( pSoldier, usAnimState );
						// Get structure ref...
						pStructureFileRef = GetAnimationStructureRef( pSoldier->ubID, usAnimSurface, usAnimState );

						// Check each struct in each direction
						for( cnt3 = 0; cnt3 < 8; cnt3++ )
						{
							if (OkayToAddStructureToWorld( (INT16)sGridNo, pSoldier->bLevel, &(pStructureFileRef->pDBStructureRef[gOneCDirection[ cnt3 ]]), usOKToAddStructID ) )
							{
								fDirectionFound = TRUE;
								break;
							}

						}
					}
					else
					{
						fDirectionFound = TRUE;
						cnt3 = (UINT8)Random( 8 );
					}

					if ( fDirectionFound )
					{
						if ( fClosestToMerc == 1 )
						{
							uiRange = GetRangeInCellCoordsFromGridNoDiff( pSoldier->sGridNo, sGridNo );
						}
						else if ( fClosestToMerc == 2 )
						{
							uiRange = GetRangeInCellCoordsFromGridNoDiff( pSoldier->sGridNo, sGridNo ) + GetRangeInCellCoordsFromGridNoDiff( sSweetGridNo, sGridNo );
						}
						else
						{
							//uiRange = GetRangeInCellCoordsFromGridNoDiff( sSweetGridNo, sGridNo );
							uiRange = abs((sSweetGridNo / MAXCOL) - (sGridNo / MAXCOL)) +
								abs((sSweetGridNo % MAXROW) - (sGridNo % MAXROW));
						}

						if ( uiRange < uiLowestRange || (uiRange == uiLowestRange && PythSpacesAway( pSoldier->sGridNo, sGridNo ) < PythSpacesAway( pSoldier->sGridNo, sLowestGridNo ) ) )
						{
							ubBestDirection = (UINT8)cnt3;
							sLowestGridNo		= sGridNo;
							uiLowestRange		= uiRange;
							fFound = TRUE;
						}
					}
				}
			}
		}
	}
	gubNPCAPBudget = ubSaveNPCAPBudget;
	gubNPCDistLimit = ubSaveNPCDistLimit;
	if ( fFound )
	{
		// Set direction we chose...
		*pubDirection = ubBestDirection;

		return( sLowestGridNo );
	}
	else
	{
		return( NOWHERE );
	}
}
示例#9
0
//Kris:  modified to actually path from sweetspot to gridno.  Previously, it only checked if the
//destination was sittable (though it was possible that that location would be trapped.
UINT16 FindGridNoFromSweetSpot( SOLDIERTYPE *pSoldier, INT16 sSweetGridNo, INT8 ubRadius, UINT8 *pubDirection )
{
	INT16  sTop, sBottom;
	INT16  sLeft, sRight;
	INT16  cnt1, cnt2;
	INT16		sGridNo;
	INT32		uiRange, uiLowestRange = 999999;
	INT16		sLowestGridNo=-1;
	INT32					leftmost;
	BOOLEAN	fFound = FALSE;
	SOLDIERTYPE soldier;
	UINT8 ubSaveNPCAPBudget;
	UINT8 ubSaveNPCDistLimit;

	//Save AI pathing vars.  changing the distlimit restricts how 
	//far away the pathing will consider.
	ubSaveNPCAPBudget = gubNPCAPBudget;
	ubSaveNPCDistLimit = gubNPCDistLimit;
	gubNPCAPBudget = 0;
	gubNPCDistLimit = ubRadius;

	//create dummy soldier, and use the pathing to determine which nearby slots are
	//reachable.
	memset( &soldier, 0, sizeof( SOLDIERTYPE ) );
	soldier.bLevel = 0;
	soldier.bTeam = 1;
	soldier.sGridNo = sSweetGridNo;
 
	sTop		= ubRadius;
	sBottom = -ubRadius;
	sLeft   = - ubRadius;
	sRight  = ubRadius;

	//clear the mapelements of potential residue MAPELEMENT_REACHABLE flags
	//in the square region.
	// ATE: CHECK FOR BOUNDARIES!!!!!!
	for( cnt1 = sBottom; cnt1 <= sTop; cnt1++ )
	{
		leftmost = ( ( sSweetGridNo + ( WORLD_COLS * cnt1 ) )/ WORLD_COLS ) * WORLD_COLS;

		for( cnt2 = sLeft; cnt2 <= sRight; cnt2++ )
		{
			sGridNo = sSweetGridNo + ( WORLD_COLS * cnt1 ) + cnt2;
			if( sGridNo >=0 && sGridNo < WORLD_MAX && sGridNo >= leftmost && sGridNo < ( leftmost + WORLD_COLS ) )
			{
				gpWorldLevelData[ sGridNo ].uiFlags &= (~MAPELEMENT_REACHABLE);
			}
		}
	}

	//Now, find out which of these gridnos are reachable 
	//(use the fake soldier and the pathing settings)
	FindBestPath( &soldier, NOWHERE, 0, WALKING, COPYREACHABLE, ( PATH_IGNORE_PERSON_AT_DEST | PATH_THROUGH_PEOPLE ) );
	
	uiLowestRange = 999999;	

	for( cnt1 = sBottom; cnt1 <= sTop; cnt1++ )
	{
		leftmost = ( ( sSweetGridNo + ( WORLD_COLS * cnt1 ) )/ WORLD_COLS ) * WORLD_COLS;

		for( cnt2 = sLeft; cnt2 <= sRight; cnt2++ )
		{
			sGridNo = sSweetGridNo + ( WORLD_COLS * cnt1 ) + cnt2;
			if( sGridNo >=0 && sGridNo < WORLD_MAX && sGridNo >= leftmost && sGridNo < ( leftmost + WORLD_COLS ) 
				&& gpWorldLevelData[ sGridNo ].uiFlags & MAPELEMENT_REACHABLE )
			{
				// Go on sweet stop
				if ( NewOKDestination( pSoldier, sGridNo, TRUE, pSoldier->bLevel ) )
				{
					// ATE: INstead of using absolute range, use the path cost!
				  //uiRange = PlotPath( &soldier, sGridNo, NO_COPYROUTE, NO_PLOT, TEMPORARY, WALKING, NOT_STEALTH, FORWARD, 50 );
					uiRange = CardinalSpacesAway( sSweetGridNo, sGridNo );
					
				//	if ( uiRange == 0 )
				//	{
				//		uiRange = 999999;
				//	}

					if ( uiRange < uiLowestRange )
					{
						sLowestGridNo = sGridNo;
						uiLowestRange = uiRange;
						fFound = TRUE;
					}
				}
			}
		}
	}
	gubNPCAPBudget = ubSaveNPCAPBudget;
	gubNPCDistLimit = ubSaveNPCDistLimit;
	if ( fFound )
	{
		// Set direction to center of map!
		*pubDirection =  (UINT8)GetDirectionToGridNoFromGridNo( sLowestGridNo, ( ( ( WORLD_ROWS / 2 ) * WORLD_COLS ) + ( WORLD_COLS / 2 ) ) );
		return( sLowestGridNo );
	}
	else
	{
		return( NOWHERE );
	}
}
示例#10
0
BOOLEAN HandleNextTileWaiting( SOLDIERTYPE *pSoldier )
{
	// Buddy is waiting to continue his path
	INT8		bBlocked, bPathBlocked;
	INT16		sCost;
	INT16   sNewGridNo, sCheckGridNo;
	UINT8		ubDirection, bCauseDirection;
	UINT8		ubPerson;
	UINT8		fFlags = 0;

 
	if ( pSoldier->fDelayedMovement )
	{
		if ( TIMECOUNTERDONE( pSoldier->NextTileCounter, NEXT_TILE_CHECK_DELAY ) )
		{
			RESETTIMECOUNTER( pSoldier->NextTileCounter, NEXT_TILE_CHECK_DELAY );

			// Get direction from gridno...
			bCauseDirection = (INT8)GetDirectionToGridNoFromGridNo( pSoldier->sGridNo, pSoldier->sDelayedMovementCauseGridNo );

			bBlocked = TileIsClear( pSoldier, bCauseDirection, pSoldier->sDelayedMovementCauseGridNo, pSoldier->bLevel );

			// If we are waiting for a temp blockage.... continue to wait
			if ( pSoldier->fDelayedMovement >= 100 &&  bBlocked == MOVE_TILE_TEMP_BLOCKED )
			{
				// ATE: Increment 1
				pSoldier->fDelayedMovement++;

				// Are we close enough to give up? ( and are a pc )
				if ( pSoldier->fDelayedMovement > 120 )
				{
					// Quit...
					SetFinalTile( pSoldier, pSoldier->sGridNo, TRUE );
					pSoldier->fDelayedMovement = FALSE;
				}
				return( TRUE );
			}

			// Try new path if anything but temp blockage!
			if ( bBlocked != MOVE_TILE_TEMP_BLOCKED )
			{
				// Set to normal delay
				if ( pSoldier->fDelayedMovement >= 100 && pSoldier->fDelayedMovement != 150 )
				{
					pSoldier->fDelayedMovement = 1;
				}

				// Default to pathing through people
				fFlags = PATH_THROUGH_PEOPLE;

				// Now, if we are in the state where we are desparently trying to get out...
				// Use other flag
				// CJC: path-through-people includes ignoring person at dest
				/*
				if ( pSoldier->fDelayedMovement >= 150 )
				{
					fFlags = PATH_IGNORE_PERSON_AT_DEST;
				}
				*/

				// Check destination first!
				if ( pSoldier->sAbsoluteFinalDestination == pSoldier->sFinalDestination )
				{
					// on last lap of scripted move, make sure we get to final dest
					sCheckGridNo = pSoldier->sAbsoluteFinalDestination;					
				}
				else if (!NewOKDestination( pSoldier, pSoldier->sFinalDestination, TRUE, pSoldier->bLevel ))
				{
					if ( pSoldier->fDelayedMovement >= 150 )
					{
						// OK, look around dest for the first one!
						sCheckGridNo = FindGridNoFromSweetSpot( pSoldier, pSoldier->sFinalDestination, 6, &ubDirection );

						if ( sCheckGridNo == NOWHERE )
						{
							// If this is nowhere, try harder!
							sCheckGridNo = FindGridNoFromSweetSpot( pSoldier, pSoldier->sFinalDestination, 16, &ubDirection );
						}
					}
					else
					{
						// OK, look around dest for the first one!
						sCheckGridNo = FindGridNoFromSweetSpotThroughPeople( pSoldier, pSoldier->sFinalDestination, 6, &ubDirection );

						if ( sCheckGridNo == NOWHERE )
						{
							// If this is nowhere, try harder!
							sCheckGridNo = FindGridNoFromSweetSpotThroughPeople( pSoldier, pSoldier->sFinalDestination, 16, &ubDirection );
						}
					}
				}
				else
				{
					sCheckGridNo = pSoldier->sFinalDestination;
				}

				// Try another path to destination
				// ATE: Allow path to exit grid!
				if ( pSoldier->ubWaitActionToDo == 1 && gubWaitingForAllMercsToExitCode == WAIT_FOR_MERCS_TO_WALK_TO_GRIDNO )
				{
					gfPlotPathToExitGrid = TRUE;
				}

				sCost = (INT16) FindBestPath( pSoldier, sCheckGridNo, pSoldier->bLevel, pSoldier->usUIMovementMode, NO_COPYROUTE, fFlags );
				gfPlotPathToExitGrid = FALSE;
				
				// Can we get there
				if ( sCost > 0 )
				{
					// Is the next tile blocked too?
					sNewGridNo = NewGridNo( (UINT16)pSoldier->sGridNo, DirectionInc( (UINT8)guiPathingData[ 0 ] ) );

					bPathBlocked = TileIsClear( pSoldier, (UINT8)guiPathingData[ 0 ], sNewGridNo, pSoldier->bLevel );

					if ( bPathBlocked == MOVE_TILE_STATIONARY_BLOCKED )
					{
						// Try to path around everyone except dest person

						if ( pSoldier->ubWaitActionToDo == 1 && gubWaitingForAllMercsToExitCode == WAIT_FOR_MERCS_TO_WALK_TO_GRIDNO )
						{
							gfPlotPathToExitGrid = TRUE;
						}

						sCost = (INT16) FindBestPath( pSoldier, sCheckGridNo, pSoldier->bLevel, pSoldier->usUIMovementMode, NO_COPYROUTE, PATH_IGNORE_PERSON_AT_DEST );

						gfPlotPathToExitGrid = FALSE;

						// Is the next tile in this new path blocked too?
						sNewGridNo = NewGridNo( (UINT16)pSoldier->sGridNo, DirectionInc( (UINT8)guiPathingData[ 0 ] ) );

						bPathBlocked = TileIsClear( pSoldier, (UINT8)guiPathingData[ 0 ], sNewGridNo, pSoldier->bLevel );

						// now working with a path which does not go through people				
						pSoldier->ubDelayedMovementFlags &= (~DELAYED_MOVEMENT_FLAG_PATH_THROUGH_PEOPLE);
					}
					else
					{
						// path through people worked fine
						if ( pSoldier->fDelayedMovement < 150 )
						{
							pSoldier->ubDelayedMovementFlags |= DELAYED_MOVEMENT_FLAG_PATH_THROUGH_PEOPLE;
						}
					}

					// Are we clear?
					if ( bPathBlocked == MOVE_TILE_CLEAR )
					{
						// Go for it path!
						if ( pSoldier->ubWaitActionToDo == 1 && gubWaitingForAllMercsToExitCode == WAIT_FOR_MERCS_TO_WALK_TO_GRIDNO )
						{
							gfPlotPathToExitGrid = TRUE;
						}

						//pSoldier->fDelayedMovement = FALSE;
						// ATE: THis will get set in EENT_GetNewSoldierPath....
						pSoldier->usActionData = sCheckGridNo;

						pSoldier->bPathStored = FALSE;

						EVENT_GetNewSoldierPath( pSoldier, sCheckGridNo, pSoldier->usUIMovementMode );
						gfPlotPathToExitGrid = FALSE;

						return( TRUE );
					}
				}

				pSoldier->fDelayedMovement++;

				if ( pSoldier->fDelayedMovement == 99 )
				{
					// Cap at 99
					pSoldier->fDelayedMovement = 99;
				}

				// Do we want to force a swap?
				if (pSoldier->fDelayedMovement == 3 && (pSoldier->sAbsoluteFinalDestination != NOWHERE || gTacticalStatus.fAutoBandageMode) )
				{
					// with person who is in the way?
					ubPerson = WhoIsThere2( pSoldier->sDelayedMovementCauseGridNo, pSoldier->bLevel );

					// if either on a mission from god, or two AI guys not on stationary...
					if ( ubPerson != NOBODY && ( pSoldier->ubQuoteRecord != 0 || ( pSoldier->bTeam != gbPlayerNum && pSoldier->bOrders != STATIONARY && MercPtrs[ ubPerson ]->bTeam != gbPlayerNum && MercPtrs[ ubPerson ]->bOrders != STATIONARY ) || (pSoldier->bTeam == gbPlayerNum && gTacticalStatus.fAutoBandageMode && !(MercPtrs[ ubPerson ]->bTeam == CIV_TEAM && MercPtrs[ ubPerson ]->bOrders == STATIONARY ) ) ) )
					{					
						// Swap now!
						//MercPtrs[ ubPerson ]->fBlockedByAnotherMerc = FALSE;

						// Restore final dest....
						//MercPtrs[ ubPerson ]->sFinalDestination = sTempDestGridNo;

						// Swap merc positions.....
						SwapMercPositions( pSoldier, MercPtrs[ ubPerson ] );
						
						// With these two guys swapped, we should try to continue on our way....				
						pSoldier->fDelayedMovement = FALSE;

						// We must calculate the path here so that we can give it the "through people" parameter
						if ( gTacticalStatus.fAutoBandageMode && pSoldier->sAbsoluteFinalDestination == NOWHERE )
						{
							FindBestPath( pSoldier, pSoldier->sFinalDestination, pSoldier->bLevel, pSoldier->usUIMovementMode, COPYROUTE, PATH_THROUGH_PEOPLE );
						}
						else if ( pSoldier->sAbsoluteFinalDestination != NOWHERE && !FindBestPath( pSoldier, pSoldier->sAbsoluteFinalDestination, pSoldier->bLevel, pSoldier->usUIMovementMode, COPYROUTE, PATH_THROUGH_PEOPLE ) )
						{
							// check to see if we're there now!
							if ( pSoldier->sGridNo == pSoldier->sAbsoluteFinalDestination )
							{
								NPCReachedDestination( pSoldier, FALSE );
								pSoldier->bNextAction = AI_ACTION_WAIT;
								pSoldier->usNextActionData = 500;
								return( TRUE );
							}
						}
						pSoldier->bPathStored = TRUE;

						EVENT_GetNewSoldierPath( pSoldier, pSoldier->sAbsoluteFinalDestination, pSoldier->usUIMovementMode );
						//EVENT_GetNewSoldierPath( MercPtrs[ ubPerson ], MercPtrs[ ubPerson ]->sFinalDestination, MercPtrs[ ubPerson ]->usUIMovementMode );					
					}

				}

				// Are we close enough to give up? ( and are a pc )
				if ( pSoldier->fDelayedMovement > 20 && pSoldier->fDelayedMovement != 150)
				{
					if ( PythSpacesAway( pSoldier->sGridNo, pSoldier->sFinalDestination ) < 5 && pSoldier->bTeam == gbPlayerNum )
					{
						// Quit...
						SetFinalTile( pSoldier, pSoldier->sGridNo, FALSE );
						pSoldier->fDelayedMovement = FALSE;
					}
				}

				// Are we close enough to give up? ( and are a pc )
				if ( pSoldier->fDelayedMovement > 170 )
				{
					if ( PythSpacesAway( pSoldier->sGridNo, pSoldier->sFinalDestination ) < 5 && pSoldier->bTeam == gbPlayerNum )
					{
						// Quit...
						SetFinalTile( pSoldier, pSoldier->sGridNo, FALSE );
						pSoldier->fDelayedMovement = FALSE;
					}
				}

			}
		}
	}
	return( TRUE );
}
示例#11
0
BUILDING * GenerateBuilding( INT16 sDesiredSpot )
{
	UINT32	uiLoop;
	INT16		sTempGridNo, sNextTempGridNo, sVeryTemporaryGridNo;
	INT16		sStartGridNo, sCurrGridNo, sPrevGridNo = NOWHERE, sRightGridNo;
	INT8		bDirection, bTempDirection;
	BOOLEAN	fFoundDir, fFoundWall;
	UINT32	uiChanceIn = ROOF_LOCATION_CHANCE; // chance of a location being considered
	INT16		sWallGridNo;
	INT8		bDesiredOrientation;
	INT8		bSkipSpots = 0;
	SOLDIERTYPE 	FakeSoldier;
	BUILDING *		pBuilding;
	UINT8					ubBuildingID = 0;

	pBuilding = CreateNewBuilding( &ubBuildingID );
	if (!pBuilding)
	{
		return( NULL );
	}

	// set up fake soldier for location testing
	memset( &FakeSoldier, 0, sizeof( SOLDIERTYPE ) );
	FakeSoldier.sGridNo = sDesiredSpot;
	FakeSoldier.bLevel = 1;
	FakeSoldier.bTeam = 1;

#ifdef ROOF_DEBUG
	memset( gsCoverValue, 0x7F, sizeof( INT16 ) * WORLD_MAX );
#endif

	// Set reachable 
	RoofReachableTest( sDesiredSpot, ubBuildingID );

	// From sGridNo, search until we find a spot that isn't part of the building
	bDirection = NORTHWEST;
	sTempGridNo = sDesiredSpot;
	// using diagonal directions to hopefully prevent picking a 
	// spot that 
	while( (gpWorldLevelData[ sTempGridNo ].uiFlags & MAPELEMENT_REACHABLE ) )
	{
		sNextTempGridNo = NewGridNo( sTempGridNo, DirectionInc( bDirection ) );
		if ( sTempGridNo == sNextTempGridNo )
		{
			// hit edge of map!??!
			return( NULL );
		}
		else
		{
			sTempGridNo = sNextTempGridNo;
		}
	} 

	// we've got our spot
	sStartGridNo = sTempGridNo;

	sCurrGridNo = sStartGridNo;
	sVeryTemporaryGridNo = NewGridNo( sCurrGridNo, DirectionInc( EAST ) );
	if ( gpWorldLevelData[ sVeryTemporaryGridNo ].uiFlags & MAPELEMENT_REACHABLE )
	{
		// go north first
		bDirection = NORTH;
	}
	else
	{
		// go that way (east)
		bDirection = EAST;
	}

	gpWorldLevelData[ sStartGridNo ].ubExtFlags[0] |= MAPELEMENT_EXT_ROOFCODE_VISITED;

	while( 1 )
	{

		// if point to (2 clockwise) is not part of building and is not visited,
		// or is starting point, turn!
		sRightGridNo = NewGridNo( sCurrGridNo, DirectionInc( gTwoCDirection[ bDirection ] ) );
		sTempGridNo = sRightGridNo;
		if ( ( ( !(gpWorldLevelData[ sTempGridNo ].uiFlags & MAPELEMENT_REACHABLE) && !(gpWorldLevelData[ sTempGridNo ].ubExtFlags[0] & MAPELEMENT_EXT_ROOFCODE_VISITED) ) || (sTempGridNo == sStartGridNo) ) && (sCurrGridNo != sStartGridNo) )
		{
			bDirection = gTwoCDirection[ bDirection ];
			// try in that direction
			continue;
		}

		// if spot ahead is part of building, turn
		sTempGridNo = NewGridNo( sCurrGridNo, DirectionInc( bDirection ) );
		if ( gpWorldLevelData[ sTempGridNo ].uiFlags & MAPELEMENT_REACHABLE )
		{
			// first search for a spot that is neither part of the building or visited

			// we KNOW that the spot in the original direction is blocked, so only loop 3 times
			bTempDirection = gTwoCDirection[ bDirection ];
			fFoundDir = FALSE;
			for ( uiLoop = 0; uiLoop < 3; uiLoop++ )
			{
				sTempGridNo = NewGridNo( sCurrGridNo, DirectionInc( bTempDirection ) );
				if ( !(gpWorldLevelData[ sTempGridNo ].uiFlags & MAPELEMENT_REACHABLE) && !(gpWorldLevelData[ sTempGridNo ].ubExtFlags[0] & MAPELEMENT_EXT_ROOFCODE_VISITED) )
				{
					// this is the way to go!
					fFoundDir = TRUE;
					break;
				}
				bTempDirection = gTwoCDirection[ bTempDirection ];
			}
			if (!fFoundDir)
			{
				// now search for a spot that is just not part of the building
				bTempDirection = gTwoCDirection[ bDirection ];
				fFoundDir = FALSE;
				for ( uiLoop = 0; uiLoop < 3; uiLoop++ )
				{
					sTempGridNo = NewGridNo( sCurrGridNo, DirectionInc( bTempDirection ) );
					if ( !(gpWorldLevelData[ sTempGridNo ].uiFlags & MAPELEMENT_REACHABLE) )
					{
						// this is the way to go!
						fFoundDir = TRUE;
						break;
					}
					bTempDirection = gTwoCDirection[ bTempDirection ];
				}
				if (!fFoundDir)
				{
					// WTF is going on?
					return( NULL );
				}
			}
			bDirection = bTempDirection;
			// try in that direction
			continue;
		}

		// move ahead
		sPrevGridNo = sCurrGridNo;
		sCurrGridNo = sTempGridNo;
		sRightGridNo = NewGridNo( sCurrGridNo, DirectionInc( gTwoCDirection[ bDirection ] ) );

#ifdef ROOF_DEBUG
		if (gsCoverValue[sCurrGridNo] == 0x7F7F)
		{
			gsCoverValue[sCurrGridNo] = 1;
		}
		else if (gsCoverValue[sCurrGridNo] >= 0)
		{
			gsCoverValue[sCurrGridNo]++;
		}

		DebugAI( String( "Roof code visits %d", sCurrGridNo ) );
#endif

		if (sCurrGridNo == sStartGridNo)
		{
			// done
			break;
		}

		if ( !(gpWorldLevelData[ sCurrGridNo ].ubExtFlags[0] & MAPELEMENT_EXT_ROOFCODE_VISITED) )
		{
			gpWorldLevelData[ sCurrGridNo ].ubExtFlags[0] |= MAPELEMENT_EXT_ROOFCODE_VISITED;

			// consider this location as possible climb gridno		
			// there must be a regular wall adjacent to this for us to consider it a 
			// climb gridno

			// if the direction is east or north, the wall would be in our gridno;
			// if south or west, the wall would be in the gridno two clockwise
			fFoundWall = FALSE;

			switch( bDirection )
			{
				case NORTH:
					sWallGridNo = sCurrGridNo;
					bDesiredOrientation = OUTSIDE_TOP_RIGHT;
					break;
				case EAST:
					sWallGridNo = sCurrGridNo;
					bDesiredOrientation = OUTSIDE_TOP_LEFT;
					break;
				case SOUTH:
					sWallGridNo = (INT16) ( sCurrGridNo + DirectionInc( gTwoCDirection[ bDirection ] ) );
					bDesiredOrientation = OUTSIDE_TOP_RIGHT;
					break;
				case WEST:
					sWallGridNo = (INT16) ( sCurrGridNo + DirectionInc( gTwoCDirection[ bDirection ] ) );
					bDesiredOrientation = OUTSIDE_TOP_LEFT;
					break;
				default:
					// what the heck?
					return( NULL );
			}

			if (bDesiredOrientation == OUTSIDE_TOP_LEFT)
			{
				if (WallExistsOfTopLeftOrientation( sWallGridNo ))
				{
					fFoundWall = TRUE;
				}
			}
			else 
			{
				if (WallExistsOfTopRightOrientation( sWallGridNo ))
				{
					fFoundWall = TRUE;
				}
			}

			if (fFoundWall)
			{
				if (bSkipSpots > 0)
				{
					bSkipSpots--;
				}
				else if ( Random( uiChanceIn ) == 0 )
				{		
					// don't consider people as obstacles
					if ( NewOKDestination( &FakeSoldier, sCurrGridNo, FALSE, 0 ) )
					{
						pBuilding->sUpClimbSpots[ pBuilding->ubNumClimbSpots ] = sCurrGridNo;
						pBuilding->sDownClimbSpots[ pBuilding->ubNumClimbSpots ] = sRightGridNo;
						pBuilding->ubNumClimbSpots++;

						if ( pBuilding->ubNumClimbSpots == MAX_CLIMBSPOTS_PER_BUILDING)
						{
							// gotta stop!
							return( pBuilding );
						}

						// if location is added as a spot, reset uiChanceIn
						uiChanceIn = ROOF_LOCATION_CHANCE;
#ifdef ROOF_DEBUG
						gsCoverValue[sCurrGridNo] = 99;
#endif
						// skip the next spot
						bSkipSpots = 1;
					}
					else
					{
						// if location is not added, 100% chance of handling next location
						// and the next until we can add one
						uiChanceIn = 1;					
	
					}
				}
				else
				{
					// didn't pick this location, so increase chance that next location 
					// will be considered
					if (uiChanceIn > 2)
					{
						uiChanceIn--;
					}
				}

			}
			else
			{
				// can't select this spot
				if ( (sPrevGridNo != NOWHERE) && (pBuilding->ubNumClimbSpots > 0) )
				{
					if ( pBuilding->sDownClimbSpots[ pBuilding->ubNumClimbSpots - 1 ] == sCurrGridNo )
					{
						// unselect previous spot
						pBuilding->ubNumClimbSpots--;
						// overwrote a selected spot so go into automatic selection for later
						uiChanceIn = 1;
#ifdef ROOF_DEBUG
						// reset marker
						gsCoverValue[sPrevGridNo] = 1;
#endif
					}
				}

				// skip the next gridno
				bSkipSpots = 1;
			}

		}

	}

	// at end could prune # of locations if there are too many

/*
#ifdef ROOF_DEBUG
	SetRenderFlags( RENDER_FLAG_FULL );
	RenderWorld();
	RenderCoverDebug( );
	InvalidateScreen( );
	EndFrameBufferRender();
	RefreshScreen( NULL );
#endif
*/

	return( pBuilding );
}
示例#12
0
BOOLEAN AddUIPlan( UINT16 sGridNo, UINT8 ubPlanID )
{
	SOLDIERTYPE				*pPlanSoldier;
	INT16							sXPos, sYPos;
	INT16							sAPCost = 0;
	INT8							bDirection;
	INT32							iLoop;
	SOLDIERCREATE_STRUCT		MercCreateStruct;
	UINT8							ubNewIndex;

	// Depeding on stance and direction facing, add guy!
	
	// If we have a planned action here, ignore!


	// If not OK Dest, ignore!
	if ( !NewOKDestination( gpUIPlannedSoldier, sGridNo, FALSE, (INT8)gsInterfaceLevel ) )
	{
		return( FALSE );
	}


	if ( ubPlanID == UIPLAN_ACTION_MOVETO )
	{
		// Calculate cost to move here
		sAPCost = PlotPath( gpUIPlannedSoldier, sGridNo, COPYROUTE, NO_PLOT, TEMPORARY, (UINT16) gpUIPlannedSoldier->usUIMovementMode, NOT_STEALTH, FORWARD,  gpUIPlannedSoldier->bActionPoints );
		// Adjust for running if we are not already running
		if (  gpUIPlannedSoldier->usUIMovementMode == RUNNING )
		{
			sAPCost += AP_START_RUN_COST;
		}

		if ( EnoughPoints( gpUIPlannedSoldier, sAPCost, 0, FALSE ) )
		{
			memset( &MercCreateStruct, 0, sizeof( MercCreateStruct ) );
			MercCreateStruct.bTeam				= SOLDIER_CREATE_AUTO_TEAM;
			MercCreateStruct.ubProfile		= NO_PROFILE;
			MercCreateStruct.fPlayerPlan	= TRUE;
			MercCreateStruct.bBodyType		= gpUIPlannedSoldier->ubBodyType;
			MercCreateStruct.sInsertionGridNo		= sGridNo;

			// Get Grid Corrdinates of mouse
			if ( TacticalCreateSoldier( &MercCreateStruct, &ubNewIndex ) )
			{			
				// Get pointer to soldier
				GetSoldier( &pPlanSoldier, (UINT16)ubNewIndex );

				pPlanSoldier->sPlannedTargetX = -1;
				pPlanSoldier->sPlannedTargetY = -1;

				// Compare OPPLISTS!
				// Set ones we don't know about but do now back to old ( ie no new guys )
				for (iLoop = 0; iLoop < MAX_NUM_SOLDIERS; iLoop++ )
				{
					if ( gpUIPlannedSoldier->bOppList[ iLoop ] < 0 )
					{
							pPlanSoldier->bOppList[ iLoop ] = gpUIPlannedSoldier->bOppList[ iLoop ];
					}
				}

				// Get XY from Gridno
				ConvertGridNoToCenterCellXY( sGridNo, &sXPos, &sYPos );

				EVENT_SetSoldierPosition( pPlanSoldier, sXPos, sYPos );
				EVENT_SetSoldierDestination( pPlanSoldier, sGridNo );
				pPlanSoldier->bVisible = 1;
				pPlanSoldier->usUIMovementMode = gpUIPlannedSoldier->usUIMovementMode;


				pPlanSoldier->bActionPoints = gpUIPlannedSoldier->bActionPoints - sAPCost;

				pPlanSoldier->ubPlannedUIAPCost = (UINT8)pPlanSoldier->bActionPoints;

				// Get direction
				bDirection = (INT8)gpUIPlannedSoldier->usPathingData[ gpUIPlannedSoldier->usPathDataSize - 1 ];

				// Set direction
				pPlanSoldier->bDirection = bDirection;
				pPlanSoldier->bDesiredDirection = bDirection;

				// Set walking animation
				ChangeSoldierState( pPlanSoldier, pPlanSoldier->usUIMovementMode, 0, FALSE );	
				
				// Change selected soldier
				gusSelectedSoldier = (UINT16)pPlanSoldier->ubID;

				// Change global planned mode to this guy!
				gpUIPlannedSoldier = pPlanSoldier;

				gubNumUIPlannedMoves++;

				gfPlotNewMovement    = TRUE;

				ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Adding Merc Move to Plan" );

			}
		}
		else
		{
			ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Merc will not have enough action points" );
		}
	}
	else if ( ubPlanID == UIPLAN_ACTION_FIRE )
	{
 	  sAPCost = CalcTotalAPsToAttack( gpUIPlannedSoldier, sGridNo, TRUE, (INT8)(gpUIPlannedSoldier->bShownAimTime /2) );

		// Get XY from Gridno
		ConvertGridNoToCenterCellXY( sGridNo, &sXPos, &sYPos );


		// If this is a player guy, show message about no APS
		if ( EnoughPoints( gpUIPlannedSoldier, sAPCost, 0, FALSE ) )
		{
			// CHECK IF WE ARE A PLANNED SOLDIER OR NOT< IF SO< CREATE!
			if ( gpUIPlannedSoldier->ubID < MAX_NUM_SOLDIERS )
			{
				memset( &MercCreateStruct, 0, sizeof( MercCreateStruct ) );
				MercCreateStruct.bTeam				= SOLDIER_CREATE_AUTO_TEAM;
				MercCreateStruct.ubProfile		= NO_PROFILE;
				MercCreateStruct.fPlayerPlan	= TRUE;
				MercCreateStruct.bBodyType		= gpUIPlannedSoldier->ubBodyType;
				MercCreateStruct.sInsertionGridNo		= sGridNo;

				// Get Grid Corrdinates of mouse
				if ( TacticalCreateSoldier( &MercCreateStruct, &ubNewIndex ) )
				{			
					// Get pointer to soldier
					GetSoldier( &pPlanSoldier, (UINT16)ubNewIndex );

					pPlanSoldier->sPlannedTargetX = -1;
					pPlanSoldier->sPlannedTargetY = -1;

					// Compare OPPLISTS!
					// Set ones we don't know about but do now back to old ( ie no new guys )
					for (iLoop = 0; iLoop < MAX_NUM_SOLDIERS; iLoop++ )
					{
						if ( gpUIPlannedSoldier->bOppList[ iLoop ] < 0 )
						{
								pPlanSoldier->bOppList[ iLoop ] = gpUIPlannedSoldier->bOppList[ iLoop ];
						}
					}

					EVENT_SetSoldierPosition( pPlanSoldier, gpUIPlannedSoldier->dXPos, gpUIPlannedSoldier->dYPos );
					EVENT_SetSoldierDestination( pPlanSoldier, gpUIPlannedSoldier->sGridNo );
					pPlanSoldier->bVisible = 1;
					pPlanSoldier->usUIMovementMode = gpUIPlannedSoldier->usUIMovementMode;


					pPlanSoldier->bActionPoints = gpUIPlannedSoldier->bActionPoints - sAPCost;

					pPlanSoldier->ubPlannedUIAPCost = (UINT8)pPlanSoldier->bActionPoints;

					// Get direction
					bDirection = (INT8)gpUIPlannedSoldier->usPathingData[ gpUIPlannedSoldier->usPathDataSize - 1 ];

					// Set direction
					pPlanSoldier->bDirection = bDirection;
					pPlanSoldier->bDesiredDirection = bDirection;

					// Set walking animation
					ChangeSoldierState( pPlanSoldier, pPlanSoldier->usUIMovementMode, 0, FALSE );	
					
					// Change selected soldier
					gusSelectedSoldier = (UINT16)pPlanSoldier->ubID;

					// Change global planned mode to this guy!
					gpUIPlannedSoldier = pPlanSoldier;

					gubNumUIPlannedMoves++;
				}


			}

			gpUIPlannedSoldier->bActionPoints = gpUIPlannedSoldier->bActionPoints - sAPCost;

			gpUIPlannedSoldier->ubPlannedUIAPCost = (UINT8)gpUIPlannedSoldier->bActionPoints;

			// Get direction from gridno
			bDirection = (INT8)GetDirectionFromGridNo( sGridNo, gpUIPlannedSoldier );

			// Set direction
			gpUIPlannedSoldier->bDirection = bDirection;
			gpUIPlannedSoldier->bDesiredDirection = bDirection;

			// Set to shooting animation
			SelectPausedFireAnimation( gpUIPlannedSoldier );

			gpUIPlannedSoldier->sPlannedTargetX = sXPos;
			gpUIPlannedSoldier->sPlannedTargetY = sYPos;

			ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Adding Merc Shoot to Plan" );

		}
		else
		{
			ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Merc will not have enough action points" );
		}
	}
	return( TRUE );
}
示例#13
0
void CalculateCover()
{
	register INT32 ubX, ubY;
	register INT8 ubZ;
	SOLDIERTYPE* pSoldier;

	RemoveCoverObjectsFromViewArea();

	if( gubDrawMode == COVER_DRAW_OFF )
	{
		return;
	}

	if( gusSelectedSoldier == NOBODY )
	{
		return;
	}

	// at we're here, we want to display cover, so remove the mines display
	if ( gubDrawModeMine != MINES_DRAW_OFF )
		RemoveMinesObjectsFromViewArea();

	GetSoldier( &pSoldier, gusSelectedSoldier );
	
	INT16 usTmp;
	GetScreenXYWorldCell( gsVIEWPORT_START_X, gsVIEWPORT_START_Y, &gsMinCellX, &usTmp );
	GetScreenXYWorldCell( gsVIEWPORT_END_X, gsVIEWPORT_END_Y, &gsMaxCellX, &usTmp );

	GetScreenXYWorldCell( gsVIEWPORT_END_X, gsVIEWPORT_START_Y, &usTmp, &gsMinCellY );
	GetScreenXYWorldCell( gsVIEWPORT_START_X, gsVIEWPORT_END_Y, &usTmp, &gsMaxCellY );
	for ( ubX=gsMinCellX; ubX<=gsMaxCellX; ++ubX )
	{
		for ( ubY=gsMinCellY; ubY<=gsMaxCellY; ++ubY )
		{
			for ( ubZ=0; ubZ<COVER_Z_CELLS; ++ubZ )
			{
				INT32& sGridNo = gCoverViewArea[ ubX ][ ubY ][ ubZ ].sGridNo;
				
				GetGridNoForViewPort( ubX, ubY, sGridNo );

				if( !GridNoOnScreenAndAround( sGridNo, 2 ) )
				{
					continue;
				}
								
				// do not show stuff on ground if roof is shown
				if ( IsTheRoofVisible( sGridNo ) )
				{
					if ( ubZ == I_GROUND_LEVEL )
						continue;
				}
				// do not show stuff on roofs if ground is shown
				else if ( ubZ == I_ROOF_LEVEL )
					continue;

				if ( !NewOKDestination( pSoldier, sGridNo, false, ubZ ) )
				{
					continue;
				}

				INT8& bCover = gCoverViewArea[ ubX ][ ubY ][ ubZ ].bCover;
				BOOLEAN& fInverseColor = gCoverViewArea[ ubX ][ ubY ][ ubZ ].fInverseColor;

				if ( gubDrawMode == COVER_DRAW_ENEMY_VIEW ) // view of enemies against your selected merc
				{
					// reset cover value
					bCover = MAX_COVER;
					CalculateCoverForSoldier( pSoldier, sGridNo, ubZ, bCover );
					fInverseColor = FALSE;
				}
				else if ( gubDrawMode == COVER_DRAW_MERC_VIEW )
				{
					// reset cover value
					bCover = MAX_COVER;
					if ( gTacticalStatus.fAtLeastOneGuyOnMultiSelect ) // view of selected mercs
					{
						// OK, loop through all guys who are 'multi-selected' and
						INT32	cnt;
						cnt = gTacticalStatus.Team[ gbPlayerNum ].bFirstID;
						for ( pSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; cnt++, pSoldier++ )
						{
							if ( pSoldier->bActive && pSoldier->bInSector )
							{
								if ( pSoldier->flags.uiStatusFlags & SOLDIER_MULTI_SELECTED )
								{
									CalculateCoverFromSoldier( pSoldier, sGridNo, ubZ, bCover );
								}
							}
						}
					}
					else // single view from your merc
						CalculateCoverFromSoldier( pSoldier, sGridNo, ubZ, bCover );
					
					fInverseColor = TRUE; // we don't want to show the cover for the enemy
				}
			}
		}
	}

	AddCoverObjectsToViewArea();
}
示例#14
0
void CalculateTraitRange()
{
	INT32 ubX, ubY, ubZ;
	SOLDIERTYPE* pSoldier;

	RemoveTraitObjectsFromViewArea();

	if ( gubDrawModeTrait == TRAIT_DRAW_OFF )
		return;
	
	if( gusSelectedSoldier == NOBODY || !GetSoldier( &pSoldier, gusSelectedSoldier ) )
		return;

	UINT16 range1 = 0;
	UINT16 range2 = 0;
	switch ( usDisplayTrait )
	{
	case RADIO_OPERATOR_NT:
		{
			// we 'mark' the map position with which we called the menu, so that the player sees where he is targetting

		}
		break;

	case VARIOUSSKILLS:
		{
			range1 = gGameExternalOptions.usSpotterRange;
			range2 = gGameExternalOptions.usSpotterRange * 2;
		}
		break;

	default:
		return;
	}

	//remove other displays
	if( gubDrawModeMine != MINES_DRAW_OFF )
		RemoveMinesObjectsFromViewArea();
		
	if ( gubDrawMode != COVER_DRAW_OFF )
		RemoveCoverObjectsFromViewArea();
			
	const INT32& sSelectedSoldierGridNo = MercPtrs[ gusSelectedSoldier ]->sGridNo;
	
	INT16 usTmp;
	GetScreenXYWorldCell( gsVIEWPORT_START_X, gsVIEWPORT_START_Y, &gsMineMinCellX, &usTmp );
	GetScreenXYWorldCell( gsVIEWPORT_END_X, gsVIEWPORT_END_Y, &gsMineMaxCellX, &usTmp );

	GetScreenXYWorldCell( gsVIEWPORT_END_X, gsVIEWPORT_START_Y, &usTmp, &gsMineMinCellY );
	GetScreenXYWorldCell( gsVIEWPORT_START_X, gsVIEWPORT_END_Y, &usTmp, &gsMineMaxCellY );
	for ( ubX=gsMineMinCellX; ubX<=gsMineMaxCellX; ++ubX )
	{
		for ( ubY=gsMineMinCellY; ubY<=gsMineMaxCellY; ++ubY )
		{
			for ( ubZ=0; ubZ<COVER_Z_CELLS; ++ubZ )
			{
				INT32& sGridNo = gCoverViewArea[ ubX ][ ubY ][ ubZ ].sGridNo;

				GetGridNoForViewPort( ubX, ubY, sGridNo );

				if( !GridNoOnScreenAndAround( sGridNo, 2 ) )
				{
					continue;
				}

				if ( !NewOKDestination( pSoldier, sGridNo, false, (INT8) ubZ ) )
				{
					continue;
				}

				// do not show stuff on roofs if ground is shown
				if ( ubZ == I_ROOF_LEVEL && !IsTheRoofVisible( sGridNo ) )
				{
					continue;
				}

				// do not show stuff on ground if roof is shown
				if ( ubZ == I_GROUND_LEVEL && IsTheRoofVisible( sGridNo ) )
				{
					continue;
				}
				
				if ( range1 && PythSpacesAway(sSelectedSoldierGridNo, sGridNo) == range1 )
					gCoverViewArea[ ubX ][ ubY ][ ubZ ].bTrait = TRAIT_1;
				else if ( range2 && PythSpacesAway(sSelectedSoldierGridNo, sGridNo) == range2 )
					gCoverViewArea[ ubX ][ ubY ][ ubZ ].bTrait = TRAIT_2;
				// mark the gridno we are targetting
				else if ( PythSpacesAway(sTraitgridNo, sGridNo) == 1 )
					gCoverViewArea[ ubX ][ ubY ][ ubZ ].bTrait = TRAIT_1;
				else
					gCoverViewArea[ ubX ][ ubY ][ ubZ ].bTrait = MAX_TRAIT;
			}
		}
	}

	AddTraitObjectsToViewArea();
}
示例#15
0
void CalculateMines()
{
	INT32 ubX, ubY, ubZ;
	SOLDIERTYPE* pSoldier;
			
	RemoveMinesObjectsFromViewArea();

	if( gubDrawModeMine == MINES_DRAW_OFF )
	{
		return;
	}

	if( gusSelectedSoldier == NOBODY )
	{
		return;
	}

	// at we're here, we want to display mines, so remove the cover display
	if ( gubDrawMode != COVER_DRAW_OFF )
		RemoveCoverObjectsFromViewArea();

	GetSoldier( &pSoldier, gusSelectedSoldier );

	// if we want to detect hostile mines and we have an metal detector in our hands, allow seeking
	BOOLEAN fWithMineDetector = FALSE;
	if ( pSoldier && gubDrawModeMine == MINES_DRAW_DETECT_ENEMY )
	{
		if ( FindMetalDetectorInHand(pSoldier) != NO_SLOT )
			fWithMineDetector = TRUE;

		// TODO: perhaps even consume batteries one day...
	}

	// if we are looking for mines via mine detector, but don't have one equipped, return, we won't detect anything
	if ( gubDrawModeMine == MINES_DRAW_DETECT_ENEMY && !fWithMineDetector )
	{
		return;
	}
	
	const INT32& sSelectedSoldierGridNo = MercPtrs[ gusSelectedSoldier ]->sGridNo;
	
	INT16 usTmp;
	GetScreenXYWorldCell( gsVIEWPORT_START_X, gsVIEWPORT_START_Y, &gsMineMinCellX, &usTmp );
	GetScreenXYWorldCell( gsVIEWPORT_END_X, gsVIEWPORT_END_Y, &gsMineMaxCellX, &usTmp );

	GetScreenXYWorldCell( gsVIEWPORT_END_X, gsVIEWPORT_START_Y, &usTmp, &gsMineMinCellY );
	GetScreenXYWorldCell( gsVIEWPORT_START_X, gsVIEWPORT_END_Y, &usTmp, &gsMineMaxCellY );
	for ( ubX=gsMineMinCellX; ubX<=gsMineMaxCellX; ++ubX )
	{
		for ( ubY=gsMineMinCellY; ubY<=gsMineMaxCellY; ++ubY )
		{
			for ( ubZ=0; ubZ<COVER_Z_CELLS; ++ubZ )
			{
				INT32& sGridNo = gCoverViewArea[ ubX ][ ubY ][ ubZ ].sGridNo;
				
				GetGridNoForViewPort( ubX, ubY, sGridNo );

				if( !GridNoOnScreenAndAround( sGridNo, 2 ) )
				{
					continue;
				}

				if ( IsTheRoofVisible( sGridNo ) )
				{
					if ( ubZ == I_GROUND_LEVEL )
						continue;
				}
				else if ( ubZ == I_ROOF_LEVEL )
				{
					continue;
				}
																
				// if we are looking for hostile mines, but the tile is out of our' detectors range, skip looking for mines
				if ( gubDrawModeMine == MINES_DRAW_DETECT_ENEMY && fWithMineDetector )
				{
					if ( PythSpacesAway(sSelectedSoldierGridNo, sGridNo) > 4 )
						continue;
				}

				if ( !NewOKDestination( pSoldier, sGridNo, false, (INT8) ubZ ) )
				{
					continue;
				}

				INT8& bMines = gCoverViewArea[ ubX ][ ubY ][ ubZ ].bMines;

				bMines = MAX_MINES;

				DetermineMineDisplayInTile( sGridNo, ubZ, bMines, fWithMineDetector );
			}
		}
	}

	AddMinesObjectsToViewArea();
}
示例#16
0
文件: Movement.c 项目: bowlofstew/ja2
INT8 RandomPointPatrolAI(SOLDIERTYPE *pSoldier)
{
	INT16 sPatrolPoint;
	INT8  bOldOrders, bPatrolIndex;
	INT8	bCnt;

	sPatrolPoint = pSoldier->usPatrolGrid[pSoldier->bNextPatrolPnt];

	// if we're already there, advance next patrol point
	if (pSoldier->sGridNo == sPatrolPoint || pSoldier->bNextPatrolPnt == 0)
	{
		// find next valid patrol point
		// we keep a count of the # of times we are in here to make sure we don't get into an endless
		//loop
		bCnt = 0;
		do
		{
			// usPatrolGrid[0] gets used for centre of close etc patrols, so we have to add 1 to the Random #
			bPatrolIndex = (INT8) PreRandom( pSoldier->bPatrolCnt ) + 1;
			sPatrolPoint = pSoldier->usPatrolGrid[ bPatrolIndex];
			bCnt++;
		}
		while ( (sPatrolPoint == pSoldier->sGridNo) || ( (sPatrolPoint != NOWHERE) && (bCnt < pSoldier->bPatrolCnt) && (NewOKDestination(pSoldier,sPatrolPoint,IGNOREPEOPLE, pSoldier->bLevel ) < 1)) ); 

		if (bCnt == pSoldier->bPatrolCnt)
		{
			// ok, we tried doing this randomly, didn't work well, so now do a linear search
			pSoldier->bNextPatrolPnt = 0;
			do
			{
				sPatrolPoint = NextPatrolPoint(pSoldier);
			}
			while ((sPatrolPoint != NOWHERE) && (NewOKDestination(pSoldier,sPatrolPoint,IGNOREPEOPLE, pSoldier->bLevel) < 1));
		}
		
		// do nothing this time around
		if (pSoldier->sGridNo == sPatrolPoint)
		{
			return( FALSE );
		}
	}

	// if we don't have a legal patrol point
	if (sPatrolPoint == NOWHERE)
	{
#ifdef BETAVERSION
		NumMessage("PointPatrolAI: ERROR - no legal patrol point for %d",pSoldier->ubID);
#endif

		// over-ride orders to something safer
		pSoldier->bOrders = FARPATROL;
		return(FALSE);
	}

	// make sure we can get there from here at this time, if we can't get all
	// the way there, at least do our best to get close
	if (LegalNPCDestination(pSoldier,sPatrolPoint,ENSURE_PATH,WATEROK,0))
	{
		pSoldier->bPathStored = TRUE;	    // optimization - Ian
		pSoldier->usActionData = sPatrolPoint;
	}
	else
	{
		// temporarily extend roaming range to infinity by changing orders, else
		// this won't work if the next patrol point is > 10 tiles away!
		bOldOrders					= pSoldier->bOrders;
		pSoldier->bOrders	= SEEKENEMY;

		pSoldier->usActionData = GoAsFarAsPossibleTowards(pSoldier,sPatrolPoint,pSoldier->bAction);

		pSoldier->bOrders = bOldOrders;

		// if it's not possible to get any closer, that's OK, but fail this call
		if (pSoldier->usActionData == NOWHERE)
			return(FALSE);
	}


	// passed all tests - start moving towards next patrol point
#ifdef DEBUGDECISIONS
	sprintf(tempstr,"%s - POINT PATROL to grid %d",pSoldier->name,pSoldier->usActionData);
	AIPopMessage(tempstr);
#endif

	return(TRUE);
}
示例#17
0
文件: Movement.c 项目: bowlofstew/ja2
void SoldierTriesToContinueAlongPath(SOLDIERTYPE *pSoldier)
{
	INT16 usNewGridNo,bAPCost;


	// turn off the flag now that we're going to do something about it...
	// ATE: USed to be redundent, now if called befroe NewDest can cause some side efects...
	// AdjustNoAPToFinishMove( pSoldier, FALSE );

	if (pSoldier->bNewSituation == IS_NEW_SITUATION)
	{
		CancelAIAction(pSoldier,DONTFORCE);
		return;
	}

	if (pSoldier->usActionData >= NOWHERE)
	{
		CancelAIAction(pSoldier,DONTFORCE);	
		return;
	}

	if (!NewOKDestination( pSoldier,pSoldier->usActionData, TRUE, pSoldier->bLevel ))
	{
		CancelAIAction(pSoldier,DONTFORCE);
		return;
	}

	if (IsActionAffordable(pSoldier))
	{
		if (pSoldier->bActionInProgress == FALSE)
		{
			// start a move that didn't even get started before...
			// hope this works...
			NPCDoesAct(pSoldier);

			// perform the chosen action
			pSoldier->bActionInProgress = ExecuteAction(pSoldier); // if started, mark us as busy
		}
		else
		{
			// otherwise we shouldn't have to do anything(?)
		}
	}
	else
	{
		CancelAIAction(pSoldier,DONTFORCE);
#ifdef TESTAI
		DebugMsg( TOPIC_JA2AI, DBG_LEVEL_3, 
						String("Soldier (%d) HAS NOT ENOUGH AP to continue along path",pSoldier->ubID) );
#endif
	}

	usNewGridNo = NewGridNo( (UINT16)pSoldier->sGridNo, DirectionInc( (UINT8)pSoldier->usPathingData[ pSoldier->usPathIndex ] ) );

	// Find out how much it takes to move here!
	bAPCost = EstimateActionPointCost( pSoldier, usNewGridNo, (INT8)pSoldier->usPathingData[ pSoldier->usPathIndex ], pSoldier->usUIMovementMode, (INT8) pSoldier->usPathIndex, (INT8) pSoldier->usPathDataSize );

	if (pSoldier->bActionPoints >= bAPCost)
	{
		// seems to have enough points...
		NewDest(pSoldier,usNewGridNo);
		// maybe we didn't actually start the action last turn...
		pSoldier->bActionInProgress = TRUE;
#ifdef TESTAI
		DebugMsg( TOPIC_JA2AI, DBG_LEVEL_3, 
						String("Soldier (%d) continues along path",pSoldier->ubID) );
#endif
	}
	else
	 {
		CancelAIAction(pSoldier,DONTFORCE);
#ifdef TESTAI
		DebugMsg( TOPIC_JA2AI, DBG_LEVEL_3, 
						String("Soldier (%d) HAS NOT ENOUGH AP to continue along path",pSoldier->ubID) );
#endif
	 }
}											
示例#18
0
INT8 TileIsClear( SOLDIERTYPE *pSoldier, INT8 bDirection,  INT16 sGridNo, INT8 bLevel )
{
	UINT8		ubPerson;
	INT16		sTempDestGridNo;
	INT16		sNewGridNo;
	BOOLEAN	fSwapInDoor = FALSE;

	if ( sGridNo == NOWHERE )
	{
		return( MOVE_TILE_CLEAR );
	}

	ubPerson = WhoIsThere2( sGridNo, bLevel );


	if ( ubPerson != NO_SOLDIER )
	{
		// If this us?
		if ( ubPerson != pSoldier->ubID )
		{
			// OK, set flag indicating we are blocked by a merc....
			if ( pSoldier->bTeam != gbPlayerNum ) // CJC: shouldn't this be in all cases???
		//if ( 0 )
			{
				pSoldier->fBlockedByAnotherMerc = TRUE;
				// Set direction we were trying to goto
				pSoldier->bBlockedByAnotherMercDirection = bDirection;

				// Are we only temporarily blocked?
				// Check if our final destination is = our gridno
				if ( ( MercPtrs[ ubPerson ]->sFinalDestination == MercPtrs[ ubPerson ]->sGridNo )  )
				{
					return( MOVE_TILE_STATIONARY_BLOCKED );
				}
				else
				{
					// OK, if buddy who is blocking us is trying to move too...
					// And we are in opposite directions...
					if ( MercPtrs[ ubPerson ]->fBlockedByAnotherMerc && MercPtrs[ ubPerson ]->bBlockedByAnotherMercDirection == gOppositeDirection[ bDirection ] )
					{
						// OK, try and get a path around buddy....
						// We have to temporarily make buddy stopped...
						sTempDestGridNo = MercPtrs[ ubPerson ]->sFinalDestination;
						MercPtrs[ ubPerson ]->sFinalDestination = MercPtrs[ ubPerson ]->sGridNo;

						if ( PlotPath( pSoldier, pSoldier->sFinalDestination, NO_COPYROUTE, NO_PLOT, TEMPORARY, pSoldier->usUIMovementMode, NOT_STEALTH, FORWARD, pSoldier->bActionPoints ) )
						{
							pSoldier->bPathStored = FALSE;
							// OK, make guy go here...
							EVENT_GetNewSoldierPath( pSoldier, pSoldier->sFinalDestination, pSoldier->usUIMovementMode );
							// Restore final dest....
							MercPtrs[ ubPerson ]->sFinalDestination = sTempDestGridNo;
							pSoldier->fBlockedByAnotherMerc = FALSE;

							// Is the next tile blocked too?
							sNewGridNo = NewGridNo( (UINT16)pSoldier->sGridNo, DirectionInc( (UINT8)guiPathingData[ 0 ] ) );

							return( TileIsClear( pSoldier, (UINT8)guiPathingData[ 0 ], sNewGridNo, pSoldier->bLevel ) );
						} 
						else
						{

								// Not for multi-tiled things...
								if ( !( pSoldier->uiStatusFlags & SOLDIER_MULTITILE ) )
								{
									// Is the next movement cost for a door?
									if ( DoorTravelCost( pSoldier, sGridNo, gubWorldMovementCosts[ sGridNo ][ bDirection ][ pSoldier->bLevel ], (BOOLEAN)( pSoldier->bTeam == gbPlayerNum ), NULL ) == TRAVELCOST_DOOR )
									{
										fSwapInDoor = TRUE;
									}

									// If we are to swap and we're near a door, open door first and then close it...?


									// Swap now!
									MercPtrs[ ubPerson ]->fBlockedByAnotherMerc = FALSE;

									// Restore final dest....
									MercPtrs[ ubPerson ]->sFinalDestination = sTempDestGridNo;
				
									// Swap merc positions.....
									SwapMercPositions( pSoldier, MercPtrs[ ubPerson ] );
									
									// With these two guys swapped, they should try and continue on their way....
									// Start them both again along their way...
									EVENT_GetNewSoldierPath( pSoldier, pSoldier->sFinalDestination, pSoldier->usUIMovementMode );
									EVENT_GetNewSoldierPath( MercPtrs[ ubPerson ], MercPtrs[ ubPerson ]->sFinalDestination, MercPtrs[ ubPerson ]->usUIMovementMode );					
								}
						}
					}
					return( MOVE_TILE_TEMP_BLOCKED );
				}
			}
			else
			{
				//return( MOVE_TILE_STATIONARY_BLOCKED );
				// ATE: OK, put some smartshere...
				// If we are waiting for more than a few times, change to stationary...
				if ( MercPtrs[ ubPerson ]->fDelayedMovement >= 105 )
				{
					// Set to special 'I want to walk through people' value
					pSoldier->fDelayedMovement = 150;

					return( MOVE_TILE_STATIONARY_BLOCKED );
				}
				if ( MercPtrs[ ubPerson ]->sGridNo == MercPtrs[ ubPerson ]->sFinalDestination )
				{
					return( MOVE_TILE_STATIONARY_BLOCKED );
				}
				return( MOVE_TILE_TEMP_BLOCKED );
			}
		}
	}

	if ( ( gpWorldLevelData[ sGridNo ].uiFlags & MAPELEMENT_MOVEMENT_RESERVED ) )
	{
		if ( gpWorldLevelData[ sGridNo ].ubReservedSoldierID != pSoldier->ubID )
		{
			return( MOVE_TILE_TEMP_BLOCKED );
		}
	}

	// Are we clear of structs?
	if ( !NewOKDestination( pSoldier, sGridNo, FALSE, pSoldier->bLevel ) )
	{
			// ATE: Fence cost is an exclusiuon here....
			if ( gubWorldMovementCosts[ sGridNo ][ bDirection ][ pSoldier->bLevel ] != TRAVELCOST_FENCE )
			{
				// ATE: HIdden structs - we do something here... reveal it!
				if ( gubWorldMovementCosts[ sGridNo ][ bDirection ][ pSoldier->bLevel ] == TRAVELCOST_HIDDENOBSTACLE )
				{
					gpWorldLevelData[ sGridNo ].uiFlags|=MAPELEMENT_REVEALED;
					gpWorldLevelData[ sGridNo ].uiFlags|=MAPELEMENT_REDRAW;
					SetRenderFlags(RENDER_FLAG_MARKED);
					RecompileLocalMovementCosts( (UINT16)sGridNo );
				}

				// Unset flag for blocked by soldier...
				pSoldier->fBlockedByAnotherMerc = FALSE;
				return( MOVE_TILE_STATIONARY_BLOCKED );
			}
			else
			{
#if 0
				// Check if there is a reserved marker here at least....
				sNewGridNo = NewGridNo( sGridNo, DirectionInc( bDirection ) );

				if ( ( gpWorldLevelData[ sNewGridNo ].uiFlags & MAPELEMENT_MOVEMENT_RESERVED ) )
				{
					if ( gpWorldLevelData[ sNewGridNo ].ubReservedSoldierID != pSoldier->ubID )
					{
						return( MOVE_TILE_TEMP_BLOCKED );
					}
				}
#endif
			}
	}

	// Unset flag for blocked by soldier...
	pSoldier->fBlockedByAnotherMerc = FALSE;

	return( MOVE_TILE_CLEAR );

}