mirror of
https://github.com/1dot13/source.git
synced 2026-07-22 13:40:22 +02:00
- allows creating of complex tripwire networks, that behave differently depending on where they are activated. Different networks can overlap, allowing a wide range of trap network designs - added network-specific view methods (ALT + Shift + C) - added new dialogues when planting tripwire New feature: remote defusing of mines (by Flugente) - the new items Remote Defuse and Remote Combo allow to remotely defuse a bomb that has been planted. Simply select a frequency for defusing upon planting the mine. This frequency is of course treated differently than a detonation frequency. New feature: directional frag explosions (by Flugente) - the tag <Directional>1</Directional> in Items.xml allows an explosive to be directional. Frags caused by its explosion will fly in the direction determined by the merc planting them. - the tags <ubHorizontalDegree> and <ubVerticalDegree> in Explosives.xml determine the arc in which the frags will fly. New feature: makeshift mines (by Flugente) - you can now create mines out of grenades: simply merge tripwire with them. You can then use them like regular mines. They can also be activated by your tripwire networks. - With a simple item transformation in the UDB, you can transform a makeshift mine back to a grenade and a piece of tripwire. Minor changes (by Flugente) - metal detector now only works if used in hands - wire cutters give a bonus if in hands while defusing tripwire or tripwire-activatable mines/bombs - added new message boxes with 8 and 16 buttons - increased the maximum number of bullets that can be on screen from 200 to 1000 (necessary for mass claymore explosions) - the tags <Detonator> and <RemoteDetonator> are not used anymore, as those properties can be set via flags in <AttachmentClass>. For now, they still remain in the xmls though. WARNING! This will break savegame compatibility! More infos on those features: 1st post: http://www.ja-galaxy-forum.com/board/ubbthreads.php?ubb=showflat&Number=303556&#Post303556 git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@5217 3b4a5df2-a311-0410-b5c6-a8a6f20db521
1222 lines
34 KiB
C++
1222 lines
34 KiB
C++
#ifdef PRECOMPILEDHEADERS
|
|
#include "AI All.h"
|
|
#include "DisplayCover.h"
|
|
#include "Interface.h"
|
|
#include "opplist.h"
|
|
#include "_Ja25Englishtext.h"
|
|
//#include "Ja25 Strategic Ai.h"
|
|
#else
|
|
#include "builddefines.h"
|
|
#include "Types.h"
|
|
#include "Isometric Utils.h"
|
|
//#include "Soldier Control.h"
|
|
#include "Overhead.h"
|
|
#include "displaycover.h"
|
|
#include "Font Control.h"
|
|
#include "_Ja25EnglishText.h"
|
|
#include "message.h"
|
|
#include "GameSettings.h"
|
|
#include "renderworld.h"
|
|
#include "Interface.h"
|
|
#include "Debug.h"
|
|
#include "PATHAI.H"
|
|
#include "worldman.h"
|
|
#include "opplist.h"
|
|
#include "los.h"
|
|
#include "weapons.h"
|
|
#include "Game Clock.h"
|
|
#include "Animation Control.h"
|
|
#include "lighting.h"
|
|
#include "Text.h"
|
|
#include "strategicmap.h"
|
|
#include "Render Fun.h"
|
|
// HEADROCK HAM B2.7: Allow calling a CTH approximation function for the CTH display ("F" key)
|
|
#include "UI Cursors.h"
|
|
#endif
|
|
|
|
//forward declarations of common classes to eliminate includes
|
|
class OBJECTTYPE;
|
|
class SOLDIERTYPE;
|
|
|
|
//******* Local Defines **************************************************
|
|
|
|
enum COVER_VALUES
|
|
{
|
|
INVALID_COVER=-1,
|
|
NO_COVER=0,
|
|
MIN_COVER=1,
|
|
MED_COVER=2,
|
|
MAX_COVER=3
|
|
};
|
|
|
|
// Flugente: mines display - stuff needs to be here
|
|
enum MINES_VALUES
|
|
{
|
|
MINES_ALL = MAX_COVER + 1,
|
|
MINE_BOMB,
|
|
MINE_WIRE,
|
|
MINE_BOMB_AND_WIRE,
|
|
MINES_NET_1,
|
|
MINES_NET_2,
|
|
MINES_NET_3,
|
|
MINES_NET_4,
|
|
MINES_LVL_1,
|
|
MINES_LVL_2,
|
|
MINES_LVL_3,
|
|
MINES_LVL_4,
|
|
MAX_MINES
|
|
};
|
|
|
|
struct CoverCell
|
|
{
|
|
INT32 sGridNo;
|
|
INT8 bCover;
|
|
BOOLEAN fInverseColor;
|
|
INT8 bMines;
|
|
|
|
CoverCell() : sGridNo(NOWHERE), bCover(INVALID_COVER), fInverseColor(FALSE), bMines(MINES_ALL) {}
|
|
};
|
|
|
|
enum COVER_DRAW_MODE {
|
|
COVER_DRAW_OFF,
|
|
COVER_DRAW_MERC_VIEW,
|
|
COVER_DRAW_ENEMY_VIEW
|
|
};
|
|
|
|
const UINT8 animArr[3] = {
|
|
ANIM_PRONE,
|
|
ANIM_CROUCH,
|
|
ANIM_STAND
|
|
};
|
|
|
|
// yea way too big... but some bytes more memory is cheap
|
|
#define COVER_X_CELLS WORLD_COLS_MAX
|
|
#define COVER_Y_CELLS WORLD_ROWS_MAX
|
|
#define COVER_Z_CELLS 2 // roof or no roof
|
|
|
|
// Flugente: mines display - stuff needs to be here
|
|
enum MINES_DRAW_MODE {
|
|
MINES_DRAW_OFF,
|
|
MINES_DRAW_DETECT_ENEMY,
|
|
MINES_DRAW_PLAYERTEAM_NETWORKS,
|
|
MINES_DRAW_NETWORKCOLOURING,
|
|
MINES_DRAW_NET_A,
|
|
MINES_DRAW_NET_B,
|
|
MINES_DRAW_NET_C,
|
|
MINES_DRAW_NET_D,
|
|
MINES_DRAW_MAX
|
|
};
|
|
|
|
//****** Local Variables *********************************************
|
|
|
|
INT16 gsMinCellX, gsMinCellY, gsMaxCellX, gsMaxCellY = -1;
|
|
|
|
CoverCell gCoverViewArea[ COVER_X_CELLS ][ COVER_Y_CELLS ][ COVER_Z_CELLS ];
|
|
|
|
DWORD guiCoverNextUpdateTime = 0;
|
|
|
|
COVER_DRAW_MODE gubDrawMode = COVER_DRAW_OFF;
|
|
MINES_DRAW_MODE gubDrawModeMine = MINES_DRAW_OFF; // Flugente: mines display
|
|
|
|
//******* Local Function Prototypes ***********************************
|
|
|
|
CHAR16* GetTerrainName( const UINT8& ubTerrainType );
|
|
|
|
TileDefines GetTileCoverIndex( const INT8& bCover );
|
|
|
|
void AddCoverObjectToWorld( const INT32& sGridNo, const UINT16& usGraphic, const BOOLEAN& fRoof );
|
|
void RemoveCoverObjectFromWorld( const INT32 sGridNo, const UINT16& usGraphic, const BOOLEAN& fRoof );
|
|
|
|
void AddCoverObjectsToViewArea();
|
|
void RemoveCoverObjectsFromViewArea();
|
|
void RemoveMinesObjectsFromViewArea(); // added by Flugente, has to be declared here
|
|
|
|
void CalculateCover();
|
|
void CalculateCoverForSoldier( SOLDIERTYPE* pForSoldier, const INT32& sTargetGridNo, const BOOLEAN& fRoof, INT8& bCover );
|
|
void CalculateCoverFromSoldier( SOLDIERTYPE* pFromSoldier, const INT32& sTargetGridNo, const BOOLEAN& fRoof, INT8& bCover, SOLDIERTYPE* pToSoldier=NULL );
|
|
|
|
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 );
|
|
|
|
//******* Functions **************************************************
|
|
|
|
///BEGIN key binding functions
|
|
void SwitchToMercView()
|
|
{
|
|
if (gubDrawMode == COVER_DRAW_MERC_VIEW)
|
|
return;
|
|
|
|
gubDrawMode = COVER_DRAW_MERC_VIEW;
|
|
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, gzDisplayCoverText[DC_MSG__COVER_DRAW_MERC_VIEW]);
|
|
DisplayCover(TRUE);
|
|
}
|
|
|
|
void SwitchToEnemyView()
|
|
{
|
|
if (gubDrawMode == COVER_DRAW_ENEMY_VIEW)
|
|
return;
|
|
|
|
gubDrawMode = COVER_DRAW_ENEMY_VIEW;
|
|
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, gzDisplayCoverText[DC_MSG__COVER_DRAW_ENEMY_VIEW]);
|
|
DisplayCover(TRUE);
|
|
}
|
|
|
|
void SwitchViewOff()
|
|
{
|
|
if (gubDrawMode == COVER_DRAW_OFF)
|
|
return;
|
|
|
|
gubDrawMode = COVER_DRAW_OFF;
|
|
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, gzDisplayCoverText[DC_MSG__COVER_DRAW_OFF]);
|
|
DisplayCover(TRUE);
|
|
}
|
|
|
|
void ToggleEnemyView()
|
|
{
|
|
if (gubDrawMode == COVER_DRAW_ENEMY_VIEW) {
|
|
SwitchViewOff();
|
|
} else {
|
|
SwitchToEnemyView();
|
|
}
|
|
}
|
|
|
|
void ToggleMercView()
|
|
{
|
|
if (gubDrawMode == COVER_DRAW_MERC_VIEW) {
|
|
SwitchViewOff();
|
|
} else {
|
|
SwitchToMercView();
|
|
}
|
|
}
|
|
|
|
void SwitchCoverDrawMode()
|
|
{
|
|
switch(gubDrawMode)
|
|
{
|
|
case COVER_DRAW_OFF:
|
|
SwitchToMercView();
|
|
break;
|
|
case COVER_DRAW_MERC_VIEW:
|
|
SwitchToEnemyView();
|
|
break;
|
|
default:
|
|
SwitchViewOff();
|
|
break;
|
|
}
|
|
}
|
|
///END key binding functions
|
|
|
|
void GetGridNoForViewPort( const INT32& ubX, const INT32& ubY, INT32& sGridNo )
|
|
{
|
|
sGridNo = MAPROWCOLTOPOS( ubY, ubX );
|
|
}
|
|
|
|
CHAR16* GetTerrainName( const UINT8& ubTerrainType )
|
|
{
|
|
switch(ubTerrainType) {
|
|
case LOW_GRASS:
|
|
case HIGH_GRASS:
|
|
return gzDisplayCoverText[DC_TTI__WOOD];
|
|
case FLAT_FLOOR:
|
|
case PAVED_ROAD:
|
|
return gzDisplayCoverText[DC_TTI__URBAN];
|
|
case DIRT_ROAD:
|
|
case TRAIN_TRACKS:
|
|
return gzDisplayCoverText[DC_TTI__DESERT];
|
|
case FLAT_GROUND:
|
|
return gzDisplayCoverText[DC_TTI__WOOD_AND_DESERT];
|
|
default:
|
|
return gzDisplayCoverText[DC_TTI__UNKNOWN];
|
|
}
|
|
}
|
|
|
|
TileDefines GetTileCoverIndex( const INT8& bCover )
|
|
{
|
|
switch(bCover) {
|
|
case NO_COVER:
|
|
return SPECIALTILE_COVER_1; // red
|
|
case MIN_COVER:
|
|
return SPECIALTILE_COVER_2; // orange
|
|
case MED_COVER:
|
|
return SPECIALTILE_COVER_3; // yellow
|
|
case MAX_COVER:
|
|
return SPECIALTILE_COVER_5; // green
|
|
default:
|
|
return SPECIALTILE_COVER_4; // light green, can be used to denote that you just don't know.
|
|
}
|
|
}
|
|
|
|
void AddCoverObjectToWorld( const INT32& sGridNo, const UINT16& usGraphic, const BOOLEAN& fRoof )
|
|
{
|
|
LEVELNODE *pNode;
|
|
|
|
if( fRoof )
|
|
{
|
|
AddOnRoofToHead( sGridNo, usGraphic );
|
|
pNode = gpWorldLevelData[ sGridNo ].pOnRoofHead;
|
|
}
|
|
else
|
|
{
|
|
AddObjectToHead( sGridNo, usGraphic );
|
|
pNode = gpWorldLevelData[ sGridNo ].pObjectHead;
|
|
}
|
|
|
|
pNode->uiFlags |= LEVELNODE_REVEAL;
|
|
|
|
if( NightTime() )
|
|
{
|
|
pNode->ubShadeLevel=DEFAULT_SHADE_LEVEL;
|
|
pNode->ubNaturalShadeLevel=DEFAULT_SHADE_LEVEL;
|
|
}
|
|
}
|
|
|
|
void RemoveCoverObjectFromWorld( const INT32 sGridNo, const UINT16& usGraphic, const BOOLEAN& fRoof )
|
|
{
|
|
if( fRoof )
|
|
{
|
|
RemoveOnRoof( sGridNo, usGraphic );
|
|
}
|
|
else
|
|
{
|
|
RemoveObject( sGridNo, usGraphic );
|
|
}
|
|
}
|
|
|
|
BOOLEAN HasAdjTile( const INT32& ubX, const INT32& ubY, const INT32& ubZ )
|
|
{
|
|
INT32 ubTX, ubTY;
|
|
|
|
for ( ubTX = ubX-1; ubTX <= ubX+1; ++ubTX )
|
|
{
|
|
if ( ubTX < 0 || ubTX > WORLD_COLS )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
for ( ubTY = ubY-1; ubTY <= ubY+1; ++ubTY )
|
|
{
|
|
if ( ubTY < 0 || ubTY > WORLD_ROWS )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
INT8& bCover = gCoverViewArea[ ubTX ][ ubTY ][ ubZ ].bCover;
|
|
|
|
if ( bCover > -1 && bCover < MAX_COVER )
|
|
{
|
|
return TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
void AddCoverObjectsToViewArea()
|
|
{
|
|
if (gsMaxCellY == -1)
|
|
{
|
|
return;
|
|
}
|
|
INT32 ubX, ubY, ubZ;
|
|
BOOLEAN fChanged = FALSE;
|
|
|
|
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;
|
|
INT8& bCover = gCoverViewArea[ ubX ][ ubY ][ ubZ ].bCover;
|
|
BOOLEAN& fInverseColor = gCoverViewArea[ ubX ][ ubY ][ ubZ ].fInverseColor;
|
|
|
|
if ( bCover != -1 && ( bCover != MAX_COVER || HasAdjTile( ubX, ubY, ubZ ) ) )
|
|
{
|
|
TileDefines tile = GetTileCoverIndex(!fInverseColor ? bCover : MAX_COVER - bCover);
|
|
AddCoverObjectToWorld( sGridNo, tile, (BOOLEAN) ubZ );
|
|
fChanged = TRUE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Re-render the scene!
|
|
if ( fChanged )
|
|
{
|
|
SetRenderFlags( RENDER_FLAG_FULL );
|
|
}
|
|
}
|
|
|
|
void RemoveCoverObjectsFromViewArea()
|
|
{
|
|
if (gsMaxCellY == -1)
|
|
{
|
|
return;
|
|
}
|
|
INT32 ubX, ubY, ubZ;
|
|
BOOLEAN fChanged = FALSE;
|
|
|
|
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;
|
|
INT8& bCover = gCoverViewArea[ ubX ][ ubY ][ ubZ ].bCover;
|
|
BOOLEAN& fInverseColor = gCoverViewArea[ ubX ][ ubY ][ ubZ ].fInverseColor;
|
|
|
|
if ( bCover != -1 )
|
|
{
|
|
TileDefines tile = GetTileCoverIndex(!fInverseColor ? bCover : MAX_COVER - bCover);
|
|
RemoveCoverObjectFromWorld( sGridNo, tile, (BOOLEAN) ubZ );
|
|
bCover = -1;
|
|
fChanged = TRUE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Re-render the scene!
|
|
if ( fChanged )
|
|
{
|
|
SetRenderFlags( RENDER_FLAG_FULL );
|
|
}
|
|
}
|
|
|
|
// ubRadius in times of y or x cell sizes
|
|
BOOLEAN GridNoOnScreenAndAround( const INT32& sGridNo, const UINT8& ubRadius )
|
|
{
|
|
INT16 sNewCenterWorldX, sNewCenterWorldY;
|
|
INT16 sWorldX;
|
|
INT16 sWorldY;
|
|
|
|
UINT16 usXDiff = ubRadius*CELL_X_SIZE;
|
|
UINT16 usYDiff = ubRadius*CELL_Y_SIZE;
|
|
|
|
ConvertGridNoToXY( sGridNo, &sNewCenterWorldX, &sNewCenterWorldY );
|
|
|
|
// Get screen coordinates for current position of soldier
|
|
GetWorldXYAbsoluteScreenXY( (INT16)(sNewCenterWorldX), (INT16)(sNewCenterWorldY), &sWorldX, &sWorldY);
|
|
|
|
if ( sWorldX >= ( gsTopLeftWorldX - usXDiff )
|
|
&& sWorldX <= ( gsBottomRightWorldX + usXDiff )
|
|
&& sWorldY >= ( gsTopLeftWorldY - usYDiff + gsVIEWPORT_WINDOW_START_Y )
|
|
&& sWorldY <= ( gsBottomRightWorldY + usYDiff ) )
|
|
{
|
|
return( TRUE );
|
|
}
|
|
return( FALSE );
|
|
}
|
|
|
|
void DisplayCover( const BOOLEAN& forceUpdate )
|
|
{
|
|
if ( gGameExternalOptions.ubCoverDisplayUpdateWait == -1 )
|
|
{
|
|
return;
|
|
}
|
|
|
|
if ( forceUpdate || ( !gfScrollPending && !gfScrollInertia && GetTickCount() > guiCoverNextUpdateTime ) )
|
|
{
|
|
CalculateCover();
|
|
guiCoverNextUpdateTime = GetTickCount() + gGameExternalOptions.ubCoverDisplayUpdateWait;
|
|
}
|
|
}
|
|
|
|
void CalculateCover()
|
|
{
|
|
INT32 ubX, ubY, 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 );
|
|
|
|
const INT32& sSelectedSoldierGridNo = MercPtrs[ gusSelectedSoldier ]->sGridNo;
|
|
|
|
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;
|
|
INT8& bCover = gCoverViewArea[ ubX ][ ubY ][ ubZ ].bCover;
|
|
BOOLEAN& fInverseColor = gCoverViewArea[ ubX ][ ubY ][ ubZ ].fInverseColor;
|
|
|
|
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 (BehindSoldier( x, y ))
|
|
|
|
|
|
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 ) // single view from your merc
|
|
{
|
|
// reset cover value
|
|
bCover = MAX_COVER;
|
|
CalculateCoverFromSoldier( pSoldier, sGridNo, ubZ, bCover );
|
|
fInverseColor = TRUE; // we don't want to show the cover for the enemy
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
AddCoverObjectsToViewArea();
|
|
}
|
|
|
|
void CalculateCoverForSoldier( SOLDIERTYPE* pSoldier, const INT32& sTargetGridNo, const BOOLEAN& fRoof, INT8& bCover )
|
|
{
|
|
UINT32 uiLoop;
|
|
SOLDIERTYPE *pOpponent;
|
|
INT8 *pbPersOL;
|
|
INT8 *pbPublOL;
|
|
|
|
//loop through all the enemies and determine the cover
|
|
for (uiLoop = 0; uiLoop<guiNumMercSlots; ++uiLoop)
|
|
{
|
|
pOpponent = MercSlots[ uiLoop ];
|
|
|
|
// if this merc is inactive, at base, on assignment, dead, unconscious
|
|
if (!pOpponent || pOpponent->stats.bLife < OKLIFE)
|
|
{
|
|
continue; // next merc
|
|
}
|
|
|
|
// if this man is neutral / on the same side, he's not an opponent
|
|
if( CONSIDERED_NEUTRAL( pSoldier, pOpponent ) || (pSoldier->bSide == pOpponent->bSide))
|
|
{
|
|
continue; // next merc
|
|
}
|
|
|
|
pbPersOL = pSoldier->aiData.bOppList + pOpponent->ubID;
|
|
pbPublOL = gbPublicOpplist[ OUR_TEAM ] + pOpponent->ubID;
|
|
|
|
// if this opponent is unknown personally and publicly
|
|
if( *pbPersOL != SEEN_CURRENTLY && *pbPublOL != SEEN_CURRENTLY )
|
|
{
|
|
continue; // next merc
|
|
}
|
|
|
|
CalculateCoverFromSoldier( pOpponent, sTargetGridNo, fRoof, bCover, pSoldier );
|
|
|
|
// if we got no cover, just return, can't get any worse than that. Helldorados lets you count
|
|
if (bCover == NO_COVER)
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
void CalculateCoverFromSoldier( SOLDIERTYPE* pFromSoldier, const INT32& sTargetGridNo, const BOOLEAN& fRoof, INT8& bCover, SOLDIERTYPE* pToSoldier )
|
|
{
|
|
UINT16 usSightLimit = pFromSoldier->GetMaxDistanceVisible(sTargetGridNo, (INT8)fRoof, CALC_FROM_WANTED_DIR);
|
|
|
|
for ( int i = 0; i<sizeof(animArr); ++i )
|
|
{
|
|
const UINT8& ubStance = animArr[i];
|
|
|
|
INT32 usAdjustedSight;
|
|
|
|
if (pToSoldier == NULL) {
|
|
usAdjustedSight = usSightLimit;
|
|
} else {
|
|
usAdjustedSight = usSightLimit + usSightLimit * GetSightAdjustment( pToSoldier, sTargetGridNo, (INT8) fRoof, ubStance ) /100;
|
|
}
|
|
|
|
if ( SoldierToVirtualSoldierLineOfSightTest( pFromSoldier, sTargetGridNo, (INT8) fRoof, ubStance, FALSE, usAdjustedSight ) != 0 )
|
|
{
|
|
if (bCover > i) bCover = i;
|
|
break; // we go from prone to stand, if soldier can see someone crouching, he can also see someone standing
|
|
}
|
|
}
|
|
}
|
|
|
|
void DisplayRangeToTarget( SOLDIERTYPE *pSoldier, INT32 sTargetGridNo )
|
|
{
|
|
UINT16 usRange=0;
|
|
CHAR16 zOutputString[512];
|
|
UINT8 title = (UsingNewCTHSystem() == true ? DC_MSG__NCTH_GUN_RANGE_INFORMATION : DC_MSG__GUN_RANGE_INFORMATION);
|
|
|
|
if( sTargetGridNo == NOWHERE || sTargetGridNo == 0 )
|
|
{
|
|
return;
|
|
}
|
|
|
|
{
|
|
UINT8 ubLightLevel = LightTrueLevel(sTargetGridNo, gsInterfaceLevel);
|
|
UINT8 ubBrightness = 100 - 100 * (ubLightLevel-SHADE_MAX)/(SHADE_MIN-SHADE_MAX); // percentage
|
|
INT8 ubTerrainType = GetTerrainTypeForGrid(sTargetGridNo, gsInterfaceLevel);
|
|
|
|
INT8 ubCover = - GetSightAdjustment(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 );
|
|
|
|
//Display the msg
|
|
//ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, zOutputString );
|
|
|
|
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE,
|
|
gzDisplayCoverText[DC_MSG__COVER_INFORMATION],
|
|
ubCover, GetTerrainName(ubTerrainType), ubBrightness );
|
|
}
|
|
|
|
//Get the range to the target location
|
|
usRange = GetRangeInCellCoordsFromGridNoDiff( pSoldier->sGridNo, sTargetGridNo );
|
|
|
|
//if the soldier has a weapon in hand, display gun range and chance to hit
|
|
if( WeaponInHand( pSoldier ) )
|
|
{
|
|
UINT32 uiHitChance;
|
|
//AXP 30.03.2007: Fix CtH calculation for first shot after changing aim level (roof/ground)
|
|
INT8 bTempTargetLevel = pSoldier->bTargetLevel;
|
|
pSoldier->bTargetLevel = (INT8)gsInterfaceLevel;
|
|
uiHitChance = CalcChanceToHitGun( pSoldier, sTargetGridNo, (INT8)(pSoldier->aiData.bShownAimTime ), pSoldier->bAimShotLocation );
|
|
// HEADROCK HAM B2.7: CTH approximation?
|
|
if (gGameExternalOptions.fApproximateCTH)
|
|
{
|
|
uiHitChance = ChanceToHitApproximation( pSoldier, uiHitChance );
|
|
}
|
|
pSoldier->bTargetLevel = bTempTargetLevel;
|
|
|
|
// HEADROCK HAM 3.6: Calculate Gun Range using formula.
|
|
// Flugente: we might be equipped with an underbarrel gun....
|
|
OBJECTTYPE* pObjhand = pSoldier->GetUsedWeapon(&pSoldier->inv[HANDPOS]);
|
|
UINT16 usGunRange = GunRange(pObjhand, pSoldier ); // SANDRO - added argument
|
|
|
|
swprintf( zOutputString, gzDisplayCoverText[title], usRange / 10, usGunRange / 10, uiHitChance );
|
|
//Display the msg
|
|
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, zOutputString );
|
|
}
|
|
else
|
|
{
|
|
swprintf( zOutputString, gzDisplayCoverText[title], usRange / 10, 0, 0 );
|
|
|
|
//Display the msg
|
|
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, zOutputString );
|
|
}
|
|
|
|
//increment the display gun range counter ( just seeing how many times people use it )
|
|
//gJa25SaveStruct.uiDisplayGunRangeCounter++;
|
|
}
|
|
|
|
BOOLEAN IsTheRoofVisible( const INT32& sGridNo )
|
|
{
|
|
if( FlatRoofAboveGridNo( sGridNo ) )
|
|
{
|
|
if( gpWorldLevelData[ sGridNo ].uiFlags & MAPELEMENT_REVEALED )
|
|
{
|
|
if( gTacticalStatus.uiFlags & SHOW_ALL_ROOFS )
|
|
return( TRUE );
|
|
else
|
|
return( FALSE );
|
|
}
|
|
else
|
|
{
|
|
return( TRUE );
|
|
}
|
|
}
|
|
|
|
return( FALSE );
|
|
}
|
|
|
|
// ----------------------------- Mines display after this ----------------------------------------
|
|
// added by Flugente
|
|
|
|
//****** Local Variables *********************************************
|
|
|
|
INT16 gsMineMinCellX, gsMineMinCellY, gsMineMaxCellX, gsMineMaxCellY = -1;
|
|
|
|
DWORD guiMinesNextUpdateTime = 0;
|
|
|
|
//******* Local Function Prototypes ***********************************
|
|
|
|
TileDefines GetTileMinesIndex( const INT8& bMines );
|
|
|
|
void AddMinesObjectsToViewArea();
|
|
|
|
void CalculateMines();
|
|
void DetermineMineDisplayInTile( INT32 sGridNo, INT8 bLevel, INT8& bMines, BOOLEAN fWithMineDetector = FALSE );
|
|
|
|
BOOLEAN MineTileHasAdjTile( const INT32& ubX, const INT32& ubY, const INT32& ubZ );
|
|
|
|
//******* Functions **************************************************
|
|
|
|
///BEGIN key binding functions
|
|
void SwitchToTrapNetworkView()
|
|
{
|
|
if (gubDrawModeMine == MINES_DRAW_PLAYERTEAM_NETWORKS)
|
|
return;
|
|
|
|
gubDrawModeMine = MINES_DRAW_PLAYERTEAM_NETWORKS;
|
|
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Display trap network");
|
|
DisplayMines(TRUE);
|
|
}
|
|
|
|
void SwitchToHostileTrapsView()
|
|
{
|
|
if (gubDrawModeMine == MINES_DRAW_DETECT_ENEMY)
|
|
return;
|
|
|
|
gubDrawModeMine = MINES_DRAW_DETECT_ENEMY;
|
|
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Display nearby traps");
|
|
DisplayMines(TRUE);
|
|
}
|
|
|
|
void SwitchMineViewOff()
|
|
{
|
|
if (gubDrawModeMine == MINES_DRAW_OFF)
|
|
return;
|
|
|
|
gubDrawModeMine = MINES_DRAW_OFF;
|
|
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Turning off trap display");
|
|
DisplayMines(TRUE);
|
|
}
|
|
|
|
void ToggleHostileTrapsView()
|
|
{
|
|
if (gubDrawModeMine == MINES_DRAW_DETECT_ENEMY) {
|
|
SwitchMineViewOff();
|
|
} else {
|
|
SwitchToHostileTrapsView();
|
|
}
|
|
}
|
|
|
|
void ToggleTrapNetworkView()
|
|
{
|
|
SwitchMinesDrawModeForNetworks();
|
|
/*if (gubDrawModeMine == MINES_DRAW_PLAYERTEAM_NETWORKS) {
|
|
SwitchMineViewOff();
|
|
} else {
|
|
SwitchToTrapNetworkView();
|
|
}*/
|
|
}
|
|
|
|
void SwitchMinesDrawModeForNetworks()
|
|
{
|
|
switch ( gubDrawModeMine )
|
|
{
|
|
case MINES_DRAW_OFF:
|
|
case MINES_DRAW_DETECT_ENEMY:
|
|
gubDrawModeMine = MINES_DRAW_PLAYERTEAM_NETWORKS;
|
|
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Display trap network");
|
|
DisplayMines(TRUE);
|
|
break;
|
|
|
|
case MINES_DRAW_PLAYERTEAM_NETWORKS:
|
|
gubDrawModeMine = MINES_DRAW_NETWORKCOLOURING;
|
|
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Display trap network colouring");
|
|
DisplayMines(TRUE);
|
|
break;
|
|
case MINES_DRAW_NETWORKCOLOURING:
|
|
gubDrawModeMine = MINES_DRAW_NET_A;
|
|
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Display trap network A");
|
|
DisplayMines(TRUE);
|
|
break;
|
|
case MINES_DRAW_NET_A:
|
|
gubDrawModeMine = MINES_DRAW_NET_B;
|
|
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Display trap network B");
|
|
DisplayMines(TRUE);
|
|
break;
|
|
case MINES_DRAW_NET_B:
|
|
gubDrawModeMine = MINES_DRAW_NET_C;
|
|
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Display trap network C");
|
|
DisplayMines(TRUE);
|
|
break;
|
|
case MINES_DRAW_NET_C:
|
|
gubDrawModeMine = MINES_DRAW_NET_D;
|
|
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Display trap network D");
|
|
DisplayMines(TRUE);
|
|
break;
|
|
case MINES_DRAW_NET_D:
|
|
case MINES_DRAW_MAX:
|
|
default:
|
|
gubDrawModeMine = MINES_DRAW_OFF;
|
|
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Turning off trap display");
|
|
DisplayMines(TRUE);
|
|
break;
|
|
}
|
|
|
|
/*switch(gubDrawModeMine)
|
|
{
|
|
case MINES_DRAW_OFF:
|
|
SwitchToTrapNetworkView();
|
|
break;
|
|
case MINES_DRAW_PLAYERTEAM_NETWORKS:
|
|
SwitchToHostileTrapsView();
|
|
break;
|
|
default:
|
|
SwitchMineViewOff();
|
|
break;
|
|
}*/
|
|
}
|
|
///END key binding functions
|
|
|
|
TileDefines GetTileMinesIndex( const INT8& bMines )
|
|
{
|
|
switch(bMines)
|
|
{
|
|
case MINES_ALL:
|
|
case MINE_BOMB:
|
|
case MINES_NET_1:
|
|
case MINES_LVL_4:
|
|
return SPECIALTILE_COVER_1; // red
|
|
case MINE_BOMB_AND_WIRE:
|
|
case MINES_NET_2:
|
|
case MINES_LVL_3:
|
|
return SPECIALTILE_COVER_2; // orange
|
|
case MINE_WIRE:
|
|
case MINES_NET_3:
|
|
case MINES_LVL_2:
|
|
return SPECIALTILE_COVER_3; // yellow
|
|
case MINES_NET_4:
|
|
case MINES_LVL_1:
|
|
return SPECIALTILE_COVER_4; // green
|
|
case MAX_MINES:
|
|
default:
|
|
return SPECIALTILE_COVER_5; // light green, can be used to denote that you just don't know. looks just like normal green, though...
|
|
}
|
|
}
|
|
|
|
BOOLEAN MineTileHasAdjTile( const INT32& ubX, const INT32& ubY, const INT32& ubZ )
|
|
{
|
|
// no search for adjacent tiles wehn looking at a specific network (we have only 4 colours, need them all :-)
|
|
if ( gubDrawModeMine == MINES_DRAW_NETWORKCOLOURING || gubDrawModeMine == MINES_DRAW_NET_A || gubDrawModeMine == MINES_DRAW_NET_B || gubDrawModeMine == MINES_DRAW_NET_C || gubDrawModeMine == MINES_DRAW_NET_D )
|
|
return FALSE;
|
|
|
|
INT32 ubTX, ubTY;
|
|
|
|
for ( ubTX = ubX-1; ubTX <= ubX+1; ++ubTX )
|
|
{
|
|
if ( ubTX < 0 || ubTX > WORLD_COLS )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
for ( ubTY = ubY-1; ubTY <= ubY+1; ++ubTY )
|
|
{
|
|
if ( ubTY < 0 || ubTY > WORLD_ROWS )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
INT8& bMines = gCoverViewArea[ ubTX ][ ubTY ][ ubZ ].bMines;
|
|
|
|
if ( bMines > MINES_ALL && bMines < MAX_MINES )
|
|
{
|
|
return TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
void AddMinesObjectsToViewArea()
|
|
{
|
|
if (gsMineMaxCellY == -1)
|
|
{
|
|
return;
|
|
}
|
|
INT32 ubX, ubY, ubZ;
|
|
BOOLEAN fChanged = FALSE;
|
|
|
|
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;
|
|
INT8& bMines = gCoverViewArea[ ubX ][ ubY ][ ubZ ].bMines;
|
|
|
|
if ( bMines != MINES_ALL && ( bMines != MAX_MINES || MineTileHasAdjTile( ubX, ubY, ubZ ) ) )
|
|
{
|
|
TileDefines tile = GetTileMinesIndex( bMines );
|
|
AddCoverObjectToWorld( sGridNo, tile, (BOOLEAN) ubZ );
|
|
fChanged = TRUE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Re-render the scene!
|
|
if ( fChanged )
|
|
{
|
|
SetRenderFlags( RENDER_FLAG_FULL );
|
|
}
|
|
}
|
|
|
|
void RemoveMinesObjectsFromViewArea()
|
|
{
|
|
if (gsMineMaxCellY == -1)
|
|
{
|
|
return;
|
|
}
|
|
INT32 ubX, ubY, ubZ;
|
|
BOOLEAN fChanged = FALSE;
|
|
|
|
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;
|
|
INT8& bMines = gCoverViewArea[ ubX ][ ubY ][ ubZ ].bMines;
|
|
|
|
if ( bMines != MINES_ALL )
|
|
{
|
|
TileDefines tile = GetTileMinesIndex( bMines );
|
|
RemoveCoverObjectFromWorld( sGridNo, tile, (BOOLEAN) ubZ );
|
|
bMines = MINES_ALL;
|
|
fChanged = TRUE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Re-render the scene!
|
|
if ( fChanged )
|
|
{
|
|
SetRenderFlags( RENDER_FLAG_FULL );
|
|
}
|
|
}
|
|
|
|
void DisplayMines( const BOOLEAN& forceUpdate )
|
|
{
|
|
if ( gGameExternalOptions.ubCoverDisplayUpdateWait == -1 )
|
|
{
|
|
return;
|
|
}
|
|
|
|
if ( forceUpdate || ( !gfScrollPending && !gfScrollInertia && GetTickCount() > guiMinesNextUpdateTime ) )
|
|
{
|
|
CalculateMines();
|
|
guiMinesNextUpdateTime = GetTickCount() + gGameExternalOptions.ubCoverDisplayUpdateWait;
|
|
}
|
|
}
|
|
|
|
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) )
|
|
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;
|
|
INT8& bMines = gCoverViewArea[ ubX ][ ubY ][ ubZ ].bMines;
|
|
|
|
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;
|
|
}
|
|
|
|
bMines = MAX_MINES;
|
|
|
|
// 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;
|
|
}
|
|
|
|
DetermineMineDisplayInTile( sGridNo, ubZ, bMines, fWithMineDetector );
|
|
}
|
|
}
|
|
}
|
|
|
|
AddMinesObjectsToViewArea();
|
|
}
|
|
|
|
|
|
void DetermineMineDisplayInTile( INT32 sGridNo, INT8 bLevel, INT8& bMines, BOOLEAN fWithMineDetector )
|
|
{
|
|
// if there is a bomb at that grid and level, and it isn't disabled
|
|
for (UINT32 uiWorldBombIndex = 0; uiWorldBombIndex < guiNumWorldBombs; ++uiWorldBombIndex)
|
|
{
|
|
if (gWorldBombs[uiWorldBombIndex].fExists && gWorldItems[ gWorldBombs[uiWorldBombIndex].iItemIndex ].sGridNo == sGridNo && gWorldItems[ gWorldBombs[uiWorldBombIndex].iItemIndex ].ubLevel == bLevel )
|
|
{
|
|
OBJECTTYPE* pObj = &( gWorldItems[ gWorldBombs[uiWorldBombIndex].iItemIndex ].object );
|
|
if (!((*pObj).fFlags & OBJECT_DISABLED_BOMB))
|
|
{
|
|
// we are looking for hostile mines and have got an detector equipped
|
|
if ( gubDrawModeMine == MINES_DRAW_DETECT_ENEMY && fWithMineDetector )
|
|
{
|
|
// display all mines
|
|
bMines = MINE_BOMB;
|
|
}
|
|
else
|
|
{
|
|
// look for mines from our own team
|
|
if ( (*pObj)[0]->data.misc.ubBombOwner > 1 )
|
|
{
|
|
switch ( gubDrawModeMine )
|
|
{
|
|
case MINES_DRAW_PLAYERTEAM_NETWORKS:
|
|
{
|
|
if ( Item[pObj->usItem].tripwire == 1 )
|
|
{
|
|
// if we're already marked as MINE_BOMB, switch to MINE_BOMB_AND_WIRE
|
|
if ( bMines == MINE_BOMB )
|
|
bMines = MINE_BOMB_AND_WIRE;
|
|
else
|
|
bMines = MINE_WIRE;
|
|
}
|
|
else
|
|
{
|
|
// if we're already marked as MINE_WIRE, switch to MINE_BOMB_AND_WIRE
|
|
if ( bMines == MINE_WIRE )
|
|
bMines = MINE_BOMB_AND_WIRE;
|
|
else
|
|
bMines = MINE_BOMB;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case MINES_DRAW_NETWORKCOLOURING:
|
|
{
|
|
if ( Item[pObj->usItem].tripwire == 1 )
|
|
{
|
|
// determine if wire is of the network we're searching for
|
|
// determine this tripwire's flag
|
|
UINT32 ubWireNetworkFlag = (*pObj)[0]->data.ubWireNetworkFlag;
|
|
|
|
// correct network?
|
|
if ( (ubWireNetworkFlag & ( PLAYER_NET_1_LVL_1 | PLAYER_NET_1_LVL_2 | PLAYER_NET_1_LVL_3 | PLAYER_NET_1_LVL_4 ) ) != 0 )
|
|
bMines = MINES_NET_1;
|
|
else if ( (ubWireNetworkFlag & ( PLAYER_NET_2_LVL_1 | PLAYER_NET_2_LVL_2 | PLAYER_NET_2_LVL_3 | PLAYER_NET_2_LVL_4 ) ) != 0 )
|
|
bMines = MINES_NET_2;
|
|
else if ( (ubWireNetworkFlag & ( PLAYER_NET_3_LVL_1 | PLAYER_NET_3_LVL_2 | PLAYER_NET_3_LVL_3 | PLAYER_NET_3_LVL_4 ) ) != 0 )
|
|
bMines = MINES_NET_3;
|
|
else if ( (ubWireNetworkFlag & ( PLAYER_NET_4_LVL_1 | PLAYER_NET_4_LVL_2 | PLAYER_NET_4_LVL_3 | PLAYER_NET_4_LVL_4 ) ) != 0 )
|
|
bMines = MINES_NET_4;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case MINES_DRAW_NET_A:
|
|
{
|
|
if ( Item[pObj->usItem].tripwire == 1 )
|
|
{
|
|
// determine if wire is of the network we're searching for
|
|
// determine this tripwire's flag
|
|
UINT32 ubWireNetworkFlag = (*pObj)[0]->data.ubWireNetworkFlag;
|
|
|
|
// correct network?
|
|
if ( (ubWireNetworkFlag & ( PLAYER_NET_1_LVL_1 | PLAYER_NET_1_LVL_2 | PLAYER_NET_1_LVL_3 | PLAYER_NET_1_LVL_4 ) ) != 0 )
|
|
{
|
|
bMines = MINES_LVL_1;
|
|
|
|
if ( (ubWireNetworkFlag & ( PLAYER_NET_1_LVL_2 ) ) != 0 )
|
|
bMines = MINES_LVL_2;
|
|
else if ( (ubWireNetworkFlag & ( PLAYER_NET_1_LVL_3 ) ) != 0 )
|
|
bMines = MINES_LVL_3;
|
|
else if ( (ubWireNetworkFlag & ( PLAYER_NET_1_LVL_4 ) ) != 0 )
|
|
bMines = MINES_LVL_4;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case MINES_DRAW_NET_B:
|
|
{
|
|
if ( Item[pObj->usItem].tripwire == 1 )
|
|
{
|
|
// determine if wire is of the network we're searching for
|
|
// determine this tripwire's flag
|
|
UINT32 ubWireNetworkFlag = (*pObj)[0]->data.ubWireNetworkFlag;
|
|
|
|
// correct network?
|
|
if ( (ubWireNetworkFlag & ( PLAYER_NET_2_LVL_1 | PLAYER_NET_2_LVL_2 | PLAYER_NET_2_LVL_3 | PLAYER_NET_2_LVL_4 ) ) != 0 )
|
|
{
|
|
bMines = MINES_LVL_1;
|
|
|
|
if ( (ubWireNetworkFlag & ( PLAYER_NET_2_LVL_2 ) ) != 0 )
|
|
bMines = MINES_LVL_2;
|
|
else if ( (ubWireNetworkFlag & ( PLAYER_NET_2_LVL_3 ) ) != 0 )
|
|
bMines = MINES_LVL_3;
|
|
else if ( (ubWireNetworkFlag & ( PLAYER_NET_2_LVL_4 ) ) != 0 )
|
|
bMines = MINES_LVL_4;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case MINES_DRAW_NET_C:
|
|
{
|
|
if ( Item[pObj->usItem].tripwire == 1 )
|
|
{
|
|
// determine if wire is of the network we're searching for
|
|
// determine this tripwire's flag
|
|
UINT32 ubWireNetworkFlag = (*pObj)[0]->data.ubWireNetworkFlag;
|
|
|
|
// correct network?
|
|
if ( (ubWireNetworkFlag & ( PLAYER_NET_3_LVL_1 | PLAYER_NET_3_LVL_2 | PLAYER_NET_3_LVL_3 | PLAYER_NET_3_LVL_4 ) ) != 0 )
|
|
{
|
|
bMines = MINES_LVL_1;
|
|
|
|
if ( (ubWireNetworkFlag & ( PLAYER_NET_3_LVL_2 ) ) != 0 )
|
|
bMines = MINES_LVL_2;
|
|
else if ( (ubWireNetworkFlag & ( PLAYER_NET_3_LVL_3 ) ) != 0 )
|
|
bMines = MINES_LVL_3;
|
|
else if ( (ubWireNetworkFlag & ( PLAYER_NET_3_LVL_4 ) ) != 0 )
|
|
bMines = MINES_LVL_4;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case MINES_DRAW_NET_D:
|
|
{
|
|
if ( Item[pObj->usItem].tripwire == 1 )
|
|
{
|
|
// determine if wire is of the network we're searching for
|
|
// determine this tripwire's flag
|
|
UINT32 ubWireNetworkFlag = (*pObj)[0]->data.ubWireNetworkFlag;
|
|
|
|
// correct network?
|
|
if ( (ubWireNetworkFlag & ( PLAYER_NET_4_LVL_1 | PLAYER_NET_4_LVL_2 | PLAYER_NET_4_LVL_3 | PLAYER_NET_4_LVL_4 ) ) != 0 )
|
|
{
|
|
bMines = MINES_LVL_1;
|
|
|
|
if ( (ubWireNetworkFlag & ( PLAYER_NET_4_LVL_2 ) ) != 0 )
|
|
bMines = MINES_LVL_2;
|
|
else if ( (ubWireNetworkFlag & ( PLAYER_NET_4_LVL_3 ) ) != 0 )
|
|
bMines = MINES_LVL_3;
|
|
else if ( (ubWireNetworkFlag & ( PLAYER_NET_4_LVL_4 ) ) != 0 )
|
|
bMines = MINES_LVL_4;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case MINES_DRAW_DETECT_ENEMY:
|
|
case MINES_DRAW_MAX:
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|