New Feature: Layered hierarchical tripwire networks (by Flugente)

- 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
This commit is contained in:
Wanne
2012-04-20 10:40:16 +00:00
parent ee2196ebb4
commit 20d677c519
28 changed files with 1012 additions and 197 deletions
+219 -40
View File
@@ -60,6 +60,10 @@ enum MINES_VALUES
MINES_NET_2,
MINES_NET_3,
MINES_NET_4,
MINES_LVL_1,
MINES_LVL_2,
MINES_LVL_3,
MINES_LVL_4,
MAX_MINES
};
@@ -93,8 +97,14 @@ const UINT8 animArr[3] = {
// 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_DETECT_ENEMY
MINES_DRAW_NETWORKCOLOURING,
MINES_DRAW_NET_A,
MINES_DRAW_NET_B,
MINES_DRAW_NET_C,
MINES_DRAW_NET_D,
MINES_DRAW_MAX
};
//****** Local Variables *********************************************
@@ -701,7 +711,7 @@ void SwitchToHostileTrapsView()
return;
gubDrawModeMine = MINES_DRAW_DETECT_ENEMY;
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Display hostile traps");
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Display nearby traps");
DisplayMines(TRUE);
}
@@ -711,7 +721,7 @@ void SwitchMineViewOff()
return;
gubDrawModeMine = MINES_DRAW_OFF;
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Turning off Mines display");
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Turning off trap display");
DisplayMines(TRUE);
}
@@ -726,16 +736,60 @@ void ToggleHostileTrapsView()
void ToggleTrapNetworkView()
{
if (gubDrawModeMine == MINES_DRAW_PLAYERTEAM_NETWORKS) {
SwitchMinesDrawModeForNetworks();
/*if (gubDrawModeMine == MINES_DRAW_PLAYERTEAM_NETWORKS) {
SwitchMineViewOff();
} else {
SwitchToTrapNetworkView();
}
}*/
}
void SwitchMinesDrawMode()
void SwitchMinesDrawModeForNetworks()
{
switch(gubDrawModeMine)
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();
@@ -746,7 +800,7 @@ void SwitchMinesDrawMode()
default:
SwitchMineViewOff();
break;
}
}*/
}
///END key binding functions
@@ -757,14 +811,18 @@ TileDefines GetTileMinesIndex( const INT8& 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 MINE_BOMB_AND_WIRE:
case MINES_LVL_3:
return SPECIALTILE_COVER_2; // orange
case MINES_NET_3:
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:
@@ -774,6 +832,10 @@ TileDefines GetTileMinesIndex( const INT8& bMines )
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 )
@@ -910,19 +972,12 @@ void CalculateMines()
GetSoldier( &pSoldier, gusSelectedSoldier );
// this stuff will be needed once a ranged mine detector is implemented, for the moment comment this out
// 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 ( (&(pSoldier->inv[HANDPOS] ))->exists() && Item[pSoldier->inv[HANDPOS].usItem].metaldetector== 1 )
{
if ( FindMetalDetectorInHand(pSoldier) )
fWithMineDetector = TRUE;
}
else if ( (&(pSoldier->inv[SECONDHANDPOS] ))->exists() && Item[pSoldier->inv[SECONDHANDPOS].usItem].metaldetector== 1 )
{
fWithMineDetector = TRUE;
}
// TODO: perhaps even consume batteries one day...
}
@@ -1005,37 +1060,161 @@ void DetermineMineDisplayInTile( INT32 sGridNo, INT8 bLevel, INT8& bMines, BOOLE
// we are looking for hostile mines and have got an detector equipped
if ( gubDrawModeMine == MINES_DRAW_DETECT_ENEMY && fWithMineDetector )
{
// look for hostile mines
//if ( ((*pObj)[0]->data.misc.ubBombOwner < 2) )
{
bMines = MINE_BOMB;
}
// display all mines
bMines = MINE_BOMB;
}
else
{
// look for mines from our own team
if ( (gubDrawModeMine == MINES_DRAW_PLAYERTEAM_NETWORKS) && ((*pObj)[0]->data.misc.ubBombOwner > 1) )
if ( (*pObj)[0]->data.misc.ubBombOwner > 1 )
{
if ( Item[pObj->usItem].tripwire == 1 )
switch ( gubDrawModeMine )
{
// 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;
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;
}
}
}
// TODO: determine correct trap network
}
}
}
+1 -1
View File
@@ -47,6 +47,6 @@ void SwitchMineViewOff();
void ToggleTrapNetworkView();
void ToggleHostileTrapsView();
void SwitchMinesDrawMode();
void SwitchMinesDrawModeForNetworks();
#endif
+81 -18
View File
@@ -1228,7 +1228,7 @@ INT32 HandleItem( SOLDIERTYPE *pSoldier, INT32 sGridNo, INT8 bLevel, UINT16 usHa
if ( Item[ usHandItem ].ubCursor == INVALIDCURS )
{
// Found detonator...
if ( IsDetonatorAttached( &(pSoldier->inv[ pSoldier->ubAttackingHand ] ) ) || IsRemoteDetonatorAttached( &(pSoldier->inv[ pSoldier->ubAttackingHand ] ) ) )
if ( HasAttachmentOfClass( &(pSoldier->inv[ pSoldier->ubAttackingHand ] ), (AC_DETONATOR | AC_REMOTEDET | AC_DEFUSE) ) )
{
fDropBomb = TRUE;
}
@@ -1462,7 +1462,7 @@ INT32 HandleItem( SOLDIERTYPE *pSoldier, INT32 sGridNo, INT8 bLevel, UINT16 usHa
if ( Item[ usHandItem ].ubCursor == INVALIDCURS )
{
// Found detonator...
if ( IsDetonatorAttached ( &(pSoldier->inv[ usHandItem ] ) ) || IsRemoteDetonatorAttached( &(pSoldier->inv[ usHandItem ] ) ) )
if ( HasAttachmentOfClass( &(pSoldier->inv[ usHandItem ] ), (AC_DETONATOR | AC_REMOTEDET | AC_DEFUSE) ) || Item[ (&(pSoldier->inv[ usHandItem ] ))->usItem ].tripwire == 1 )
{
StartBombMessageBox( pSoldier, sGridNo );
@@ -1482,7 +1482,7 @@ INT32 HandleItem( SOLDIERTYPE *pSoldier, INT32 sGridNo, INT8 bLevel, UINT16 usHa
void HandleSoldierDropBomb( SOLDIERTYPE *pSoldier, INT32 sGridNo )
{
// Does this have detonator that needs info?
if ( IsDetonatorAttached ( &(pSoldier->inv[ HANDPOS ] ) ) || IsRemoteDetonatorAttached( &(pSoldier->inv[ HANDPOS ] ) ) )
if ( HasAttachmentOfClass( &(pSoldier->inv[ HANDPOS ] ), (AC_DETONATOR | AC_REMOTEDET | AC_DEFUSE) ) || Item[ (&(pSoldier->inv[ HANDPOS ] ))->usItem ].tripwire == 1)
{
StartBombMessageBox( pSoldier, sGridNo );
}
@@ -1515,6 +1515,13 @@ void HandleSoldierDropBomb( SOLDIERTYPE *pSoldier, INT32 sGridNo )
}
pSoldier->inv[ HANDPOS ][0]->data.misc.ubBombOwner = pSoldier->ubID + 2;
// Flugente: determine the direction we are looking at and apply that direction to our explosive
pSoldier->inv[ HANDPOS ][0]->data.ubDirection = pSoldier->ubDirection;
// no frequency known... give a default value, so we don't defuse it by accident
gTempObject[0]->data.ubWireNetworkFlag = ENEMY_NET_1_LVL_1;
gTempObject[0]->data.bDefuseFrequency = 0;
// we now know there is something nasty here
gpWorldLevelData[ sGridNo ].uiFlags |= MAPELEMENT_PLAYER_MINE_PRESENT;
@@ -1531,7 +1538,7 @@ void HandleSoldierDropBomb( SOLDIERTYPE *pSoldier, INT32 sGridNo )
if ( iResult < -20 && Item[ pSoldier->inv[ HANDPOS ].usItem ].tripwire != 1 )
{
// OOPS! ... BOOM!
IgniteExplosion( NOBODY, pSoldier->sX, pSoldier->sY, (INT16) (gpWorldLevelData[pSoldier->sGridNo].sHeight), pSoldier->sGridNo, pSoldier->inv[ HANDPOS ].usItem, pSoldier->pathing.bLevel );
IgniteExplosion( NOBODY, pSoldier->sX, pSoldier->sY, (INT16) (gpWorldLevelData[pSoldier->sGridNo].sHeight), pSoldier->sGridNo, pSoldier->inv[ HANDPOS ].usItem, pSoldier->pathing.bLevel, pSoldier->ubDirection );
pSoldier->inv[ HANDPOS ].MoveThisObjectTo(gTempObject, 1);
}
}
@@ -1939,8 +1946,19 @@ void SoldierGetItemFromWorld( SOLDIERTYPE *pSoldier, INT32 iItemIndex, INT32 sGr
// REMOVE ITEM FROM POOL
if ( ItemExistsAtLocation( sGridNo, iItemIndex, pSoldier->pathing.bLevel ) )
{
// Flugente: if item is tripwireactivated and is a planted bomb, call the defuse dialogue. We obviously know about the items' existence already...
if ( gWorldItems[ iItemIndex ].object.exists() && gWorldItems[ iItemIndex ].object.fFlags & OBJECT_ARMED_BOMB && Item[gWorldItems[ iItemIndex ].object.usItem].tripwireactivation == 1 )
{
gpBoobyTrapItemPool = GetItemPoolForIndex( sGridNo, iItemIndex, pSoldier->pathing.bLevel );
gpBoobyTrapSoldier = pSoldier;
gsBoobyTrapGridNo = sGridNo;
gbBoobyTrapLevel = pSoldier->pathing.bLevel;
gfDisarmingBuriedBomb = FALSE;
gbTrapDifficulty = (gWorldItems[ iItemIndex ].object)[0]->data.bTrap;
if ( ContinuePastBoobyTrap( pSoldier, sGridNo, bZLevel, iItemIndex, FALSE, &fSaidBoobyTrapQuote ) )
DoMessageBox( MSG_BOX_BASIC_STYLE, TacticalStr[ DISARM_BOOBYTRAP_PROMPT ], GAME_SCREEN, ( UINT8 )MSG_BOX_FLAG_YESNO, BoobyTrapMessageBoxCallBack, NULL );
}
else if ( ContinuePastBoobyTrap( pSoldier, sGridNo, bZLevel, iItemIndex, FALSE, &fSaidBoobyTrapQuote ) )
{
if ( ItemIsCool( &gWorldItems[ iItemIndex ].object ) )
{
@@ -4313,7 +4331,7 @@ void StartBombMessageBox( SOLDIERTYPE * pSoldier, INT32 sGridNo )
gsTempGridNo = sGridNo;
if (Item[ pSoldier->inv[HANDPOS].usItem].remotetrigger )
{
DoMessageBox( MSG_BOX_BASIC_SMALL_BUTTONS, TacticalStr[ CHOOSE_BOMB_FREQUENCY_STR ], GAME_SCREEN, ( UINT8 )MSG_BOX_FLAG_FOUR_NUMBERED_BUTTONS, BombMessageBoxCallBack, NULL );
DoMessageBox( MSG_BOX_BASIC_SMALL_BUTTONS, TacticalStr[ CHOOSE_BOMB_OR_DEFUSE_FREQUENCY_STR ], GAME_SCREEN, MSG_BOX_FLAG_EIGHT_NUMBERED_BUTTONS, BombMessageBoxCallBack, NULL );
}
else if (pSoldier->inv[HANDPOS].usItem == REMOTETRIGGER)
{
@@ -4351,13 +4369,32 @@ void StartBombMessageBox( SOLDIERTYPE * pSoldier, INT32 sGridNo )
pSoldier->DoMercBattleSound( BATTLE_SOUND_CURSE1 );
}
}
else if ( IsDetonatorAttached ( &(pSoldier->inv[HANDPOS]) ) )
else if ( HasAttachmentOfClass( &(pSoldier->inv[HANDPOS]), AC_DEFUSE ) )
{
DoMessageBox( MSG_BOX_BASIC_SMALL_BUTTONS, TacticalStr[ CHOOSE_TIMER_STR ], GAME_SCREEN, ( UINT8 )MSG_BOX_FLAG_FOUR_NUMBERED_BUTTONS, BombMessageBoxCallBack, NULL );
if ( HasAttachmentOfClass( &(pSoldier->inv[ HANDPOS ] ), (AC_DETONATOR ) ) )
{
DoMessageBox( MSG_BOX_BASIC_SMALL_BUTTONS, TacticalStr[ CHOOSE_DETONATE_AND_REMOTE_DEFUSE_FREQUENCY_STR ], GAME_SCREEN, MSG_BOX_FLAG_SIXTEEN_NUMBERED_BUTTONS, BombMessageBoxCallBack, NULL );
}
else if ( HasAttachmentOfClass( &(pSoldier->inv[ HANDPOS ] ), (AC_REMOTEDET) ) )
{
DoMessageBox( MSG_BOX_BASIC_SMALL_BUTTONS, TacticalStr[ CHOOSE_REMOTE_DETONATE_AND_REMOTE_DEFUSE_FREQUENCY_STR ], GAME_SCREEN, MSG_BOX_FLAG_SIXTEEN_NUMBERED_BUTTONS, BombMessageBoxCallBack, NULL );
}
else
{
DoMessageBox( MSG_BOX_BASIC_SMALL_BUTTONS, TacticalStr[ CHOOSE_REMOTE_DEFUSE_FREQUENCY_STR ], GAME_SCREEN, MSG_BOX_FLAG_FOUR_NUMBERED_BUTTONS, BombMessageBoxCallBack, NULL );
}
}
else if ( IsRemoteDetonatorAttached( &(pSoldier->inv[HANDPOS]) ) )
else if ( HasAttachmentOfClass( &(pSoldier->inv[ HANDPOS ] ), (AC_DETONATOR ) ) )
{
DoMessageBox( MSG_BOX_BASIC_SMALL_BUTTONS, TacticalStr[ CHOOSE_REMOTE_FREQUENCY_STR ], GAME_SCREEN, ( UINT8 )MSG_BOX_FLAG_FOUR_NUMBERED_BUTTONS, BombMessageBoxCallBack, NULL );
DoMessageBox( MSG_BOX_BASIC_SMALL_BUTTONS, TacticalStr[ CHOOSE_TIMER_STR ], GAME_SCREEN, MSG_BOX_FLAG_FOUR_NUMBERED_BUTTONS, BombMessageBoxCallBack, NULL );
}
else if ( HasAttachmentOfClass( &(pSoldier->inv[ HANDPOS ] ), (AC_REMOTEDET) ) )
{
DoMessageBox( MSG_BOX_BASIC_SMALL_BUTTONS, TacticalStr[ CHOOSE_REMOTE_FREQUENCY_STR ], GAME_SCREEN, MSG_BOX_FLAG_FOUR_NUMBERED_BUTTONS, BombMessageBoxCallBack, NULL );
}
else if ( Item[ (&(pSoldier->inv[HANDPOS]))->usItem ].tripwire == 1 )
{
DoMessageBox( MSG_BOX_BASIC_SMALL_BUTTONS, TacticalStr[ CHOOSE_TRIPWIRE_NETWORK ], GAME_SCREEN, MSG_BOX_FLAG_SIXTEEN_NUMBERED_BUTTONS, BombMessageBoxCallBack, NULL );
}
}
@@ -4372,8 +4409,8 @@ void BombMessageBoxCallBack( UINT8 ubExitValue )
else
{
INT32 iResult;
if (IsRemoteDetonatorAttached( &(gpTempSoldier->inv[HANDPOS]) ) )
if ( HasAttachmentOfClass( &(gpTempSoldier->inv[HANDPOS]), AC_REMOTEDET ) )
{
iResult = SkillCheck( gpTempSoldier, PLANTING_REMOTE_BOMB_CHECK, 0 );
}
@@ -4413,10 +4450,11 @@ void BombMessageBoxCallBack( UINT8 ubExitValue )
}
else
{
// we can't blow up tripwire, no matter how bad we fail
if ( Item[ gpTempSoldier->inv[ HANDPOS ].usItem ].tripwire != 1 )
{
// OOPS! ... BOOM!
IgniteExplosion( NOBODY, gpTempSoldier->sX, gpTempSoldier->sY, (INT16) (gpWorldLevelData[gpTempSoldier->sGridNo].sHeight), gpTempSoldier->sGridNo, gpTempSoldier->inv[ HANDPOS ].usItem, gpTempSoldier->pathing.bLevel );
IgniteExplosion( NOBODY, gpTempSoldier->sX, gpTempSoldier->sY, (INT16) (gpWorldLevelData[gpTempSoldier->sGridNo].sHeight), gpTempSoldier->sGridNo, gpTempSoldier->inv[ HANDPOS ].usItem, gpTempSoldier->pathing.bLevel, gpTempSoldier->ubDirection );
}
return;
@@ -4439,9 +4477,16 @@ void BombMessageBoxCallBack( UINT8 ubExitValue )
// HACK IMMINENT!
// value of 1 is stored in maps for SIDE of bomb owner... when we want to use IDs!
// so we add 2 to all owner IDs passed through here and subtract 2 later
if (gpTempSoldier->inv[HANDPOS].MoveThisObjectTo(gTempObject, 1) == 0) {
if (gpTempSoldier->inv[HANDPOS].MoveThisObjectTo(gTempObject, 1) == 0)
{
gTempObject[0]->data.misc.ubBombOwner = gpTempSoldier->ubID + 2;
AddItemToPool( gsTempGridNo, &gTempObject, 1, gpTempSoldier->pathing.bLevel, WORLD_ITEM_ARMED_BOMB, 0 );
gTempObject[0]->data.ubDirection = gpTempSoldier->ubDirection; // Flugente: direction of bomb is direction of soldier
// Flugente: tripwire was called through a messagebox, but has to be buried nevertheless
if ( Item[ (&gTempObject)->usItem ].tripwire == 1 )
AddItemToPool( gsTempGridNo, &gTempObject, BURIED, gpTempSoldier->pathing.bLevel, WORLD_ITEM_ARMED_BOMB, 0 );
else
AddItemToPool( gsTempGridNo, &gTempObject, VISIBLE, gpTempSoldier->pathing.bLevel, WORLD_ITEM_ARMED_BOMB, 0 );
}
}
}
@@ -4681,15 +4726,28 @@ void BoobyTrapMessageBoxCallBack( UINT8 ubExitValue )
// owner - 2 gives the ID of the character who planted it
if ( gTempObject[0]->data.misc.ubBombOwner > 1 && ( (INT32)gTempObject[0]->data.misc.ubBombOwner - 2 >= gTacticalStatus.Team[ OUR_TEAM ].bFirstID && gTempObject[0]->data.misc.ubBombOwner - 2 <= gTacticalStatus.Team[ OUR_TEAM ].bLastID ) )
{
// Flugente: get a tripwire-related bonus if we have a wire cutter in our hands
INT8 wirecutterbonus = 0;
if ( ( (&gpBoobyTrapSoldier->inv[HANDPOS])->exists() && Item[ gpBoobyTrapSoldier->inv[HANDPOS].usItem ].wirecutters == 1 ) || ( (&gpBoobyTrapSoldier->inv[SECONDHANDPOS])->exists() && Item[ gpBoobyTrapSoldier->inv[SECONDHANDPOS].usItem ].wirecutters == 1 ) )
{
// + 10 if item gets activated by tripwire
if ( Item[gTempObject.usItem].tripwireactivation == 1 )
wirecutterbonus += 10;
// + 10 if item is tripwire
if ( Item[gTempObject.usItem].tripwire == 1 )
wirecutterbonus += 10;
}
if ( gTempObject[0]->data.misc.ubBombOwner - 2 == gpBoobyTrapSoldier->ubID )
{
// my own boobytrap!
iCheckResult = SkillCheck( gpBoobyTrapSoldier, DISARM_TRAP_CHECK, 40 );
iCheckResult = SkillCheck( gpBoobyTrapSoldier, DISARM_TRAP_CHECK, 40 + wirecutterbonus );
}
else
{
// our team's boobytrap!
iCheckResult = SkillCheck( gpBoobyTrapSoldier, DISARM_TRAP_CHECK, 20 );
iCheckResult = SkillCheck( gpBoobyTrapSoldier, DISARM_TRAP_CHECK, 20 + wirecutterbonus );
}
}
else
@@ -4977,7 +5035,12 @@ BOOLEAN NearbyGroundSeemsWrong( SOLDIERTYPE * pSoldier, INT32 sGridNo, BOOLEAN f
ubDetectLevel = 0;
if ( FindMetalDetector( pSoldier ) != NO_SLOT )
// Flugente: changed the way the metal detector works: now it detects mines only when it is used in hands, not if it is anywhere in the inventory.
// Reason: with the new tripwire functionality and th new ability of a detector to spot mines several tiles away the detector s more useful.
// However, the most likely persons to use it (explosive experts) are also those that plant those networks. They will often have a detector in their inventory.
// If the detector just works if its in inventory, they autoflag the mines they are laying, which is bad.
// With this change, a detector must be in order to work.
if ( FindMetalDetectorInHand( pSoldier ) != NO_SLOT )
{
fMining = TRUE;
}
+13
View File
@@ -1024,7 +1024,12 @@ ObjectData::ObjectData(const ObjectData& src)
this->bTrap = src.bTrap;
this->fUsed = src.fUsed;
this->ubImprintID = src.ubImprintID;
this->bTemperature = src.bTemperature;
this->ubDirection = src.ubDirection;
this->ubWireNetworkFlag = src.ubWireNetworkFlag;
this->bDefuseFrequency = src.bDefuseFrequency;
//copy over the union
this->gun = src.gun;
@@ -1043,7 +1048,12 @@ ObjectData& ObjectData::operator =(const ObjectData& src)
this->bTrap = src.bTrap;
this->fUsed = src.fUsed;
this->ubImprintID = src.ubImprintID;
this->bTemperature = src.bTemperature;
this->ubDirection = src.ubDirection;
this->ubWireNetworkFlag = src.ubWireNetworkFlag;
this->bDefuseFrequency = src.bDefuseFrequency;
//copy over the union
this->gun = src.gun;
@@ -1300,6 +1310,9 @@ OBJECTTYPE& OBJECTTYPE::operator=(const OLD_OBJECTTYPE_101& src)
(*this)[0]->data.misc.ubBombOwner = src.ugYucky.ubBombOwner;
(*this)[0]->data.misc.bActionValue = src.ugYucky.bActionValue;
(*this)[0]->data.misc.ubTolerance = src.ugYucky.ubTolerance; // includes ubLocationID
(*this)[0]->data.ubDirection = DIRECTION_IRRELEVANT;
(*this)[0]->data.ubWireNetworkFlag = ENEMY_NET_1_LVL_1;
(*this)[0]->data.bDefuseFrequency = 0;
break;
default:
//This should cover all other possibilities since only Money, Key and "Bomb/Misc" have layouts that don't
+50
View File
@@ -466,7 +466,14 @@ public:
// New values, like bTemperature, have to come after this. And please, don't destroy ObjectData's POD-ness.
char endOfPOD;
// these variables should belong to a different position. However, I am forced to put them here, otherwise loading of WF maps and other old data would not work properly
FLOAT bTemperature; // Flugente FTW 1.2: temperature of gun
// shoul belong to misc, but was moved here because of the odl maps issue
// added by Flugente 12-04-15
UINT8 ubDirection; // direction the bomb faces (for directional explosives)
UINT32 ubWireNetworkFlag; // flags for the tripwire network
INT8 bDefuseFrequency; // frequency for defusing, >=0 values used only
};
// Flugente: needed for reading WF maps
#define SIZEOF_OBJECTDATA_POD (offsetof(ObjectData, endOfPOD))
@@ -655,6 +662,48 @@ extern OBJECTTYPE gTempObject;
#define AC_MISC19 0x40000000 //1073741824
#define AC_MISC20 0x80000000 //2147483648
// -------- added by Flugente: flags for tripwire networks --------
// the numbering of these flags is important. DO NOT CHANGE THEM, UNLESS YOU KNOW WHAT YOU ARE DOING!!!
#define ENEMY_NET_1_LVL_1 0x00000001 //1
#define ENEMY_NET_2_LVL_1 0x00000002 //2
#define ENEMY_NET_3_LVL_1 0x00000004 //4
#define ENEMY_NET_4_LVL_1 0x00000008 //8
#define ENEMY_NET_1_LVL_2 0x00000010 //16
#define ENEMY_NET_2_LVL_2 0x00000020 //32
#define ENEMY_NET_3_LVL_2 0x00000040 //64
#define ENEMY_NET_4_LVL_2 0x00000080 //128
#define ENEMY_NET_1_LVL_3 0x00000100 //256
#define ENEMY_NET_2_LVL_3 0x00000200 //512
#define ENEMY_NET_3_LVL_3 0x00000400 //1024
#define ENEMY_NET_4_LVL_3 0x00000800 //2048
#define ENEMY_NET_1_LVL_4 0x00001000 //4096
#define ENEMY_NET_2_LVL_4 0x00002000 //8192
#define ENEMY_NET_3_LVL_4 0x00004000 //16384
#define ENEMY_NET_4_LVL_4 0x00008000 //32768
#define PLAYER_NET_1_LVL_1 0x00010000 //65536
#define PLAYER_NET_2_LVL_1 0x00020000 //131072
#define PLAYER_NET_3_LVL_1 0x00040000 //262144
#define PLAYER_NET_4_LVL_1 0x00080000 //524288
#define PLAYER_NET_1_LVL_2 0x00100000 //1048576
#define PLAYER_NET_2_LVL_2 0x00200000 //2097152
#define PLAYER_NET_3_LVL_2 0x00400000 //4194304
#define PLAYER_NET_4_LVL_2 0x00800000 //8388608
#define PLAYER_NET_1_LVL_3 0x01000000 //16777216
#define PLAYER_NET_2_LVL_3 0x02000000 //33554432
#define PLAYER_NET_3_LVL_3 0x04000000 //67108864
#define PLAYER_NET_4_LVL_3 0x08000000 //134217728
#define PLAYER_NET_1_LVL_4 0x10000000 //268435456
#define PLAYER_NET_2_LVL_4 0x20000000 //536870912
#define PLAYER_NET_3_LVL_4 0x40000000 //1073741824
#define PLAYER_NET_4_LVL_4 0x80000000 //2147483648
// ----------------------------------------------------------------
// replaces candamage
//#define ITEM_DAMAGEABLE 0x0001
@@ -893,6 +942,7 @@ typedef struct
BOOLEAN tripwireactivation; // item (mine) can be activated by nearby tripwire
BOOLEAN tripwire; // item is tripwire
BOOLEAN directional; // item is a directional mine/bomb (actual direction is set upon planting)
} INVTYPE;
+89 -23
View File
@@ -1590,17 +1590,18 @@ INT8 FindBestWeaponIfCurrentIsOutOfRange(SOLDIERTYPE * pSoldier, INT8 bCurrentWe
return( bCurrentWeaponIndex );
}
INT8 FindMetalDetector( SOLDIERTYPE * pSoldier )
INT8 FindMetalDetectorInHand( SOLDIERTYPE * pSoldier )
{
INT8 bLoop;
for (bLoop = 0; bLoop < (INT8) pSoldier->inv.size(); bLoop++)
if ( (&(pSoldier->inv[HANDPOS] ))->exists() && Item[pSoldier->inv[HANDPOS].usItem].metaldetector )
{
if (Item[pSoldier->inv[bLoop].usItem].metaldetector && pSoldier->inv[bLoop].exists() == true)
{
return( bLoop );
}
return( HANDPOS );
}
if ( (&(pSoldier->inv[SECONDHANDPOS] ))->exists() && Item[pSoldier->inv[SECONDHANDPOS].usItem].metaldetector )
{
return( SECONDHANDPOS );
}
return( NO_SLOT );
}
@@ -7345,6 +7346,12 @@ BOOLEAN ArmBomb( OBJECTTYPE * pObj, INT8 bSetting )
BOOLEAN fPressure = FALSE;
BOOLEAN fTimed = FALSE;
BOOLEAN fSwitch = FALSE;
BOOLEAN fDefuse = FALSE; // bomb can be defused remotely
if ( HasAttachmentOfClass( pObj, AC_DEFUSE) )
{
fDefuse = TRUE;
}
if (pObj->usItem == ACTION_ITEM)
{
@@ -7360,11 +7367,11 @@ BOOLEAN ArmBomb( OBJECTTYPE * pObj, INT8 bSetting )
}
}
else if ( IsDetonatorAttached( pObj ) )
else if ( HasAttachmentOfClass( pObj, AC_DETONATOR ) )
{
fTimed = TRUE;
}
else if ( (IsRemoteDetonatorAttached( pObj ) ) || (pObj->usItem == ACTION_ITEM) )
else if ( HasAttachmentOfClass( pObj, (AC_REMOTEDET | AC_DEFUSE) ) || (pObj->usItem == ACTION_ITEM) )
{
fRemote = TRUE;
}
@@ -7392,22 +7399,74 @@ BOOLEAN ArmBomb( OBJECTTYPE * pObj, INT8 bSetting )
return( FALSE );
}
// Flugente TODO determine correct frequency and detonate/defuse stuff
// Flugente: decide how to interpret the bSetting we just got.
// Due to limitations in the message system, we only receive a single value to interpret, as we currently can't have a message box return 2 values
// It might be possible to have proper checkboxes, but I'll rather not research this right now.
// The remote defuse complicates things, as you'll see:
//
// If we are placing a bomb or mine (so no tripwire), consider the following:
// a) if we have a timed detonator: time in turns until she blows': 1-4
// b) if we have a remote detonator: frequency on which the bomb will blow: 1-4
// c) if we have a timed detonator plus a remote defuse: time in turns until she blows plus frequency to defuse: 1-16
// d) if we have a remote detonator plus a remote defuse: frequency on which the bomb will blow plus frequency to defuse: 1-16
//
// I we are placing tripwire, consider this:
// e) if we palce tripwire: the tripwire network plus the hierachy in that network: 1-16
//
// It is clear that we only have to reinterpret the values if a defuse is equiped, or we are placing tripwire
INT8 detonatesetting = bSetting;
INT8 defusesetting = bSetting;
if ( fDefuse && bSetting > 0 && bSetting < 17 ) // checks for safety
{
// the bSetting consists of the 4 * (detonation frequency - 1) + defuse frequency
detonatesetting = 1;
defusesetting = bSetting % 4;
if ( defusesetting == 0 )
defusesetting = 4;
INT8 tmp = bSetting - defusesetting; // now 0, 4, 8 or 12
if ( tmp > 0 ) ++detonatesetting;
if ( tmp > 4 ) ++detonatesetting;
if ( tmp > 8 ) ++detonatesetting; // defusesetting is now in 1-4
}
// tripwires
UINT32 ubWireNetworkFlag = 0;
if ( Item[pObj->usItem].tripwire == 1 && bSetting > 0 && bSetting < 17 ) // checks for safety
{
// the bSetting consists of the network number + 4 * (network hierarchy - 1)
// account for placement by the enemy
INT8 editoradj = 16;
//if ( editor ) editoradj = 0; or something like that
ubWireNetworkFlag = 1 << (editoradj - 1 + bSetting);
}
if (fDefuse) // TODO: doesn't work this way if both a detonator and a remote defuse is attached...
{
(*pObj)[0]->data.misc.bDetonatorType = BOMB_REMOTE;
(*pObj)[0]->data.bDefuseFrequency = defusesetting;
}
if (fRemote)
{
(*pObj)[0]->data.misc.bDetonatorType = BOMB_REMOTE;
(*pObj)[0]->data.misc.bFrequency = bSetting;
(*pObj)[0]->data.misc.bFrequency = detonatesetting;
}
else if (fPressure)
{
(*pObj)[0]->data.misc.bDetonatorType = BOMB_PRESSURE;
(*pObj)[0]->data.misc.bFrequency = 0;
(*pObj)[0]->data.ubWireNetworkFlag = ubWireNetworkFlag;
}
else if (fTimed)
{
(*pObj)[0]->data.misc.bDetonatorType = BOMB_TIMED;
// In realtime the player could choose to put down a bomb right before a turn expires, SO
// add 1 to the setting in RT
(*pObj)[0]->data.misc.bDelay = bSetting;
(*pObj)[0]->data.misc.bDelay = detonatesetting;
if ( !(gTacticalStatus.uiFlags & TURNBASED && gTacticalStatus.uiFlags & INCOMBAT) )
{
(*pObj)[0]->data.misc.bDelay++;
@@ -7417,13 +7476,17 @@ BOOLEAN ArmBomb( OBJECTTYPE * pObj, INT8 bSetting )
else if (fSwitch)
{
(*pObj)[0]->data.misc.bDetonatorType = BOMB_SWITCH;
(*pObj)[0]->data.misc.bFrequency = bSetting;
(*pObj)[0]->data.misc.bFrequency = detonatesetting;
}
else
{
return( FALSE );
}
// for safety, weird things happen
if ( (*pObj).fFlags & OBJECT_DISABLED_BOMB )
(*pObj).fFlags &= ~(OBJECT_DISABLED_BOMB);
(*pObj).fFlags |= OBJECT_ARMED_BOMB;
(*pObj)[0]->data.misc.usBombItem = pObj->usItem;
return( TRUE );
@@ -7997,11 +8060,11 @@ void CheckEquipmentForDamage( SOLDIERTYPE *pSoldier, INT32 iDamage )
// blow it up!
if ( gTacticalStatus.ubAttackBusyCount )
{
IgniteExplosion( pSoldier->ubAttackerID, CenterX( pSoldier->sGridNo ), CenterY( pSoldier->sGridNo ), 0, pSoldier->sGridNo, pSoldier->inv[ bSlot ].usItem, pSoldier->pathing.bLevel );
IgniteExplosion( pSoldier->ubAttackerID, CenterX( pSoldier->sGridNo ), CenterY( pSoldier->sGridNo ), 0, pSoldier->sGridNo, pSoldier->inv[ bSlot ].usItem, pSoldier->pathing.bLevel, pSoldier->ubDirection );
}
else
{
IgniteExplosion( pSoldier->ubID, CenterX( pSoldier->sGridNo ), CenterY( pSoldier->sGridNo ), 0, pSoldier->sGridNo, pSoldier->inv[ bSlot ].usItem, pSoldier->pathing.bLevel );
IgniteExplosion( pSoldier->ubID, CenterX( pSoldier->sGridNo ), CenterY( pSoldier->sGridNo ), 0, pSoldier->sGridNo, pSoldier->inv[ bSlot ].usItem, pSoldier->pathing.bLevel, pSoldier->ubDirection );
}
//ADB when something in a stack blows up the whole stack goes, so no need to worry about number of items
@@ -8066,7 +8129,7 @@ BOOLEAN DamageItemOnGround( OBJECTTYPE * pObject, INT32 sGridNo, INT8 bLevel, IN
if ( fBlowsUp )
{
// OK, Ignite this explosion!
IgniteExplosion( ubOwner, CenterX( sGridNo ), CenterY( sGridNo ), 0, sGridNo, pObject->usItem, bLevel );
IgniteExplosion( ubOwner, CenterX( sGridNo ), CenterY( sGridNo ), 0, sGridNo, pObject->usItem, bLevel, DIRECTION_IRRELEVANT );
// SANDRO - merc records
if ( (pObject->fFlags & OBJECT_ARMED_BOMB) && ((*pObject)[0]->data.misc.ubBombOwner > 1) )
@@ -12605,8 +12668,8 @@ INT32 GetGunAccuracy( OBJECTTYPE *pObj )
if ( gGameOptions.fWeaponOverheating )
{
FLOAT overheatdamagepercentage = GetGunOverheatDamagePercentage( pObj );
FLOAT accuracymalus = (max(1.0, overheatdamagepercentage) - 1.0) * 0.1;
accuracyheatmultiplicator = max(0.0, 1.0 - accuracymalus);
FLOAT accuracymalus = (max((FLOAT)1.0, overheatdamagepercentage) - (FLOAT)1.0) * 0.1;
accuracyheatmultiplicator = max((FLOAT)0.0, (FLOAT)1.0 - accuracymalus);
}
if(UsingNewCTHSystem() == false)
@@ -13022,12 +13085,15 @@ BOOLEAN IsAttachmentClass( UINT16 usItem, UINT32 aFlag )
BOOLEAN HasAttachmentOfClass( OBJECTTYPE * pObj, UINT32 aFlag )
{
// check all attachments
attachmentList::iterator iterend = (*pObj)[0]->attachments.end();
for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != iterend; ++iter)
if ( pObj->exists() )
{
if ( iter->exists() && IsAttachmentClass( iter->usItem, aFlag ) )
return( TRUE );
// check all attachments
attachmentList::iterator iterend = (*pObj)[0]->attachments.end();
for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != iterend; ++iter)
{
if ( iter->exists() && IsAttachmentClass( iter->usItem, aFlag ) )
return( TRUE );
}
}
return( FALSE );
+3 -3
View File
@@ -374,12 +374,12 @@ INT16 GetAttachedArmourBonus( OBJECTTYPE * pObj );
INT16 GetBulletSpeedBonus( OBJECTTYPE * pObj );
INT8 FindGasMask( SOLDIERTYPE * pSoldier );
INT8 FindLockBomb( SOLDIERTYPE * pSoldier );
INT8 FindMetalDetector( SOLDIERTYPE * pSoldier );
INT8 FindMetalDetectorInHand( SOLDIERTYPE * pSoldier ); // Flugente: changed, now only works if detector is in hands
INT8 FindCannon( SOLDIERTYPE * pSoldier );
INT8 FindUsableCrowbar( SOLDIERTYPE * pSoldier );
INT8 FindToolkit( SOLDIERTYPE * pSoldier );
BOOLEAN IsDetonatorAttached( OBJECTTYPE * pObj );
BOOLEAN IsRemoteDetonatorAttached( OBJECTTYPE * pObj );
BOOLEAN IsDetonatorAttached( OBJECTTYPE * pObj ); // Flugente: no more needed, use HasAttachmentOfClass( pObj, AC_DETONATOR ) instead
BOOLEAN IsRemoteDetonatorAttached( OBJECTTYPE * pObj ); // Flugente: no more needed, use HasAttachmentOfClass( pObj, AC_REMOTEDET ) instead
OBJECTTYPE* FindAttachedBatteries( OBJECTTYPE * pObj );
INT8 FindMedKit( SOLDIERTYPE * pSoldier );
INT8 FindFirstAidKit( SOLDIERTYPE * pSoldier );
+2 -2
View File
@@ -12910,7 +12910,7 @@ void SOLDIERTYPE::SoldierInventoryCoolDown(void)
FLOAT cooldownfactor = GetItemCooldownFactor(pObj); // ... get cooldown factor ...
FLOAT newtemperature = max(0.0, temperature - cooldownfactor); // ... calculate new temperature ...
FLOAT newtemperature = max((FLOAT)0.0, temperature - cooldownfactor); // ... calculate new temperature ...
(*pObj)[i]->data.bTemperature = newtemperature; // ... set new temperature
#if 0//def JA2TESTVERSION
@@ -12926,7 +12926,7 @@ void SOLDIERTYPE::SoldierInventoryCoolDown(void)
FLOAT cooldownfactor = GetItemCooldownFactor( &(*iter) ); // ... get cooldown factor ...
FLOAT newtemperature = max(0.0, temperature - cooldownfactor); // ... calculate new temperature ...
FLOAT newtemperature = max((FLOAT)0.0, temperature - cooldownfactor); // ... calculate new temperature ...
(*iter)[i]->data.bTemperature = newtemperature; // ... set new temperature
#if 0//def JA2TESTVERSION
+6 -2
View File
@@ -2582,11 +2582,15 @@ UINT8 GetActionModeCursor( SOLDIERTYPE *pSoldier )
// Detonators can only be on invalidcurs things...
if ( ubCursor == INVALIDCURS )
{
if ( IsDetonatorAttached( &(pSoldier->inv[HANDPOS]) ) )
if ( HasAttachmentOfClass( &(pSoldier->inv[HANDPOS]), AC_DETONATOR ) )
{
ubCursor = BOMBCURS;
}
else if ( IsRemoteDetonatorAttached( &(pSoldier->inv[HANDPOS]) ) )
else if ( HasAttachmentOfClass( &(pSoldier->inv[HANDPOS]), AC_REMOTEDET ) )
{
ubCursor = BOMBCURS;
}
else if ( HasAttachmentOfClass( &(pSoldier->inv[HANDPOS]), AC_DEFUSE) )
{
ubCursor = BOMBCURS;
}
+2
View File
@@ -378,6 +378,8 @@ typedef struct
UINT8 ubFragType;
UINT16 ubFragDamage;
UINT16 ubFragRange;
UINT16 ubHorizontalDegree; // Flugente: size of the horizontal arc into which fragments will be shot
UINT16 ubVerticalDegree; // Flugente: size of the vertical arc into which fragments will be shot
} EXPLOSIVETYPE;
//GLOBALS
+32 -11
View File
@@ -62,7 +62,9 @@ explosiveStartElementHandle(void *userData, const XML_Char *name, const XML_Char
strcmp(name, "usNumFragments") == 0 || // HEADROCK HAM 5.1: Fragmenting explosive data
strcmp(name, "ubFragType") == 0 ||
strcmp(name, "ubFragDamage") == 0 ||
strcmp(name, "ubFragRange") == 0 ))
strcmp(name, "ubFragRange") == 0 ||
strcmp(name, "ubHorizontalDegree") == 0 ||
strcmp(name, "ubVerticalDegree") == 0 ))
{
pData->curElement = ELEMENT_PROPERTY;
@@ -196,6 +198,18 @@ explosiveEndElementHandle(void *userData, const XML_Char *name)
pData->curExplosive.ubFragRange = (UINT16) atol(pData->szCharData);
}
else if(strcmp(name, "ubHorizontalDegree") == 0)
{
pData->curElement = ELEMENT;
pData->curExplosive.ubHorizontalDegree = (UINT16) atol(pData->szCharData);
}
else if(strcmp(name, "ubVerticalDegree") == 0)
{
pData->curElement = ELEMENT;
pData->curExplosive.ubVerticalDegree = (UINT16) atol(pData->szCharData);
}
pData->maxReadDepth--;
}
@@ -287,18 +301,25 @@ BOOLEAN WriteExplosiveStats()
FilePrintf(hFile,"\t<EXPLOSIVE>\r\n");
FilePrintf(hFile,"\t\t<uiIndex>%d</uiIndex>\r\n", cnt );
FilePrintf(hFile,"\t\t<ubType>%d</ubType>\r\n", Explosive[cnt].ubType );
FilePrintf(hFile,"\t\t<ubDamage>%d</ubDamage>\r\n", Explosive[cnt].ubDamage );
FilePrintf(hFile,"\t\t<ubStunDamage>%d</ubStunDamage>\r\n", Explosive[cnt].ubStunDamage );
FilePrintf(hFile,"\t\t<ubRadius>%d</ubRadius>\r\n", Explosive[cnt].ubRadius );
FilePrintf(hFile,"\t\t<ubVolume>%d</ubVolume>\r\n", Explosive[cnt].ubVolume );
FilePrintf(hFile,"\t\t<ubVolatility>%d</ubVolatility>\r\n", Explosive[cnt].ubVolatility );
FilePrintf(hFile,"\t\t<ubAnimationID>%d</ubAnimationID>\r\n", Explosive[cnt].ubAnimationID );
FilePrintf(hFile,"\t\t<uiIndex>%d</uiIndex>\r\n", cnt );
FilePrintf(hFile,"\t\t<ubType>%d</ubType>\r\n", Explosive[cnt].ubType );
FilePrintf(hFile,"\t\t<ubDamage>%d</ubDamage>\r\n", Explosive[cnt].ubDamage );
FilePrintf(hFile,"\t\t<ubStunDamage>%d</ubStunDamage>\r\n", Explosive[cnt].ubStunDamage );
FilePrintf(hFile,"\t\t<ubRadius>%d</ubRadius>\r\n", Explosive[cnt].ubRadius );
FilePrintf(hFile,"\t\t<ubVolume>%d</ubVolume>\r\n", Explosive[cnt].ubVolume );
FilePrintf(hFile,"\t\t<ubVolatility>%d</ubVolatility>\r\n", Explosive[cnt].ubVolatility );
FilePrintf(hFile,"\t\t<ubAnimationID>%d</ubAnimationID>\r\n", Explosive[cnt].ubAnimationID );
FilePrintf(hFile,"\t\t<ubDuration>%d</ubDuration>\r\n", Explosive[cnt].ubDuration );
FilePrintf(hFile,"\t\t<ubStartRadius>%d</ubStartRadius>\r\n", Explosive[cnt].ubStartRadius );
FilePrintf(hFile,"\t\t<ubStartRadius>%d</ubStartRadius>\r\n", Explosive[cnt].ubStartRadius );
FilePrintf(hFile,"\t\t<ubMagSize>%d</ubMagSize>\r\n", Explosive[cnt].ubMagSize );
FilePrintf(hFile,"\t\t<fExplodeOnImpact>%d</fExplodeOnImpact>\r\n", (UINT8)Explosive[cnt].fExplodeOnImpact );
FilePrintf(hFile,"\t\t<fExplodeOnImpact>%d</fExplodeOnImpact>\r\n", (UINT8)Explosive[cnt].fExplodeOnImpact );
FilePrintf(hFile,"\t\t<usNumFragments>%d</usNumFragments>\r\n", Explosive[cnt].usNumFragments );
FilePrintf(hFile,"\t\t<ubFragType>%d</ubFragType>\r\n", Explosive[cnt].ubFragType );
FilePrintf(hFile,"\t\t<ubFragDamage>%d</ubFragDamage>\r\n", Explosive[cnt].ubFragDamage );
FilePrintf(hFile,"\t\t<ubFragRange>%d</ubFragRange>\r\n", Explosive[cnt].fExplodeOnImpact );
FilePrintf(hFile,"\t\t<ubHorizontalDegree>%d</ubHorizontalDegree>\r\n", Explosive[cnt].ubHorizontalDegree );
FilePrintf(hFile,"\t\t<ubVerticalDegree>%d</ubVerticalDegree>\r\n", Explosive[cnt].ubVerticalDegree );
FilePrintf(hFile,"\t</EXPLOSIVE>\r\n");
}
+1 -1
View File
@@ -32,7 +32,7 @@
// Defines
// HEADROCK HAM 5: Increasing... with the hope of making spectacular fragmenting explosives.
#define NUM_BULLET_SLOTS 200
#define NUM_BULLET_SLOTS 1000 // Flugente: 200 -> 100
// GLOBAL FOR FACES LISTING