mirror of
https://github.com/1dot13/source.git
synced 2026-07-22 13:40:22 +02:00
- guns can now be attached to tripwire and then be used as tripwire-activatd traps o Attach any firearm (any gun, no RPGs, Mortars or GLs) to a piece of tripwire. You will need the newest xmls for that. o You can plant the tripwire as you usually do. o Once activated, the gun that is attached to the wire will fire once. It will fire in the direction that you planted the bomb, just like claymore mines do (the direction that the merc planting the wire was looking). o The bullet fired has the range and damage it would have if fired from the gun. o The gun correctly heats, jams, degrades and whatever else guns do when fired. If the gun is jammed, not pumped (pumpguns) or does not have ammo, it will not fire. o After firing, the gun lies on the floor, just where the trp was planted. o This can be applied to any tripwire. You can ave multiple of these traps. Just put them into your normal trap setup however you like. o At the moment, only single shots are possible, even for guns that do not have a single shot mode (MG3 etc.) o Although I did not experience any problems with attachments, it might be a good idea to take any attachments off a gun if you attach it to tripwire. o When the gun is attached, it is possible to attach gun attachments (lasers, scopes etc.) to the explosive. Do not attach any attachments to the explosive. They will be lost if the wire is activated. o see: http://www.bears-pit.com/board/ubbthreads.php/topics/305634.html#Post305634 -> To support this feature, some (already existing) xml-tags have been added to the weapons in Data-1.13\TableData\Items.xml (<nasAttachmentClass>, <AttachmentPoint>, <AttachToPointAPCost>, <Attachment>) git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@5331 3b4a5df2-a311-0410-b5c6-a8a6f20db521
1241 lines
34 KiB
C++
1241 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 if ( bMines == MINE_BOMB_AND_WIRE )
|
|
;
|
|
else
|
|
{
|
|
// check if the tripwire has a gun attached
|
|
BOOLEAN fgunfound = FALSE;
|
|
attachmentList::iterator iterend = (*pObj)[0]->attachments.end();
|
|
for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != iterend; ++iter)
|
|
{
|
|
if ( iter->exists() && Item[iter->usItem].usItemClass == IC_GUN )
|
|
{
|
|
fgunfound = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ( fgunfound )
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|