Fix (by Asdow): Enemy cover display performance improved.

git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@8685 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
silversurfer
2019-08-11 07:49:47 +00:00
parent 01b540184d
commit 037e877013
6 changed files with 257 additions and 146 deletions
+204 -93
View File
@@ -88,18 +88,23 @@ void AddCoverObjectsToViewArea();
void RemoveCoverObjectsFromViewArea();
void CalculateCover();
void CalculateCoverFromEnemies();
void CalculateMines();
void CalculateTraitRange();
void CalculateTrackerRange();
void CalculateFortify();
void CalculateWeapondata();
void CalculateCoverFromEnemySoldier(SOLDIERTYPE* pFromSoldier, const INT32& sTargetGridNo, const BOOLEAN& fRoof, INT8& bOverlayType, SOLDIERTYPE* pToSoldier, const BOOLEAN& bFromSoldierCowering, const UINT8& tunnelVision, const INT8 ToSoldierStealth, const INT8 ToSoldierLBeSightAdjustment);
void GetGridNoForViewPort( const INT32& ubX, const INT32& ubY, INT32& sGridNo );
BOOLEAN GridNoOnScreenAndAround( const INT32& sGridNo, const UINT8& ubRadius=2 );
BOOLEAN IsTheRoofVisible( const INT32& sGridNo );
BOOLEAN HasAdjTile( const INT32& ubX, const INT32& ubY );
BOOLEAN HasAdjTile(const INT32& ubX, const INT32& ubY, const INT32& ubZ);
TileDefines GetOverlayIndex( INT8 bOverlayType )
{
@@ -491,10 +496,13 @@ void DisplayCover( BOOLEAN forceUpdate )
switch ( gubDrawMode )
{
case COVER_DRAW_MERC_VIEW:
case COVER_DRAW_ENEMY_VIEW:
CalculateCover();
break;
case COVER_DRAW_ENEMY_VIEW:
CalculateCoverFromEnemies();
break;
case MINES_DRAW_DETECT_ENEMY:
case MINES_DRAW_PLAYERTEAM_NETWORKS:
case MINES_DRAW_NETWORKCOLOURING:
@@ -526,99 +534,40 @@ void DisplayCover( BOOLEAN forceUpdate )
}
}
void CalculateCover()
static void CalculateCoverFromEnemies()
{
register INT32 ubX, ubY;
register INT8 ubZ;
SOLDIERTYPE* pSoldier;
if( gusSelectedSoldier == NOBODY )
if (gusSelectedSoldier == NOBODY)
return;
GetSoldier( &pSoldier, gusSelectedSoldier );
for ( ubX=gsMinCellX; ubX<=gsMaxCellX; ++ubX )
SOLDIERTYPE* pSoldier;
GetSoldier(&pSoldier, gusSelectedSoldier);
INT8 OurSoldierStealth = GetStealth(pSoldier);
INT8 OurSoldierLBESightAdjustment = GetSightAdjustmentBasedOnLBE(pSoldier);
// Loop through the grid and reset cover
for (INT32 ubX = gsMinCellX; ubX <= gsMaxCellX; ++ubX)
{
for ( ubY=gsMinCellY; ubY<=gsMaxCellY; ++ubY )
for (INT32 ubY = gsMinCellY; ubY <= gsMaxCellY; ++ubY)
{
for ( ubZ=0; ubZ<COVER_Z_CELLS; ++ubZ )
for (INT8 ubZ = 0; ubZ < COVER_Z_CELLS; ++ubZ)
{
INT32& sGridNo = gCoverViewArea[ ubX ][ ubY ][ ubZ ].sGridNo;
if( !GridNoOnScreenAndAround( sGridNo, 2 ) )
continue;
if ( IsTheRoofVisible( sGridNo ) )
{
// do not show stuff on ground if roof is shown
if ( ubZ == I_GROUND_LEVEL )
continue;
}
else
{
// do not show stuff on roofs if ground is shown
if ( ubZ == I_ROOF_LEVEL )
continue;
}
if ( !NewOKDestination( pSoldier, sGridNo, false, ubZ ) )
continue;
INT8& bOverlayType = gCoverViewArea[ubX][ubY][ubZ].bOverlayType;
if ( gubDrawMode == COVER_DRAW_ENEMY_VIEW ) // view of enemies against your selected merc
{
// reset cover value
bOverlayType = MAX_COVER;
CalculateCoverForSoldier( pSoldier, sGridNo, ubZ, bOverlayType );
}
else if ( gubDrawMode == COVER_DRAW_MERC_VIEW )
{
// reset cover value
bOverlayType = MAX_COVER;
if ( gTacticalStatus.fAtLeastOneGuyOnMultiSelect ) // view of selected mercs
{
// OK, loop through all guys who are 'multi-selected' and
INT32 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, bOverlayType );
// if the tile is already NO_COVER, there's no need to continue
if ( NO_COVER == bOverlayType )
break;
}
}
}
}
else // single view from your merc
CalculateCoverFromSoldier( pSoldier, sGridNo, ubZ, bOverlayType );
// we use different enums for our merc's sight to avoid confusing inverse sight
bOverlayType = MAX_SEE - bOverlayType;
}
bOverlayType = MAX_COVER;
}
}
}
AddCoverObjectsToViewArea();
}
void CalculateCoverForSoldier( SOLDIERTYPE* pSoldier, const INT32& sTargetGridNo, const BOOLEAN& fRoof, INT8& bOverlayType )
{
UINT32 uiLoop;
SOLDIERTYPE *pOpponent;
INT8 *pbPersOL;
INT8 *pbPublOL;
//loop through all the enemies and determine the cover
for (uiLoop = 0; uiLoop<guiNumMercSlots; ++uiLoop)
//loop through all the actors in the sector and save enemies' info for cover calculation
std::vector<SOLDIERTYPE*> pOpponents;
std::vector<BOOLEAN> bCowering;
std::vector<UINT8> tunnelVision;
for (UINT32 i = 0; i < guiNumMercSlots; ++i)
{
pOpponent = MercSlots[ uiLoop ];
SOLDIERTYPE *pOpponent = MercSlots[i];
// if this merc is inactive, at base, on assignment, dead, unconscious
if (!pOpponent || pOpponent->stats.bLife < OKLIFE)
@@ -627,30 +576,166 @@ void CalculateCoverForSoldier( SOLDIERTYPE* pSoldier, const INT32& sTargetGridNo
}
// if this man is neutral / on the same side, he's not an opponent
if( CONSIDERED_NEUTRAL( pSoldier, pOpponent ) || (pSoldier->bSide == pOpponent->bSide))
if (CONSIDERED_NEUTRAL(pSoldier, pOpponent) || (pSoldier->bSide == pOpponent->bSide))
{
continue; // next merc
}
pbPersOL = pSoldier->aiData.bOppList + pOpponent->ubID;
pbPublOL = gbPublicOpplist[ OUR_TEAM ] + pOpponent->ubID;
INT8 *pbPersOL = pSoldier->aiData.bOppList + pOpponent->ubID;
INT8 *pbPublOL = gbPublicOpplist[OUR_TEAM] + pOpponent->ubID;
// if this opponent is unknown personally and publicly
if( *pbPersOL != SEEN_CURRENTLY && *pbPublOL != SEEN_CURRENTLY )
if (*pbPersOL != SEEN_CURRENTLY && *pbPublOL != SEEN_CURRENTLY)
{
continue; // next merc
}
CalculateCoverFromSoldier( pOpponent, sTargetGridNo, fRoof, bOverlayType, pSoldier );
pOpponents.push_back(pOpponent);
bCowering.push_back(CoweringShockLevel(pOpponent));
tunnelVision.push_back(GetPercentTunnelVision(pOpponent));
}
// if we got no cover, just return, can't get any worse than that. Helldorados lets you count
if ( bOverlayType == NO_COVER )
// Calculate cover for the whole grid, one opponent at a time.
for (UINT32 i = 0; i < pOpponents.size(); ++i)
{
SOLDIERTYPE *pOpponent = pOpponents[i];
BOOLEAN isCowering = bCowering[i];
UINT8 tunnelVisionPercentage = tunnelVision[i];
for (INT32 ubX = gsMinCellX; ubX <= gsMaxCellX; ++ubX)
{
return;
for (INT32 ubY = gsMinCellY; ubY <= gsMaxCellY; ++ubY)
{
for (INT8 ubZ = 0; ubZ < COVER_Z_CELLS; ++ubZ)
{
INT32& sGridNo = gCoverViewArea[ubX][ubY][ubZ].sGridNo;
if (!GridNoOnScreenAndAround(sGridNo, 2))
continue;
INT8& bOverlayType = gCoverViewArea[ubX][ubY][ubZ].bOverlayType;
if (IsTheRoofVisible(sGridNo))
{
// do not show stuff on ground if roof is shown
if (ubZ == I_GROUND_LEVEL)
{
bOverlayType = INVALID_COVER;
continue;
}
}
else
{
// do not show stuff on roofs if ground is shown
if (ubZ == I_ROOF_LEVEL)
{
bOverlayType = INVALID_COVER;
continue;
}
}
if (!NewOKDestination(pSoldier, sGridNo, false, ubZ))
continue;
//Skip cover calculation if there already is no cover.
if (bOverlayType == NO_COVER)
{
continue;
}
else
{
CalculateCoverFromEnemySoldier(pOpponent, sGridNo, ubZ, bOverlayType, pSoldier, isCowering, tunnelVisionPercentage, OurSoldierStealth, OurSoldierLBESightAdjustment);
}
}
}
}
}
AddCoverObjectsToViewArea();
}
void CalculateCover()
{
register INT32 ubX, ubY;
register INT8 ubZ;
SOLDIERTYPE* pSoldier;
if (gusSelectedSoldier == NOBODY)
return;
GetSoldier(&pSoldier, gusSelectedSoldier);
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;
if (!GridNoOnScreenAndAround(sGridNo, 2))
continue;
if (IsTheRoofVisible(sGridNo))
{
// do not show stuff on ground if roof is shown
if (ubZ == I_GROUND_LEVEL)
continue;
}
else
{
// do not show stuff on roofs if ground is shown
if (ubZ == I_ROOF_LEVEL)
continue;
}
if (!NewOKDestination(pSoldier, sGridNo, false, ubZ))
continue;
INT8& bOverlayType = gCoverViewArea[ubX][ubY][ubZ].bOverlayType;
// reset cover value
bOverlayType = MAX_COVER;
if (gTacticalStatus.fAtLeastOneGuyOnMultiSelect) // view of selected mercs
{
// OK, loop through all guys who are 'multi-selected' and
INT32 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, bOverlayType);
// if the tile is already NO_COVER, there's no need to continue
if (NO_COVER == bOverlayType)
break;
}
}
}
}
else // single view from your merc
{
CalculateCoverFromSoldier(pSoldier, sGridNo, ubZ, bOverlayType);
}
// we use different enums for our merc's sight to avoid confusing inverse sight
bOverlayType = MAX_SEE - bOverlayType;
}
}
}
AddCoverObjectsToViewArea();
}
void CalculateCoverFromSoldier( SOLDIERTYPE* pFromSoldier, const INT32& sTargetGridNo, const BOOLEAN& fRoof, INT8& bOverlayType, SOLDIERTYPE* pToSoldier )
{
UINT16 usSightLimit = pFromSoldier->GetMaxDistanceVisible(sTargetGridNo, (INT8)fRoof, CALC_FROM_WANTED_DIR);
@@ -664,7 +749,7 @@ void CalculateCoverFromSoldier( SOLDIERTYPE* pFromSoldier, const INT32& sTargetG
if (pToSoldier == NULL) {
usAdjustedSight = usSightLimit;
} else {
usAdjustedSight = usSightLimit + usSightLimit * GetSightAdjustment( pToSoldier, sTargetGridNo, (INT8) fRoof, ubStance ) /100;
usAdjustedSight = usSightLimit + usSightLimit * GetSightAdjustment( pToSoldier, GetStealth(pToSoldier), GetSightAdjustmentBasedOnLBE(pToSoldier), sTargetGridNo, (INT8) fRoof, ubStance ) /100;
}
if ( SoldierToVirtualSoldierLineOfSightTest( pFromSoldier, sTargetGridNo, (INT8) fRoof, ubStance, FALSE, usAdjustedSight ) != 0 )
@@ -675,6 +760,32 @@ void CalculateCoverFromSoldier( SOLDIERTYPE* pFromSoldier, const INT32& sTargetG
}
}
static void CalculateCoverFromEnemySoldier(SOLDIERTYPE* pFromSoldier, const INT32& sTargetGridNo, const BOOLEAN& fRoof, INT8& bOverlayType, SOLDIERTYPE* pToSoldier, const BOOLEAN& bFromSoldierCowering, const UINT8& tunnelVision, const INT8 ToSoldierStealth, const INT8 ToSoldierLBeSightAdjustment)
{
// Had to extract this from SOLDIERTYPE::GetMaxDistanceVisible() function due to performance improvement from minimizing recalculating CoweringShockLevel(pSoldier) & GetPercentTunnelVision(pSoldier)
UINT16 usSightLimit = DistanceVisible(pFromSoldier, (SoldierHasLimitedVision(pFromSoldier) ? pFromSoldier->pathing.bDesiredDirection : DIRECTION_IRRELEVANT), DIRECTION_IRRELEVANT, sTargetGridNo, (INT8)fRoof, bFromSoldierCowering, tunnelVision);
for (int i = 0; i < sizeof(animArr); ++i)
{
const UINT8& ubStance = animArr[i];
INT32 usAdjustedSight;
if (pToSoldier == nullptr) {
usAdjustedSight = usSightLimit;
}
else {
usAdjustedSight = usSightLimit + usSightLimit * GetSightAdjustment(pToSoldier, ToSoldierStealth, ToSoldierLBeSightAdjustment, sTargetGridNo, (INT8)fRoof, ubStance) / 100;
}
if (SoldierToVirtualSoldierLineOfSightTest(pFromSoldier, sTargetGridNo, (INT8)fRoof, ubStance, FALSE, usAdjustedSight) != 0)
{
if (bOverlayType > i) bOverlayType = i;
break; // we go from prone to stand, if soldier can see someone crouching, he can also see someone standing
}
}
}
BOOLEAN CanSoldierSeeFloor( SOLDIERTYPE* pSoldier, INT32 sGridNo, INT8 bLevel )
{
if ( !pSoldier )
@@ -717,7 +828,7 @@ void DisplayRangeToTarget( SOLDIERTYPE *pSoldier, INT32 sTargetGridNo )
ubTerrainType = GetTerrainTypeForGrid(sTargetGridNo, gsInterfaceLevel);
}
INT8 ubCover = - GetSightAdjustment(pSoldier, sTargetGridNo, gsInterfaceLevel);
INT8 ubCover = - GetSightAdjustment(pSoldier, GetStealth(pSoldier), GetSightAdjustmentBasedOnLBE(pSoldier), sTargetGridNo, gsInterfaceLevel);
//display a string with cover value of current selected merc and brightness
//swprintf( zOutputString, gzDisplayCoverText[DC_MSG__COVER_INFORMATION], ubCover, GetTerrainName(ubTerrainType), ubBrightness );