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
+225 -41
View File
@@ -215,8 +215,15 @@ INT32 DoMessageBox( UINT8 ubStyle, const STR16 zString, UINT32 uiExitScreen, UIN
gMsgBox.fRenderBox = TRUE; gMsgBox.fRenderBox = TRUE;
gMsgBox.bHandled = 0; gMsgBox.bHandled = 0;
// Flugente: increase the height of the display box under certain conditions
UINT16 heightincrease = 0;
if ( usFlags & MSG_BOX_FLAG_EIGHT_NUMBERED_BUTTONS )
heightincrease = 50;
if ( usFlags & MSG_BOX_FLAG_SIXTEEN_NUMBERED_BUTTONS )
heightincrease = 90;
// Init message box // Init message box
gMsgBox.iBoxId = PrepareMercPopupBox( iId, ubMercBoxBackground, ubMercBoxBorder, zString, MSGBOX_DEFAULT_WIDTH, 40, 10, 30, &usTextBoxWidth, &usTextBoxHeight ); gMsgBox.iBoxId = PrepareMercPopupBox( iId, ubMercBoxBackground, ubMercBoxBorder, zString, MSGBOX_DEFAULT_WIDTH, 40, 10, 30 + heightincrease, &usTextBoxWidth, &usTextBoxHeight );
if( gMsgBox.iBoxId == -1 ) if( gMsgBox.iBoxId == -1 )
{ {
@@ -348,11 +355,117 @@ INT32 DoMessageBox( UINT8 ubStyle, const STR16 zString, UINT32 uiExitScreen, UIN
DEFAULT_MOVE_CALLBACK, (GUI_CALLBACK)NumberedMsgBoxCallback ); DEFAULT_MOVE_CALLBACK, (GUI_CALLBACK)NumberedMsgBoxCallback );
MSYS_SetBtnUserData( gMsgBox.uiButton[3], 0, 4); MSYS_SetBtnUserData( gMsgBox.uiButton[3], 0, 4);
SetButtonCursor(gMsgBox.uiButton[3], usCursor); SetButtonCursor(gMsgBox.uiButton[3], usCursor);
ForceButtonUnDirty( gMsgBox.uiButton[3] );
ForceButtonUnDirty( gMsgBox.uiButton[2] );
ForceButtonUnDirty( gMsgBox.uiButton[1] );
ForceButtonUnDirty( gMsgBox.uiButton[0] );
for ( INT8 i = 3; i >= 0; --i)
{
ForceButtonUnDirty( gMsgBox.uiButton[i] );
}
}
// Create eight numbered buttons
else if ( usFlags & MSG_BOX_FLAG_EIGHT_NUMBERED_BUTTONS )
{
sBlankSpace = usTextBoxWidth - MSGBOX_SMALL_BUTTON_WIDTH * 4 - MSGBOX_SMALL_BUTTON_X_SEP * 3;
sButtonX = sBlankSpace / 2;
sButtonY = usTextBoxHeight - MSGBOX_BUTTON_HEIGHT - 10 - heightincrease;
STR16 eightstr[8] = {
L"1",
L"2",
L"3",
L"4",
L"A",
L"B",
L"C",
L"D",
};
sButtonY -= MSGBOX_SMALL_BUTTON_WIDTH - MSGBOX_SMALL_BUTTON_X_SEP;
for ( INT8 i = 0; i < 2; ++i)
{
// new row
sButtonY += MSGBOX_SMALL_BUTTON_WIDTH;// + MSGBOX_SMALL_BUTTON_X_SEP;
// begin from the front
sButtonX = sBlankSpace / 2 - MSGBOX_SMALL_BUTTON_WIDTH - MSGBOX_SMALL_BUTTON_X_SEP;
for ( INT8 j = 0; j < 4; ++j)
{
INT8 k = 4*i + j;
sButtonX += MSGBOX_SMALL_BUTTON_WIDTH + MSGBOX_SMALL_BUTTON_X_SEP;
gMsgBox.uiButton[k] = CreateIconAndTextButton( gMsgBox.iButtonImages, eightstr[k], FONT12ARIAL,
ubFontColor, ubFontShadowColor,
ubFontColor, ubFontShadowColor,
TEXT_CJUSTIFIED,
(INT16)(gMsgBox.sX + sButtonX ), (INT16)(gMsgBox.sY + sButtonY ), BUTTON_TOGGLE ,MSYS_PRIORITY_HIGHEST,
DEFAULT_MOVE_CALLBACK, (GUI_CALLBACK)NumberedMsgBoxCallback );
MSYS_SetBtnUserData( gMsgBox.uiButton[k], 0, k+1);
SetButtonCursor(gMsgBox.uiButton[k], usCursor);
}
}
for ( INT8 i = 7; i >= 0; --i)
{
ForceButtonUnDirty( gMsgBox.uiButton[i] );
}
}
// Create sixteen numbered buttons
else if ( usFlags & MSG_BOX_FLAG_SIXTEEN_NUMBERED_BUTTONS )
{
sBlankSpace = usTextBoxWidth - MSGBOX_SMALL_BUTTON_WIDTH * 4 - MSGBOX_SMALL_BUTTON_X_SEP * 3;
sButtonX = sBlankSpace / 2;
sButtonY = usTextBoxHeight - MSGBOX_BUTTON_HEIGHT - 10 - heightincrease - 6;
STR16 sixteenstr[16] = {
L"1-A",
L"1-B",
L"1-C",
L"1-D",
L"2-A",
L"2-B",
L"2-C",
L"2-D",
L"3-A",
L"3-B",
L"3-C",
L"3-D",
L"4-A",
L"4-B",
L"4-C",
L"4-D",
};
sButtonY -= MSGBOX_SMALL_BUTTON_WIDTH - MSGBOX_SMALL_BUTTON_X_SEP;
for ( INT8 i = 0; i < 4; ++i)
{
// new row
sButtonY += MSGBOX_SMALL_BUTTON_WIDTH - 2;// + MSGBOX_SMALL_BUTTON_X_SEP;
// begin from the front
sButtonX = sBlankSpace / 2 - MSGBOX_SMALL_BUTTON_WIDTH - MSGBOX_SMALL_BUTTON_X_SEP;
for ( INT8 j = 0; j < 4; ++j)
{
INT8 k = 4*i + j;
sButtonX += MSGBOX_SMALL_BUTTON_WIDTH + MSGBOX_SMALL_BUTTON_X_SEP;
gMsgBox.uiButton[k] = CreateIconAndTextButton( gMsgBox.iButtonImages, sixteenstr[k], FONT12ARIAL,
ubFontColor, ubFontShadowColor,
ubFontColor, ubFontShadowColor,
TEXT_CJUSTIFIED,
(INT16)(gMsgBox.sX + sButtonX ), (INT16)(gMsgBox.sY + sButtonY ), BUTTON_TOGGLE ,MSYS_PRIORITY_HIGHEST,
DEFAULT_MOVE_CALLBACK, (GUI_CALLBACK)NumberedMsgBoxCallback );
MSYS_SetBtnUserData( gMsgBox.uiButton[k], 0, k+1);
SetButtonCursor(gMsgBox.uiButton[k], usCursor);
}
}
for ( INT8 i = 15; i >= 0; --i)
{
ForceButtonUnDirty( gMsgBox.uiButton[i] );
}
} }
else if (usFlags & MSG_BOX_FLAG_INPUTBOX) else if (usFlags & MSG_BOX_FLAG_INPUTBOX)
{ {
@@ -853,10 +966,24 @@ UINT32 ExitMsgBox( INT8 ubExitCode )
//Delete buttons! //Delete buttons!
if ( gMsgBox.usFlags & MSG_BOX_FLAG_FOUR_NUMBERED_BUTTONS ) if ( gMsgBox.usFlags & MSG_BOX_FLAG_FOUR_NUMBERED_BUTTONS )
{ {
RemoveButton( gMsgBox.uiButton[0] ); for (UINT8 i = 0; i < 4; ++i)
RemoveButton( gMsgBox.uiButton[1] ); {
RemoveButton( gMsgBox.uiButton[2] ); RemoveButton( gMsgBox.uiButton[i] );
RemoveButton( gMsgBox.uiButton[3] ); }
}
else if ( gMsgBox.usFlags & MSG_BOX_FLAG_EIGHT_NUMBERED_BUTTONS )
{
for (UINT8 i = 0; i < 8; ++i)
{
RemoveButton( gMsgBox.uiButton[i] );
}
}
else if ( gMsgBox.usFlags & MSG_BOX_FLAG_SIXTEEN_NUMBERED_BUTTONS )
{
for (UINT8 i = 0; i < 16; ++i)
{
RemoveButton( gMsgBox.uiButton[i] );
}
} }
// OJW - 20090208 - Add text input box type // OJW - 20090208 - Add text input box type
else if (gMsgBox.usFlags & MSG_BOX_FLAG_INPUTBOX) else if (gMsgBox.usFlags & MSG_BOX_FLAG_INPUTBOX)
@@ -1079,10 +1206,24 @@ UINT32 MessageBoxScreenHandle( )
{ {
if ( gMsgBox.usFlags & MSG_BOX_FLAG_FOUR_NUMBERED_BUTTONS ) if ( gMsgBox.usFlags & MSG_BOX_FLAG_FOUR_NUMBERED_BUTTONS )
{ {
MarkAButtonDirty( gMsgBox.uiButton[0] ); for (UINT8 i = 0; i < 4; ++i)
MarkAButtonDirty( gMsgBox.uiButton[1] ); {
MarkAButtonDirty( gMsgBox.uiButton[2] ); MarkAButtonDirty( gMsgBox.uiButton[i] );
MarkAButtonDirty( gMsgBox.uiButton[3] ); }
}
else if ( gMsgBox.usFlags & MSG_BOX_FLAG_EIGHT_NUMBERED_BUTTONS )
{
for (UINT8 i = 0; i < 8; ++i)
{
MarkAButtonDirty( gMsgBox.uiButton[i] );
}
}
else if ( gMsgBox.usFlags & MSG_BOX_FLAG_SIXTEEN_NUMBERED_BUTTONS )
{
for (UINT8 i = 0; i < 16; ++i)
{
MarkAButtonDirty( gMsgBox.uiButton[i] );
}
} }
if ( gMsgBox.usFlags & MSG_BOX_FLAG_OK ) if ( gMsgBox.usFlags & MSG_BOX_FLAG_OK )
@@ -1227,39 +1368,82 @@ UINT32 MessageBoxScreenHandle( )
gMsgBox.bHandled = MSG_BOX_RETURN_YES; gMsgBox.bHandled = MSG_BOX_RETURN_YES;
} }
} }
if( InputEvent.usParam == '1' )
// box with four buttons
UINT32 four[8] = {
'1',
'2',
'3',
'4',
};
for ( INT8 i = 0; i < 4; ++i )
{ {
if ( gMsgBox.usFlags & MSG_BOX_FLAG_FOUR_NUMBERED_BUTTONS ) if( InputEvent.usParam == four[i] )
{ {
// Exit messagebox if ( gMsgBox.usFlags & MSG_BOX_FLAG_FOUR_NUMBERED_BUTTONS )
gMsgBox.bHandled = 1; {
} // Exit messagebox
} gMsgBox.bHandled = 1;
if( InputEvent.usParam == '2' ) }
{
if ( gMsgBox.usFlags & MSG_BOX_FLAG_FOUR_NUMBERED_BUTTONS )
{
// Exit messagebox
gMsgBox.bHandled = 1;
}
}
if( InputEvent.usParam == '3' )
{
if ( gMsgBox.usFlags & MSG_BOX_FLAG_FOUR_NUMBERED_BUTTONS )
{
// Exit messagebox
gMsgBox.bHandled = 1;
}
}
if( InputEvent.usParam == '4' )
{
if ( gMsgBox.usFlags & MSG_BOX_FLAG_FOUR_NUMBERED_BUTTONS )
{
// Exit messagebox
gMsgBox.bHandled = 1;
} }
} }
// box with eight buttons
UINT32 eighttxt[8] = {
'1',
'2',
'3',
'4',
'A',
'B',
'C',
'D',
};
for ( INT8 i = 0; i < 8; ++i )
{
if( InputEvent.usParam == eighttxt[i] )
{
if ( gMsgBox.usFlags & MSG_BOX_FLAG_EIGHT_NUMBERED_BUTTONS )
{
// Exit messagebox
gMsgBox.bHandled = 1;
}
}
}
// box with sixteen buttons
UINT32 sixteentxt[16] = {
'1-A',
'1-B',
'1-C',
'1-D',
'2-A',
'2-B',
'2-C',
'2-D',
'3-A',
'3-B',
'3-C',
'3-D',
'4-A',
'4-B',
'4-C',
'4-D',
};
for ( INT8 i = 0; i < 16; ++i )
{
if( InputEvent.usParam == sixteentxt[i] )
{
if ( gMsgBox.usFlags & MSG_BOX_FLAG_SIXTEEN_NUMBERED_BUTTONS )
{
// Exit messagebox
gMsgBox.bHandled = 1;
}
}
}
} }
} }
+4 -1
View File
@@ -18,6 +18,9 @@
#define MSG_BOX_FLAG_GENERIC 0x0800 // 2 user-defined text buttons #define MSG_BOX_FLAG_GENERIC 0x0800 // 2 user-defined text buttons
// OJW - Adding text chatbox // OJW - Adding text chatbox
#define MSG_BOX_FLAG_INPUTBOX 0x1000 // has a text input field #define MSG_BOX_FLAG_INPUTBOX 0x1000 // has a text input field
// Flugente - added boxes for simultaneous defuse/detonate mechanism
#define MSG_BOX_FLAG_EIGHT_NUMBERED_BUTTONS 0x2000 // Displays eight numbered buttons, 1-4, 10, 20, 30, 40. Numbers 1-4 respond to the normal detonate mechanism, rest to defusing
#define MSG_BOX_FLAG_SIXTEEN_NUMBERED_BUTTONS 0x4000 // Displays sixteen numbered buttons, 1-16, for setting up a tripwire network and choosing both a detonation and defusing frequency
// message box return codes // message box return codes
#define MSG_BOX_RETURN_OK 1 // ENTER or on OK button #define MSG_BOX_RETURN_OK 1 // ENTER or on OK button
@@ -66,7 +69,7 @@ typedef struct
}; };
struct struct
{ {
UINT32 uiButton[4]; UINT32 uiButton[16];
}; };
}; };
BOOLEAN fRenderBox; BOOLEAN fRenderBox;
+4
View File
@@ -3067,6 +3067,10 @@ void recievePLANTEXPLOSIVE (RPCParameters *rpcParameters)
else else
(*pObj)[0]->data.misc.bDelay = exp->bDelayFreq; (*pObj)[0]->data.misc.bDelay = exp->bDelayFreq;
(*pObj)[0]->data.ubDirection = DIRECTION_IRRELEVANT;
(*pObj)[0]->data.ubWireNetworkFlag = ENEMY_NET_1_LVL_1;
(*pObj)[0]->data.bDefuseFrequency = 0;
// save old clients WorldID if we can // save old clients WorldID if we can
// loop through world bombs and find the one linked to the item we just created // loop through world bombs and find the one linked to the item we just created
UINT32 uiCount; UINT32 uiCount;
+219 -40
View File
@@ -60,6 +60,10 @@ enum MINES_VALUES
MINES_NET_2, MINES_NET_2,
MINES_NET_3, MINES_NET_3,
MINES_NET_4, MINES_NET_4,
MINES_LVL_1,
MINES_LVL_2,
MINES_LVL_3,
MINES_LVL_4,
MAX_MINES MAX_MINES
}; };
@@ -93,8 +97,14 @@ const UINT8 animArr[3] = {
// Flugente: mines display - stuff needs to be here // Flugente: mines display - stuff needs to be here
enum MINES_DRAW_MODE { enum MINES_DRAW_MODE {
MINES_DRAW_OFF, MINES_DRAW_OFF,
MINES_DRAW_DETECT_ENEMY,
MINES_DRAW_PLAYERTEAM_NETWORKS, 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 ********************************************* //****** Local Variables *********************************************
@@ -701,7 +711,7 @@ void SwitchToHostileTrapsView()
return; return;
gubDrawModeMine = MINES_DRAW_DETECT_ENEMY; 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); DisplayMines(TRUE);
} }
@@ -711,7 +721,7 @@ void SwitchMineViewOff()
return; return;
gubDrawModeMine = MINES_DRAW_OFF; 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); DisplayMines(TRUE);
} }
@@ -726,16 +736,60 @@ void ToggleHostileTrapsView()
void ToggleTrapNetworkView() void ToggleTrapNetworkView()
{ {
if (gubDrawModeMine == MINES_DRAW_PLAYERTEAM_NETWORKS) { SwitchMinesDrawModeForNetworks();
/*if (gubDrawModeMine == MINES_DRAW_PLAYERTEAM_NETWORKS) {
SwitchMineViewOff(); SwitchMineViewOff();
} else { } else {
SwitchToTrapNetworkView(); 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: case MINES_DRAW_OFF:
SwitchToTrapNetworkView(); SwitchToTrapNetworkView();
@@ -746,7 +800,7 @@ void SwitchMinesDrawMode()
default: default:
SwitchMineViewOff(); SwitchMineViewOff();
break; break;
} }*/
} }
///END key binding functions ///END key binding functions
@@ -757,14 +811,18 @@ TileDefines GetTileMinesIndex( const INT8& bMines )
case MINES_ALL: case MINES_ALL:
case MINE_BOMB: case MINE_BOMB:
case MINES_NET_1: case MINES_NET_1:
case MINES_LVL_4:
return SPECIALTILE_COVER_1; // red return SPECIALTILE_COVER_1; // red
case MINE_BOMB_AND_WIRE:
case MINES_NET_2: case MINES_NET_2:
case MINE_BOMB_AND_WIRE: case MINES_LVL_3:
return SPECIALTILE_COVER_2; // orange return SPECIALTILE_COVER_2; // orange
case MINES_NET_3:
case MINE_WIRE: case MINE_WIRE:
case MINES_NET_3:
case MINES_LVL_2:
return SPECIALTILE_COVER_3; // yellow return SPECIALTILE_COVER_3; // yellow
case MINES_NET_4: case MINES_NET_4:
case MINES_LVL_1:
return SPECIALTILE_COVER_4; // green return SPECIALTILE_COVER_4; // green
case MAX_MINES: case MAX_MINES:
default: default:
@@ -774,6 +832,10 @@ TileDefines GetTileMinesIndex( const INT8& bMines )
BOOLEAN MineTileHasAdjTile( const INT32& ubX, const INT32& ubY, const INT32& ubZ ) 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; INT32 ubTX, ubTY;
for ( ubTX = ubX-1; ubTX <= ubX+1; ++ubTX ) for ( ubTX = ubX-1; ubTX <= ubX+1; ++ubTX )
@@ -910,19 +972,12 @@ void CalculateMines()
GetSoldier( &pSoldier, gusSelectedSoldier ); 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 // if we want to detect hostile mines and we have an metal detector in our hands, allow seeking
BOOLEAN fWithMineDetector = FALSE; BOOLEAN fWithMineDetector = FALSE;
if ( pSoldier && gubDrawModeMine == MINES_DRAW_DETECT_ENEMY ) if ( pSoldier && gubDrawModeMine == MINES_DRAW_DETECT_ENEMY )
{ {
if ( (&(pSoldier->inv[HANDPOS] ))->exists() && Item[pSoldier->inv[HANDPOS].usItem].metaldetector== 1 ) if ( FindMetalDetectorInHand(pSoldier) )
{
fWithMineDetector = TRUE; fWithMineDetector = TRUE;
}
else if ( (&(pSoldier->inv[SECONDHANDPOS] ))->exists() && Item[pSoldier->inv[SECONDHANDPOS].usItem].metaldetector== 1 )
{
fWithMineDetector = TRUE;
}
// TODO: perhaps even consume batteries one day... // 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 // we are looking for hostile mines and have got an detector equipped
if ( gubDrawModeMine == MINES_DRAW_DETECT_ENEMY && fWithMineDetector ) if ( gubDrawModeMine == MINES_DRAW_DETECT_ENEMY && fWithMineDetector )
{ {
// look for hostile mines // display all mines
//if ( ((*pObj)[0]->data.misc.ubBombOwner < 2) ) bMines = MINE_BOMB;
{
bMines = MINE_BOMB;
}
} }
else else
{ {
// look for mines from our own team // 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 case MINES_DRAW_PLAYERTEAM_NETWORKS:
if ( bMines == MINE_BOMB ) {
bMines = MINE_BOMB_AND_WIRE; if ( Item[pObj->usItem].tripwire == 1 )
else {
bMines = MINE_WIRE; // if we're already marked as MINE_BOMB, switch to MINE_BOMB_AND_WIRE
} if ( bMines == MINE_BOMB )
else bMines = MINE_BOMB_AND_WIRE;
{ else
// if we're already marked as MINE_WIRE, switch to MINE_BOMB_AND_WIRE bMines = MINE_WIRE;
if ( bMines == MINE_WIRE ) }
bMines = MINE_BOMB_AND_WIRE; else
else {
bMines = MINE_BOMB; // 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 ToggleTrapNetworkView();
void ToggleHostileTrapsView(); void ToggleHostileTrapsView();
void SwitchMinesDrawMode(); void SwitchMinesDrawModeForNetworks();
#endif #endif
+80 -17
View File
@@ -1228,7 +1228,7 @@ INT32 HandleItem( SOLDIERTYPE *pSoldier, INT32 sGridNo, INT8 bLevel, UINT16 usHa
if ( Item[ usHandItem ].ubCursor == INVALIDCURS ) if ( Item[ usHandItem ].ubCursor == INVALIDCURS )
{ {
// Found detonator... // 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; fDropBomb = TRUE;
} }
@@ -1462,7 +1462,7 @@ INT32 HandleItem( SOLDIERTYPE *pSoldier, INT32 sGridNo, INT8 bLevel, UINT16 usHa
if ( Item[ usHandItem ].ubCursor == INVALIDCURS ) if ( Item[ usHandItem ].ubCursor == INVALIDCURS )
{ {
// Found detonator... // 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 ); StartBombMessageBox( pSoldier, sGridNo );
@@ -1482,7 +1482,7 @@ INT32 HandleItem( SOLDIERTYPE *pSoldier, INT32 sGridNo, INT8 bLevel, UINT16 usHa
void HandleSoldierDropBomb( SOLDIERTYPE *pSoldier, INT32 sGridNo ) void HandleSoldierDropBomb( SOLDIERTYPE *pSoldier, INT32 sGridNo )
{ {
// Does this have detonator that needs info? // 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 ); StartBombMessageBox( pSoldier, sGridNo );
} }
@@ -1515,6 +1515,13 @@ void HandleSoldierDropBomb( SOLDIERTYPE *pSoldier, INT32 sGridNo )
} }
pSoldier->inv[ HANDPOS ][0]->data.misc.ubBombOwner = pSoldier->ubID + 2; 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 // we now know there is something nasty here
gpWorldLevelData[ sGridNo ].uiFlags |= MAPELEMENT_PLAYER_MINE_PRESENT; 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 ) if ( iResult < -20 && Item[ pSoldier->inv[ HANDPOS ].usItem ].tripwire != 1 )
{ {
// OOPS! ... BOOM! // 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); pSoldier->inv[ HANDPOS ].MoveThisObjectTo(gTempObject, 1);
} }
} }
@@ -1939,8 +1946,19 @@ void SoldierGetItemFromWorld( SOLDIERTYPE *pSoldier, INT32 iItemIndex, INT32 sGr
// REMOVE ITEM FROM POOL // REMOVE ITEM FROM POOL
if ( ItemExistsAtLocation( sGridNo, iItemIndex, pSoldier->pathing.bLevel ) ) 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 ) ) if ( ItemIsCool( &gWorldItems[ iItemIndex ].object ) )
{ {
@@ -4313,7 +4331,7 @@ void StartBombMessageBox( SOLDIERTYPE * pSoldier, INT32 sGridNo )
gsTempGridNo = sGridNo; gsTempGridNo = sGridNo;
if (Item[ pSoldier->inv[HANDPOS].usItem].remotetrigger ) 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) else if (pSoldier->inv[HANDPOS].usItem == REMOTETRIGGER)
{ {
@@ -4351,13 +4369,32 @@ void StartBombMessageBox( SOLDIERTYPE * pSoldier, INT32 sGridNo )
pSoldier->DoMercBattleSound( BATTLE_SOUND_CURSE1 ); 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 );
} }
} }
@@ -4373,7 +4410,7 @@ void BombMessageBoxCallBack( UINT8 ubExitValue )
{ {
INT32 iResult; INT32 iResult;
if (IsRemoteDetonatorAttached( &(gpTempSoldier->inv[HANDPOS]) ) ) if ( HasAttachmentOfClass( &(gpTempSoldier->inv[HANDPOS]), AC_REMOTEDET ) )
{ {
iResult = SkillCheck( gpTempSoldier, PLANTING_REMOTE_BOMB_CHECK, 0 ); iResult = SkillCheck( gpTempSoldier, PLANTING_REMOTE_BOMB_CHECK, 0 );
} }
@@ -4413,10 +4450,11 @@ void BombMessageBoxCallBack( UINT8 ubExitValue )
} }
else else
{ {
// we can't blow up tripwire, no matter how bad we fail
if ( Item[ gpTempSoldier->inv[ HANDPOS ].usItem ].tripwire != 1 ) if ( Item[ gpTempSoldier->inv[ HANDPOS ].usItem ].tripwire != 1 )
{ {
// OOPS! ... BOOM! // 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; return;
@@ -4439,9 +4477,16 @@ void BombMessageBoxCallBack( UINT8 ubExitValue )
// HACK IMMINENT! // HACK IMMINENT!
// value of 1 is stored in maps for SIDE of bomb owner... when we want to use IDs! // 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 // 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; 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 // 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 ) ) 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 ) if ( gTempObject[0]->data.misc.ubBombOwner - 2 == gpBoobyTrapSoldier->ubID )
{ {
// my own boobytrap! // my own boobytrap!
iCheckResult = SkillCheck( gpBoobyTrapSoldier, DISARM_TRAP_CHECK, 40 ); iCheckResult = SkillCheck( gpBoobyTrapSoldier, DISARM_TRAP_CHECK, 40 + wirecutterbonus );
} }
else else
{ {
// our team's boobytrap! // our team's boobytrap!
iCheckResult = SkillCheck( gpBoobyTrapSoldier, DISARM_TRAP_CHECK, 20 ); iCheckResult = SkillCheck( gpBoobyTrapSoldier, DISARM_TRAP_CHECK, 20 + wirecutterbonus );
} }
} }
else else
@@ -4977,7 +5035,12 @@ BOOLEAN NearbyGroundSeemsWrong( SOLDIERTYPE * pSoldier, INT32 sGridNo, BOOLEAN f
ubDetectLevel = 0; 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; fMining = TRUE;
} }
+13
View File
@@ -1024,7 +1024,12 @@ ObjectData::ObjectData(const ObjectData& src)
this->bTrap = src.bTrap; this->bTrap = src.bTrap;
this->fUsed = src.fUsed; this->fUsed = src.fUsed;
this->ubImprintID = src.ubImprintID; this->ubImprintID = src.ubImprintID;
this->bTemperature = src.bTemperature; this->bTemperature = src.bTemperature;
this->ubDirection = src.ubDirection;
this->ubWireNetworkFlag = src.ubWireNetworkFlag;
this->bDefuseFrequency = src.bDefuseFrequency;
//copy over the union //copy over the union
this->gun = src.gun; this->gun = src.gun;
@@ -1043,7 +1048,12 @@ ObjectData& ObjectData::operator =(const ObjectData& src)
this->bTrap = src.bTrap; this->bTrap = src.bTrap;
this->fUsed = src.fUsed; this->fUsed = src.fUsed;
this->ubImprintID = src.ubImprintID; this->ubImprintID = src.ubImprintID;
this->bTemperature = src.bTemperature; this->bTemperature = src.bTemperature;
this->ubDirection = src.ubDirection;
this->ubWireNetworkFlag = src.ubWireNetworkFlag;
this->bDefuseFrequency = src.bDefuseFrequency;
//copy over the union //copy over the union
this->gun = src.gun; 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.ubBombOwner = src.ugYucky.ubBombOwner;
(*this)[0]->data.misc.bActionValue = src.ugYucky.bActionValue; (*this)[0]->data.misc.bActionValue = src.ugYucky.bActionValue;
(*this)[0]->data.misc.ubTolerance = src.ugYucky.ubTolerance; // includes ubLocationID (*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; break;
default: default:
//This should cover all other possibilities since only Money, Key and "Bomb/Misc" have layouts that don't //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. // New values, like bTemperature, have to come after this. And please, don't destroy ObjectData's POD-ness.
char endOfPOD; 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 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 // Flugente: needed for reading WF maps
#define SIZEOF_OBJECTDATA_POD (offsetof(ObjectData, endOfPOD)) #define SIZEOF_OBJECTDATA_POD (offsetof(ObjectData, endOfPOD))
@@ -655,6 +662,48 @@ extern OBJECTTYPE gTempObject;
#define AC_MISC19 0x40000000 //1073741824 #define AC_MISC19 0x40000000 //1073741824
#define AC_MISC20 0x80000000 //2147483648 #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 // replaces candamage
//#define ITEM_DAMAGEABLE 0x0001 //#define ITEM_DAMAGEABLE 0x0001
@@ -893,6 +942,7 @@ typedef struct
BOOLEAN tripwireactivation; // item (mine) can be activated by nearby tripwire BOOLEAN tripwireactivation; // item (mine) can be activated by nearby tripwire
BOOLEAN tripwire; // item is tripwire BOOLEAN tripwire; // item is tripwire
BOOLEAN directional; // item is a directional mine/bomb (actual direction is set upon planting)
} INVTYPE; } INVTYPE;
+89 -23
View File
@@ -1590,17 +1590,18 @@ INT8 FindBestWeaponIfCurrentIsOutOfRange(SOLDIERTYPE * pSoldier, INT8 bCurrentWe
return( bCurrentWeaponIndex ); return( bCurrentWeaponIndex );
} }
INT8 FindMetalDetector( SOLDIERTYPE * pSoldier ) INT8 FindMetalDetectorInHand( SOLDIERTYPE * pSoldier )
{ {
INT8 bLoop; if ( (&(pSoldier->inv[HANDPOS] ))->exists() && Item[pSoldier->inv[HANDPOS].usItem].metaldetector )
for (bLoop = 0; bLoop < (INT8) pSoldier->inv.size(); bLoop++)
{ {
if (Item[pSoldier->inv[bLoop].usItem].metaldetector && pSoldier->inv[bLoop].exists() == true) return( HANDPOS );
{
return( bLoop );
}
} }
if ( (&(pSoldier->inv[SECONDHANDPOS] ))->exists() && Item[pSoldier->inv[SECONDHANDPOS].usItem].metaldetector )
{
return( SECONDHANDPOS );
}
return( NO_SLOT ); return( NO_SLOT );
} }
@@ -7345,6 +7346,12 @@ BOOLEAN ArmBomb( OBJECTTYPE * pObj, INT8 bSetting )
BOOLEAN fPressure = FALSE; BOOLEAN fPressure = FALSE;
BOOLEAN fTimed = FALSE; BOOLEAN fTimed = FALSE;
BOOLEAN fSwitch = FALSE; BOOLEAN fSwitch = FALSE;
BOOLEAN fDefuse = FALSE; // bomb can be defused remotely
if ( HasAttachmentOfClass( pObj, AC_DEFUSE) )
{
fDefuse = TRUE;
}
if (pObj->usItem == ACTION_ITEM) 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; fTimed = TRUE;
} }
else if ( (IsRemoteDetonatorAttached( pObj ) ) || (pObj->usItem == ACTION_ITEM) ) else if ( HasAttachmentOfClass( pObj, (AC_REMOTEDET | AC_DEFUSE) ) || (pObj->usItem == ACTION_ITEM) )
{ {
fRemote = TRUE; fRemote = TRUE;
} }
@@ -7392,22 +7399,74 @@ BOOLEAN ArmBomb( OBJECTTYPE * pObj, INT8 bSetting )
return( FALSE ); 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) if (fRemote)
{ {
(*pObj)[0]->data.misc.bDetonatorType = BOMB_REMOTE; (*pObj)[0]->data.misc.bDetonatorType = BOMB_REMOTE;
(*pObj)[0]->data.misc.bFrequency = bSetting; (*pObj)[0]->data.misc.bFrequency = detonatesetting;
} }
else if (fPressure) else if (fPressure)
{ {
(*pObj)[0]->data.misc.bDetonatorType = BOMB_PRESSURE; (*pObj)[0]->data.misc.bDetonatorType = BOMB_PRESSURE;
(*pObj)[0]->data.misc.bFrequency = 0; (*pObj)[0]->data.misc.bFrequency = 0;
(*pObj)[0]->data.ubWireNetworkFlag = ubWireNetworkFlag;
} }
else if (fTimed) else if (fTimed)
{ {
(*pObj)[0]->data.misc.bDetonatorType = BOMB_TIMED; (*pObj)[0]->data.misc.bDetonatorType = BOMB_TIMED;
// In realtime the player could choose to put down a bomb right before a turn expires, SO // In realtime the player could choose to put down a bomb right before a turn expires, SO
// add 1 to the setting in RT // 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) ) if ( !(gTacticalStatus.uiFlags & TURNBASED && gTacticalStatus.uiFlags & INCOMBAT) )
{ {
(*pObj)[0]->data.misc.bDelay++; (*pObj)[0]->data.misc.bDelay++;
@@ -7417,13 +7476,17 @@ BOOLEAN ArmBomb( OBJECTTYPE * pObj, INT8 bSetting )
else if (fSwitch) else if (fSwitch)
{ {
(*pObj)[0]->data.misc.bDetonatorType = BOMB_SWITCH; (*pObj)[0]->data.misc.bDetonatorType = BOMB_SWITCH;
(*pObj)[0]->data.misc.bFrequency = bSetting; (*pObj)[0]->data.misc.bFrequency = detonatesetting;
} }
else else
{ {
return( FALSE ); return( FALSE );
} }
// for safety, weird things happen
if ( (*pObj).fFlags & OBJECT_DISABLED_BOMB )
(*pObj).fFlags &= ~(OBJECT_DISABLED_BOMB);
(*pObj).fFlags |= OBJECT_ARMED_BOMB; (*pObj).fFlags |= OBJECT_ARMED_BOMB;
(*pObj)[0]->data.misc.usBombItem = pObj->usItem; (*pObj)[0]->data.misc.usBombItem = pObj->usItem;
return( TRUE ); return( TRUE );
@@ -7997,11 +8060,11 @@ void CheckEquipmentForDamage( SOLDIERTYPE *pSoldier, INT32 iDamage )
// blow it up! // blow it up!
if ( gTacticalStatus.ubAttackBusyCount ) 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 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 //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 ) if ( fBlowsUp )
{ {
// OK, Ignite this explosion! // 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 // SANDRO - merc records
if ( (pObject->fFlags & OBJECT_ARMED_BOMB) && ((*pObject)[0]->data.misc.ubBombOwner > 1) ) if ( (pObject->fFlags & OBJECT_ARMED_BOMB) && ((*pObject)[0]->data.misc.ubBombOwner > 1) )
@@ -12605,8 +12668,8 @@ INT32 GetGunAccuracy( OBJECTTYPE *pObj )
if ( gGameOptions.fWeaponOverheating ) if ( gGameOptions.fWeaponOverheating )
{ {
FLOAT overheatdamagepercentage = GetGunOverheatDamagePercentage( pObj ); FLOAT overheatdamagepercentage = GetGunOverheatDamagePercentage( pObj );
FLOAT accuracymalus = (max(1.0, overheatdamagepercentage) - 1.0) * 0.1; FLOAT accuracymalus = (max((FLOAT)1.0, overheatdamagepercentage) - (FLOAT)1.0) * 0.1;
accuracyheatmultiplicator = max(0.0, 1.0 - accuracymalus); accuracyheatmultiplicator = max((FLOAT)0.0, (FLOAT)1.0 - accuracymalus);
} }
if(UsingNewCTHSystem() == false) if(UsingNewCTHSystem() == false)
@@ -13022,12 +13085,15 @@ BOOLEAN IsAttachmentClass( UINT16 usItem, UINT32 aFlag )
BOOLEAN HasAttachmentOfClass( OBJECTTYPE * pObj, UINT32 aFlag ) BOOLEAN HasAttachmentOfClass( OBJECTTYPE * pObj, UINT32 aFlag )
{ {
// check all attachments if ( pObj->exists() )
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 ) ) // check all attachments
return( TRUE ); 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 ); return( FALSE );
+3 -3
View File
@@ -374,12 +374,12 @@ INT16 GetAttachedArmourBonus( OBJECTTYPE * pObj );
INT16 GetBulletSpeedBonus( OBJECTTYPE * pObj ); INT16 GetBulletSpeedBonus( OBJECTTYPE * pObj );
INT8 FindGasMask( SOLDIERTYPE * pSoldier ); INT8 FindGasMask( SOLDIERTYPE * pSoldier );
INT8 FindLockBomb( 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 FindCannon( SOLDIERTYPE * pSoldier );
INT8 FindUsableCrowbar( SOLDIERTYPE * pSoldier ); INT8 FindUsableCrowbar( SOLDIERTYPE * pSoldier );
INT8 FindToolkit( SOLDIERTYPE * pSoldier ); INT8 FindToolkit( SOLDIERTYPE * pSoldier );
BOOLEAN IsDetonatorAttached( OBJECTTYPE * pObj ); BOOLEAN IsDetonatorAttached( OBJECTTYPE * pObj ); // Flugente: no more needed, use HasAttachmentOfClass( pObj, AC_DETONATOR ) instead
BOOLEAN IsRemoteDetonatorAttached( OBJECTTYPE * pObj ); BOOLEAN IsRemoteDetonatorAttached( OBJECTTYPE * pObj ); // Flugente: no more needed, use HasAttachmentOfClass( pObj, AC_REMOTEDET ) instead
OBJECTTYPE* FindAttachedBatteries( OBJECTTYPE * pObj ); OBJECTTYPE* FindAttachedBatteries( OBJECTTYPE * pObj );
INT8 FindMedKit( SOLDIERTYPE * pSoldier ); INT8 FindMedKit( SOLDIERTYPE * pSoldier );
INT8 FindFirstAidKit( 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 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 (*pObj)[i]->data.bTemperature = newtemperature; // ... set new temperature
#if 0//def JA2TESTVERSION #if 0//def JA2TESTVERSION
@@ -12926,7 +12926,7 @@ void SOLDIERTYPE::SoldierInventoryCoolDown(void)
FLOAT cooldownfactor = GetItemCooldownFactor( &(*iter) ); // ... get cooldown factor ... 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 (*iter)[i]->data.bTemperature = newtemperature; // ... set new temperature
#if 0//def JA2TESTVERSION #if 0//def JA2TESTVERSION
+6 -2
View File
@@ -2582,11 +2582,15 @@ UINT8 GetActionModeCursor( SOLDIERTYPE *pSoldier )
// Detonators can only be on invalidcurs things... // Detonators can only be on invalidcurs things...
if ( ubCursor == INVALIDCURS ) if ( ubCursor == INVALIDCURS )
{ {
if ( IsDetonatorAttached( &(pSoldier->inv[HANDPOS]) ) ) if ( HasAttachmentOfClass( &(pSoldier->inv[HANDPOS]), AC_DETONATOR ) )
{ {
ubCursor = BOMBCURS; 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; ubCursor = BOMBCURS;
} }
+2
View File
@@ -378,6 +378,8 @@ typedef struct
UINT8 ubFragType; UINT8 ubFragType;
UINT16 ubFragDamage; UINT16 ubFragDamage;
UINT16 ubFragRange; 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; } EXPLOSIVETYPE;
//GLOBALS //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, "usNumFragments") == 0 || // HEADROCK HAM 5.1: Fragmenting explosive data
strcmp(name, "ubFragType") == 0 || strcmp(name, "ubFragType") == 0 ||
strcmp(name, "ubFragDamage") == 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; pData->curElement = ELEMENT_PROPERTY;
@@ -196,6 +198,18 @@ explosiveEndElementHandle(void *userData, const XML_Char *name)
pData->curExplosive.ubFragRange = (UINT16) atol(pData->szCharData); 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--; pData->maxReadDepth--;
} }
@@ -287,18 +301,25 @@ BOOLEAN WriteExplosiveStats()
FilePrintf(hFile,"\t<EXPLOSIVE>\r\n"); FilePrintf(hFile,"\t<EXPLOSIVE>\r\n");
FilePrintf(hFile,"\t\t<uiIndex>%d</uiIndex>\r\n", cnt ); 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<ubType>%d</ubType>\r\n", Explosive[cnt].ubType );
FilePrintf(hFile,"\t\t<ubDamage>%d</ubDamage>\r\n", Explosive[cnt].ubDamage ); 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<ubStunDamage>%d</ubStunDamage>\r\n", Explosive[cnt].ubStunDamage );
FilePrintf(hFile,"\t\t<ubRadius>%d</ubRadius>\r\n", Explosive[cnt].ubRadius ); 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<ubVolume>%d</ubVolume>\r\n", Explosive[cnt].ubVolume );
FilePrintf(hFile,"\t\t<ubVolatility>%d</ubVolatility>\r\n", Explosive[cnt].ubVolatility ); 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<ubAnimationID>%d</ubAnimationID>\r\n", Explosive[cnt].ubAnimationID );
FilePrintf(hFile,"\t\t<ubDuration>%d</ubDuration>\r\n", Explosive[cnt].ubDuration ); 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<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"); FilePrintf(hFile,"\t</EXPLOSIVE>\r\n");
} }
+1 -1
View File
@@ -32,7 +32,7 @@
// Defines // Defines
// HEADROCK HAM 5: Increasing... with the hope of making spectacular fragmenting explosives. // 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 // GLOBAL FOR FACES LISTING
+194 -45
View File
@@ -104,7 +104,7 @@ BOOLEAN ExpAffect( INT32 sBombGridNo, INT32 sGridNo, UINT32 uiDist, UINT16 usIte
UINT8 DetermineFlashbangEffect( SOLDIERTYPE *pSoldier, INT8 ubExplosionDir, BOOLEAN fInBuilding); UINT8 DetermineFlashbangEffect( SOLDIERTYPE *pSoldier, INT8 ubExplosionDir, BOOLEAN fInBuilding);
// HEADROCK HAM 5.1: Explosion Fragments launcher // HEADROCK HAM 5.1: Explosion Fragments launcher
void FireFragments( SOLDIERTYPE * pThrower, INT16 sX, INT16 sY, INT16 sZ, UINT16 usItem ); void FireFragments( SOLDIERTYPE * pThrower, INT16 sX, INT16 sY, INT16 sZ, UINT16 usItem, UINT8 ubDirection = DIRECTION_IRRELEVANT );
extern INT8 gbSAMGraphicList[ MAX_NUMBER_OF_SAMS ]; extern INT8 gbSAMGraphicList[ MAX_NUMBER_OF_SAMS ];
extern void AddToShouldBecomeHostileOrSayQuoteList( UINT8 ubID ); extern void AddToShouldBecomeHostileOrSayQuoteList( UINT8 ubID );
@@ -271,12 +271,12 @@ void RecountExplosions( void )
// GENERATE EXPLOSION // GENERATE EXPLOSION
void InternalIgniteExplosion( UINT8 ubOwner, INT16 sX, INT16 sY, INT16 sZ, INT32 sGridNo, UINT16 usItem, BOOLEAN fLocate, INT8 bLevel ) void InternalIgniteExplosion( UINT8 ubOwner, INT16 sX, INT16 sY, INT16 sZ, INT32 sGridNo, UINT16 usItem, BOOLEAN fLocate, INT8 bLevel, UINT8 ubDirection )
{ {
#ifdef JA2BETAVERSION #ifdef JA2BETAVERSION
if (is_networked) { if (is_networked) {
CHAR tmpMPDbgString[512]; CHAR tmpMPDbgString[512];
sprintf(tmpMPDbgString,"InternalIgniteExplosion ( ubOwner : %i , sX : %i , sY : %i , sZ : %i , sGridNo : %i , usItem : %i , fLocate : %i , bLevel : %i )\n",ubOwner, sX , sY , sZ , sGridNo , usItem , (int)fLocate , bLevel ); sprintf(tmpMPDbgString,"InternalIgniteExplosion ( ubOwner : %i , sX : %i , sY : %i , sZ : %i , sGridNo : %i , usItem : %i , fLocate : %i , bLevel : %i , ubDirection : %i )\n",ubOwner, sX , sY , sZ , sGridNo , usItem , (int)fLocate , bLevel, ubDirection );
MPDebugMsg(tmpMPDbgString); MPDebugMsg(tmpMPDbgString);
} }
#endif #endif
@@ -346,15 +346,15 @@ void InternalIgniteExplosion( UINT8 ubOwner, INT16 sX, INT16 sY, INT16 sZ, INT32
if (Explosive[ Item[ usItem ].ubClassIndex ].usNumFragments > 0 ) if (Explosive[ Item[ usItem ].ubClassIndex ].usNumFragments > 0 )
{ {
// HEADROCK HAM 5: Deactivated until the release of HAM 5.1. // HEADROCK HAM 5: Deactivated until the release of HAM 5.1.
FireFragments( MercPtrs[ubOwner], sX, sY, sZ, usItem ); FireFragments( MercPtrs[ubOwner], sX, sY, sZ, usItem, ubDirection );
} }
} }
void IgniteExplosion( UINT8 ubOwner, INT16 sX, INT16 sY, INT16 sZ, INT32 sGridNo, UINT16 usItem, INT8 bLevel ) void IgniteExplosion( UINT8 ubOwner, INT16 sX, INT16 sY, INT16 sZ, INT32 sGridNo, UINT16 usItem, INT8 bLevel, UINT8 ubDirection )
{ {
InternalIgniteExplosion( ubOwner, sX, sY, sZ, sGridNo, usItem, TRUE, bLevel ); InternalIgniteExplosion( ubOwner, sX, sY, sZ, sGridNo, usItem, TRUE, bLevel, ubDirection );
} }
void GenerateExplosion( EXPLOSION_PARAMS *pExpParams ) void GenerateExplosion( EXPLOSION_PARAMS *pExpParams )
@@ -3609,8 +3609,8 @@ void AddBombToQueue( UINT32 uiWorldBombIndex, UINT32 uiTimeStamp, BOOL fFromRemo
gfExplosionQueueActive = TRUE; gfExplosionQueueActive = TRUE;
} }
// Flugente: activate everything connected to a tripwire in the surrounding if sGridNo on level bLevel // Flugente: activate everything connected to a tripwire in the surrounding if sGridNo on level bLevel with regard to the tripwire netwrok and hierarchy determined by ubFlag
BOOLEAN ActivateSurroundingTripwire( UINT8 ubID, INT32 sGridNo, INT8 bLevel ) BOOLEAN ActivateSurroundingTripwire( UINT8 ubID, INT32 sGridNo, INT8 bLevel, UINT32 ubFlag )
{ {
UINT32 uiTimeStamp= GetJA2Clock(); UINT32 uiTimeStamp= GetJA2Clock();
BOOLEAN fFoundMine = FALSE; BOOLEAN fFoundMine = FALSE;
@@ -3644,29 +3644,63 @@ BOOLEAN ActivateSurroundingTripwire( UINT8 ubID, INT32 sGridNo, INT8 bLevel )
// tripwire just gets activated // tripwire just gets activated
if ( Item[pObj->usItem].tripwire == 1 ) if ( Item[pObj->usItem].tripwire == 1 )
{ {
OBJECTTYPE newtripwireObject; // determine this tripwire's flag
CreateItem( pObj->usItem, (*pObj)[0]->data.objectStatus, &newtripwireObject ); UINT32 ubWireNetworkFlag = (*pObj)[0]->data.ubWireNetworkFlag;
// this is important: delete the tripwire, otherwise we get into an infinite loop if there are two piecs of tripwire.... // check if a) tripwire belongs to the same tripwire network and b) its of the same or lower hierarchy level
RemoveItemFromPool( adjgrid, gWorldBombs[ uiWorldBombIndex ].iItemIndex, bLevel ); BOOLEAN samenetwork = FALSE;
BOOLEAN sameorlowerhierarchy = FALSE;
// if no other bomb exists here if ( ubWireNetworkFlag <= ubFlag ) // hierarchy of a group is sorted, so this suffices
if ( FindWorldItemForBombInGridNo(adjgrid, bLevel) == -1 ) sameorlowerhierarchy = TRUE;
if ( !sameorlowerhierarchy )
continue;
for (INT8 i = 0; i < 2; ++i) // 2 runs: first for enemy networks, second for player networks
{ {
// make sure no one thinks there is a bomb here any more! for (INT8 j = 0; j < 4; ++j)
if ( gpWorldLevelData[adjgrid].uiFlags & MAPELEMENT_PLAYER_MINE_PRESENT )
{ {
RemoveBlueFlag( adjgrid, bLevel ); UINT32 samenetworkflag = ( ENEMY_NET_1_LVL_1 | ENEMY_NET_1_LVL_2 | ENEMY_NET_1_LVL_3 | ENEMY_NET_1_LVL_4 ) << (16*i + j); // comparing with this flag will determine the network
if ( ( (ubFlag & samenetworkflag) != 0 ) && ( (ubWireNetworkFlag & samenetworkflag) != 0 ) )
samenetwork = TRUE;
if ( samenetwork )
break;
} }
gpWorldLevelData[adjgrid].uiFlags &= ~(MAPELEMENT_ENEMY_MINE_PRESENT);
} }
// no add a tripwire item to the floor, simulating that activating tripwire deactivates it if ( samenetwork && sameorlowerhierarchy )
AddItemToPool( adjgrid, &newtripwireObject, 1, bLevel, 0, -1 ); {
// if we have passed the check, our tripwire belongs to the same tripwirenetwork as the one that caused this call
// it is also of the sme or a lower hierarchy
// so, this wire calls other wires in the surrounding area. But the new flag is ubWireNetworkFlag instead of ubFlag, so the hierarchy level might be lower
// activate surrounding tripwires, unless tripwire is too much damaged and we are unlucky.. OBJECTTYPE newtripwireObject;
if ( newtripwireObject[0]->data.objectStatus > (INT16)Random(50) ) CreateItem( pObj->usItem, (*pObj)[0]->data.objectStatus, &newtripwireObject );
fFoundMine = ActivateSurroundingTripwire(ubID, adjgrid, bLevel);
// this is important: delete the tripwire, otherwise we get into an infinite loop if there are two piecs of tripwire....
RemoveItemFromPool( adjgrid, gWorldBombs[ uiWorldBombIndex ].iItemIndex, bLevel );
// if no other bomb exists here
if ( FindWorldItemForBombInGridNo(adjgrid, bLevel) == -1 )
{
// make sure no one thinks there is a bomb here any more!
if ( gpWorldLevelData[adjgrid].uiFlags & MAPELEMENT_PLAYER_MINE_PRESENT )
{
RemoveBlueFlag( adjgrid, bLevel );
}
gpWorldLevelData[adjgrid].uiFlags &= ~(MAPELEMENT_ENEMY_MINE_PRESENT);
}
// no add a tripwire item to the floor, simulating that activating tripwire deactivates it
AddItemToPool( adjgrid, &newtripwireObject, 1, bLevel, 0, -1 );
// activate surrounding tripwires, unless tripwire is too much damaged and we are unlucky..
if ( newtripwireObject[0]->data.objectStatus > (INT16)Random(50) )
fFoundMine = ActivateSurroundingTripwire(ubID, adjgrid, bLevel, ubWireNetworkFlag);
}
} }
// bombs go off // bombs go off
else else
@@ -3767,12 +3801,12 @@ void HandleExplosionQueue( void )
// bomb objects only store the SIDE who placed the bomb! :-( // bomb objects only store the SIDE who placed the bomb! :-(
if ( (*pObj)[0]->data.misc.ubBombOwner > 1 ) if ( (*pObj)[0]->data.misc.ubBombOwner > 1 )
{ {
IgniteExplosion( (UINT8) ((*pObj)[0]->data.misc.ubBombOwner - 2), CenterX( sGridNo ), CenterY( sGridNo ), 0, sGridNo, (*pObj)[0]->data.misc.usBombItem, ubLevel ); IgniteExplosion( (UINT8) ((*pObj)[0]->data.misc.ubBombOwner - 2), CenterX( sGridNo ), CenterY( sGridNo ), 0, sGridNo, (*pObj)[0]->data.misc.usBombItem, ubLevel, (*pObj)[0]->data.ubDirection );
} }
else else
{ {
// pre-placed // pre-placed
IgniteExplosion( NOBODY, CenterX( sGridNo ), CenterY( sGridNo ), 0, sGridNo, (*pObj)[0]->data.misc.usBombItem, ubLevel ); IgniteExplosion( NOBODY, CenterX( sGridNo ), CenterY( sGridNo ), 0, sGridNo, (*pObj)[0]->data.misc.usBombItem, ubLevel, (*pObj)[0]->data.ubDirection );
} }
} }
@@ -3895,6 +3929,18 @@ void SetOffBombsByFrequency( UINT8 ubID, INT8 bFrequency )
uiTimeStamp = GetJA2Clock(); uiTimeStamp = GetJA2Clock();
// Flugente: The remote detonator can now detonate _or_ defuse bombs.
// In order for a bomb do be detonated, it must have a remote detonator attached. If a 'detonate' command was clicked, bFrequency will be out of 1 - 4.
// In order for a bomb do be detonated, it must have a remote defuse attached. If a 'defuse' command was clicked, bFrequency will be out of 5 - 8.
BOOLEAN fDetonate = TRUE;
// if bFrequency is in 5-8, it must have been a 'defuse' command. Change for correct frequency;
if ( bFrequency > 4 && bFrequency < 9)
{
fDetonate = FALSE;
bFrequency -= 4;
}
// Go through all the bombs in the world, and look for remote ones // Go through all the bombs in the world, and look for remote ones
for (uiWorldBombIndex = 0; uiWorldBombIndex < guiNumWorldBombs; uiWorldBombIndex++) for (uiWorldBombIndex = 0; uiWorldBombIndex < guiNumWorldBombs; uiWorldBombIndex++)
{ {
@@ -3904,27 +3950,74 @@ void SetOffBombsByFrequency( UINT8 ubID, INT8 bFrequency )
if ( (*pObj)[0]->data.misc.bDetonatorType == BOMB_REMOTE && !((*pObj).fFlags & OBJECT_DISABLED_BOMB) ) if ( (*pObj)[0]->data.misc.bDetonatorType == BOMB_REMOTE && !((*pObj).fFlags & OBJECT_DISABLED_BOMB) )
{ {
// Found a remote bomb, so check to see if it has the same frequency // Found a remote bomb, so check to see if it has the same frequency
if ((*pObj)[0]->data.misc.bFrequency == bFrequency) if ( fDetonate ) // detonate bombs
{ {
// SANDRO - added merc records and some exp // Found a remote bomb, so check to see if it has the same frequency
if ( ((*pObj)[0]->data.misc.ubBombOwner) > 1 ) if ((*pObj)[0]->data.misc.bFrequency == bFrequency)
{ {
if ( MercPtrs[((*pObj)[0]->data.misc.ubBombOwner - 2)]->ubProfile != NO_PROFILE && // SANDRO - added merc records and some exp
MercPtrs[((*pObj)[0]->data.misc.ubBombOwner - 2)]->bTeam == gbPlayerNum ) if ( ((*pObj)[0]->data.misc.ubBombOwner) > 1 )
{ {
gMercProfiles[MercPtrs[((*pObj)[0]->data.misc.ubBombOwner - 2)]->ubProfile].records.usExpDetonated++; if ( MercPtrs[((*pObj)[0]->data.misc.ubBombOwner - 2)]->ubProfile != NO_PROFILE &&
MercPtrs[((*pObj)[0]->data.misc.ubBombOwner - 2)]->bTeam == gbPlayerNum )
{
gMercProfiles[MercPtrs[((*pObj)[0]->data.misc.ubBombOwner - 2)]->ubProfile].records.usExpDetonated++;
StatChange( MercPtrs[((*pObj)[0]->data.misc.ubBombOwner - 2)], EXPLODEAMT, ( 5 ), FALSE ); StatChange( MercPtrs[((*pObj)[0]->data.misc.ubBombOwner - 2)], EXPLODEAMT, ( 5 ), FALSE );
}
}
gubPersonToSetOffExplosions = ubID;
// put this bomb on the queue
AddBombToQueue( uiWorldBombIndex, uiTimeStamp );
if (pObj->usItem != ACTION_ITEM || (*pObj)[0]->data.misc.bActionValue == ACTION_ITEM_BLOW_UP)
{
uiTimeStamp += BOMB_QUEUE_DELAY;
} }
} }
}
gubPersonToSetOffExplosions = ubID; else // defuse bombs
{
// put this bomb on the queue // check for frequency
AddBombToQueue( uiWorldBombIndex, uiTimeStamp ); if ((*pObj)[0]->data.bDefuseFrequency == bFrequency)
if (pObj->usItem != ACTION_ITEM || (*pObj)[0]->data.misc.bActionValue == ACTION_ITEM_BLOW_UP)
{ {
uiTimeStamp += BOMB_QUEUE_DELAY; // check for a defuse
if ( HasAttachmentOfClass(pObj, AC_DEFUSE) )
{
(*pObj)[0]->data.bTrap = 0;
if ( (*pObj).fFlags & OBJECT_KNOWN_TO_BE_TRAPPED )
pObj->fFlags &= ~( OBJECT_KNOWN_TO_BE_TRAPPED );
if ( (*pObj).fFlags & OBJECT_ARMED_BOMB )
pObj->fFlags &= ~( OBJECT_ARMED_BOMB );
if ( !((*pObj).fFlags & OBJECT_DISABLED_BOMB) )
pObj->fFlags |= OBJECT_DISABLED_BOMB ;
INT32 sGridNo = gWorldItems[ gWorldBombs[uiWorldBombIndex].iItemIndex ].sGridNo;
UINT8 ubLevel = gWorldItems[ gWorldBombs[uiWorldBombIndex].iItemIndex ].ubLevel;
// OJW - 20091029 - disarm explosives
if (is_networked && is_client)
send_disarm_explosive( sGridNo , gWorldBombs[uiWorldBombIndex].iItemIndex, ubID );
// set back ubWireNetworkFlag and bDefuseFrequency, but not the direction... bomb is still aimed, it is just turned off
(*pObj)[0]->data.ubWireNetworkFlag = 0;
(*pObj)[0]->data.bDefuseFrequency = 0;
//create a new item: copy the old item
OBJECTTYPE newbombitem( *pObj );
// place item on the floor
AddItemToPool( sGridNo, &newbombitem, 1, ubLevel, 0, -1 );
// remove old item
RemoveItemFromPool( sGridNo, gWorldBombs[uiWorldBombIndex].iItemIndex, ubLevel );
// TODO remove bomb from queue...
}
} }
} }
} }
@@ -4019,6 +4112,9 @@ BOOLEAN SetOffBombsInGridNo( UINT8 ubID, INT32 sGridNo, BOOLEAN fAllBombs, INT8
OBJECTTYPE newtripwireObject; OBJECTTYPE newtripwireObject;
CreateItem( pObj->usItem, (*pObj)[0]->data.objectStatus, &newtripwireObject ); CreateItem( pObj->usItem, (*pObj)[0]->data.objectStatus, &newtripwireObject );
// determine this tripwire's flag
UINT32 ubWireNetworkFlag = (*pObj)[0]->data.ubWireNetworkFlag;
// this is important: delete the tripwire, otherwise we get into an infinite loop if there are two piecs of tripwire.... // this is important: delete the tripwire, otherwise we get into an infinite loop if there are two piecs of tripwire....
RemoveItemFromPool( sGridNo, gWorldBombs[ uiWorldBombIndex ].iItemIndex, bLevel ); RemoveItemFromPool( sGridNo, gWorldBombs[ uiWorldBombIndex ].iItemIndex, bLevel );
@@ -4038,7 +4134,7 @@ BOOLEAN SetOffBombsInGridNo( UINT8 ubID, INT32 sGridNo, BOOLEAN fAllBombs, INT8
// activate surrounding tripwires and tripwire-activated mines, unless tripwire is too much damaged and we are unlucky.. // activate surrounding tripwires and tripwire-activated mines, unless tripwire is too much damaged and we are unlucky..
if ( newtripwireObject[0]->data.objectStatus > (INT16)Random(50) ) if ( newtripwireObject[0]->data.objectStatus > (INT16)Random(50) )
fFoundMine = ActivateSurroundingTripwire(ubID, sGridNo, bLevel); fFoundMine = ActivateSurroundingTripwire(ubID, sGridNo, bLevel, ubWireNetworkFlag);
} }
else else
{ {
@@ -4482,18 +4578,71 @@ UINT8 DetermineFlashbangEffect( SOLDIERTYPE *pSoldier, INT8 ubExplosionDir, BOOL
// HEADROCK HAM 5.1: This handles launching fragments out of an explosion. The number of fragments is read from // HEADROCK HAM 5.1: This handles launching fragments out of an explosion. The number of fragments is read from
// the Explosives.XML file, and they each have a set amount of damage and range as well. They are currently // the Explosives.XML file, and they each have a set amount of damage and range as well. They are currently
// fired at completely random trajectories. // fired at completely random trajectories.
void FireFragments( SOLDIERTYPE * pThrower, INT16 sX, INT16 sY, INT16 sZ, UINT16 usItem ) void FireFragments( SOLDIERTYPE * pThrower, INT16 sX, INT16 sY, INT16 sZ, UINT16 usItem, UINT8 ubDirection )
{ {
UINT16 usNumFragments = Explosive[Item[usItem].ubClassIndex].usNumFragments; UINT16 usNumFragments = Explosive[Item[usItem].ubClassIndex].usNumFragments;
UINT16 ubFragRange = Explosive[Item[usItem].ubClassIndex].ubFragRange; UINT16 ubFragRange = Explosive[Item[usItem].ubClassIndex].ubFragRange;
AssertMsg( ubFragRange > 0 , "Fragmentation data lacks range property!" ); AssertMsg( ubFragRange > 0 , "Fragmentation data lacks range property!" );
for (UINT16 x = 0; x < usNumFragments; x++) for (UINT16 x = 0; x < usNumFragments; ++x)
{ {
FLOAT dRandomX = ((FLOAT)Random(2000) / 1000.0f) - 1.0f; FLOAT dRandomX = 0;
FLOAT dRandomY = ((FLOAT)Random(2000) / 1000.0f) - 1.0f; FLOAT dRandomY = 0;
FLOAT dRandomZ = ((FLOAT)Random(2000) / 1000.0f) - 1.0f; FLOAT dRandomZ = 0;
// if explosive is directional, calculation of frags is different
if ( Item[usItem].directional == TRUE )
{
// Flugente: if item is a directional explosive, determine in what direction the frags should fly
INT16 degree = (45 + ubDirection * 45) % 360; // modulo 360 to prevent nonsense from nonsensical input
INT16 horizontalarc = Explosive[Item[usItem].ubClassIndex].ubHorizontalDegree % 360; // modulo 360 to prevent nonsense from nonsensical input
INT16 halfhorizontalarc = (INT16)(horizontalarc / 2);
INT16 sLowHorizontalD = (360 + degree - halfhorizontalarc) % 360;
INT16 dRandomDegreeH = (sLowHorizontalD + Random(horizontalarc) ) % 360;
// transform the degree into our coordinates
if ( dRandomDegreeH < 90 )
{
dRandomX = (FLOAT)dRandomDegreeH / 45.0f;
dRandomY = 0.0;
}
else if ( dRandomDegreeH < 180 )
{
dRandomX = (FLOAT)2.0;
dRandomY = (FLOAT)(dRandomDegreeH - 90 ) / 45.0f;
}
else if ( dRandomDegreeH < 270 )
{
dRandomX = (FLOAT)(270 - dRandomDegreeH) / 45.0f;
dRandomY = (FLOAT)2.0;
}
else
{
dRandomX = 0.0;
dRandomY = (FLOAT)(360 - dRandomDegreeH) / 45.0f;
}
// X and Y now need to be distributed, at the moment they are on a circle
// project into [-1.0, 1.0]
dRandomX -= 1.0f;
dRandomY -= 1.0f;
// vertical stuff
INT16 verticalarc = Explosive[Item[usItem].ubClassIndex].ubVerticalDegree % 180; // modulo 180 to prevent nonsense from nonsensical input
INT16 halfverticalarc = (INT16)(verticalarc / 2);
INT16 sLowVerticalD = (90 - halfverticalarc) % 180;
INT16 dRandomDegreeV = sLowVerticalD + Random(verticalarc);
dRandomZ = ((FLOAT)(dRandomDegreeV) / 90.0f) - 1.0f;
}
else
{
dRandomX = ((FLOAT)Random(2000) / 1000.0f) - 1.0f;
dRandomY = ((FLOAT)Random(2000) / 1000.0f) - 1.0f;
dRandomZ = ((FLOAT)Random(2000) / 1000.0f) - 1.0f;
}
FLOAT dDeltaX = (dRandomX * ubFragRange); FLOAT dDeltaX = (dRandomX * ubFragRange);
FLOAT dDeltaY = (dRandomY * ubFragRange); FLOAT dDeltaY = (dRandomY * ubFragRange);
+4 -4
View File
@@ -98,8 +98,8 @@ extern EXPLOSIONTYPE gExplosionData[ NUM_EXPLOSION_SLOTS ];
extern UINT8 gubElementsOnExplosionQueue; extern UINT8 gubElementsOnExplosionQueue;
extern BOOLEAN gfExplosionQueueActive; extern BOOLEAN gfExplosionQueueActive;
void IgniteExplosion( UINT8 ubOwner, INT16 sX, INT16 sY, INT16 sZ, INT32 sGridNo, UINT16 usItem, INT8 bLevel ); void IgniteExplosion( UINT8 ubOwner, INT16 sX, INT16 sY, INT16 sZ, INT32 sGridNo, UINT16 usItem, INT8 bLevel, UINT8 ubDirection = DIRECTION_IRRELEVANT );
void InternalIgniteExplosion( UINT8 ubOwner, INT16 sX, INT16 sY, INT16 sZ, INT32 sGridNo, UINT16 usItem, BOOLEAN fLocate, INT8 bLevel ); void InternalIgniteExplosion( UINT8 ubOwner, INT16 sX, INT16 sY, INT16 sZ, INT32 sGridNo, UINT16 usItem, BOOLEAN fLocate, INT8 bLevel, UINT8 ubDirection = DIRECTION_IRRELEVANT );
void GenerateExplosion( EXPLOSION_PARAMS *pExpParams ); void GenerateExplosion( EXPLOSION_PARAMS *pExpParams );
@@ -133,8 +133,8 @@ BOOLEAN DishOutGasDamage( SOLDIERTYPE * pSoldier, EXPLOSIVETYPE * pExplosive, IN
void SpreadEffect( INT32 sGridNo, UINT8 ubRadius, UINT16 usItem, UINT8 ubOwner, BOOLEAN fSubsequent, INT8 bLevel, INT32 iSmokeEffectNum , BOOL fFromRemoteClient = FALSE , BOOL fNewSmokeEffect = FALSE ); void SpreadEffect( INT32 sGridNo, UINT8 ubRadius, UINT16 usItem, UINT8 ubOwner, BOOLEAN fSubsequent, INT8 bLevel, INT32 iSmokeEffectNum , BOOL fFromRemoteClient = FALSE , BOOL fNewSmokeEffect = FALSE );
void AddBombToQueue( UINT32 uiWorldBombIndex, UINT32 uiTimeStamp, BOOL fFromRemoteClient = FALSE ); void AddBombToQueue( UINT32 uiWorldBombIndex, UINT32 uiTimeStamp, BOOL fFromRemoteClient = FALSE );
// Flugente: activate everything connected to a tripwire in the surrounding if sGridNo on level bLevel // Flugente: activate everything connected to a tripwire in the surrounding if sGridNo on level bLevel with regard to the tripwire netwrok and hierarchy determined by ubFlag
BOOLEAN ActivateSurroundingTripwire( UINT8 ubID, INT32 sGridNo, INT8 bLevel ); BOOLEAN ActivateSurroundingTripwire( UINT8 ubID, INT32 sGridNo, INT8 bLevel, UINT32 ubFlag );
extern void ToggleActionItemsByFrequency( INT8 bFrequency ); extern void ToggleActionItemsByFrequency( INT8 bFrequency );
extern void PerformItemAction( INT32 sGridNo, OBJECTTYPE * pObj ); extern void PerformItemAction( INT32 sGridNo, OBJECTTYPE * pObj );
+8
View File
@@ -801,6 +801,14 @@ enum
NO_LOS_TO_TALK_TARGET, NO_LOS_TO_TALK_TARGET,
ATTACHMENT_REMOVED, ATTACHMENT_REMOVED,
VEHICLE_CAN_NOT_BE_ADDED, VEHICLE_CAN_NOT_BE_ADDED,
// added by Flugente for defusing/setting up trap networks
CHOOSE_BOMB_OR_DEFUSE_FREQUENCY_STR,
CHOOSE_REMOTE_DEFUSE_FREQUENCY_STR,
CHOOSE_REMOTE_DETONATE_AND_REMOTE_DEFUSE_FREQUENCY_STR,
CHOOSE_DETONATE_AND_REMOTE_DEFUSE_FREQUENCY_STR,
CHOOSE_TRIPWIRE_NETWORK,
TEXT_NUM_TACTICAL_STR TEXT_NUM_TACTICAL_STR
}; };
+7
View File
@@ -259,6 +259,7 @@ itemStartElementHandle(void *userData, const XML_Char *name, const XML_Char **at
strcmp(name, "AttachmentClass") == 0 || strcmp(name, "AttachmentClass") == 0 ||
strcmp(name, "TripWireActivation") == 0 || strcmp(name, "TripWireActivation") == 0 ||
strcmp(name, "TripWire") == 0 || strcmp(name, "TripWire") == 0 ||
strcmp(name, "Directional") == 0 ||
strcmp(name, "fFlags") == 0 )) strcmp(name, "fFlags") == 0 ))
{ {
@@ -1295,6 +1296,11 @@ itemEndElementHandle(void *userData, const XML_Char *name)
pData->curElement = ELEMENT; pData->curElement = ELEMENT;
pData->curItem.tripwire = (BOOLEAN) atol(pData->szCharData); pData->curItem.tripwire = (BOOLEAN) atol(pData->szCharData);
} }
else if(strcmp(name, "Directional") == 0)
{
pData->curElement = ELEMENT;
pData->curItem.directional = (BOOLEAN) atol(pData->szCharData);
}
pData->maxReadDepth--; pData->maxReadDepth--;
} }
@@ -1904,6 +1910,7 @@ BOOLEAN WriteItemStats()
FilePrintf(hFile,"\t\t<TripwireActivation>%d</TripwireActivation>\r\n", Item[cnt].tripwireactivation ); FilePrintf(hFile,"\t\t<TripwireActivation>%d</TripwireActivation>\r\n", Item[cnt].tripwireactivation );
FilePrintf(hFile,"\t\t<TripWire>%d</TripWire>\r\n", Item[cnt].tripwire ); FilePrintf(hFile,"\t\t<TripWire>%d</TripWire>\r\n", Item[cnt].tripwire );
FilePrintf(hFile,"\t\t<Directional>%d</Directional>\r\n", Item[cnt].directional );
FilePrintf(hFile,"\t</ITEM>\r\n"); FilePrintf(hFile,"\t</ITEM>\r\n");
} }
+7
View File
@@ -2913,6 +2913,13 @@ CHAR16 TacticalStr[][ MED_STRING_LENGTH ] =
L"%s看不见%s。", // Cannot see person trying to talk to L"%s看不见%s。", // Cannot see person trying to talk to
L"附件被移除", L"附件被移除",
L"你已经有了两辆车,无法拥有更多的车辆。", L"你已经有了两辆车,无法拥有更多的车辆。",
// added by Flugente for defusing/setting up trap networks // TODO.Translate
L"Choose detonation frequency (1 - 4) or defuse frequency (A - D):",
L"Set defusing frequency:",
L"Set detonation frequency (1 - 4) and defusing frequency (A - D):",
L"Set detonation time in turns (1 - 4) and defusing frequency (A - D):",
L"Select tripwire hierarchy (1 - 4) and network (A - D):",
}; };
//Varying helptext explains (for the "Go to Sector/Map" checkbox) what will happen given different circumstances in the "exiting sector" interface. //Varying helptext explains (for the "Go to Sector/Map" checkbox) what will happen given different circumstances in the "exiting sector" interface.
+7
View File
@@ -2910,6 +2910,13 @@ CHAR16 TacticalStr[][ MED_STRING_LENGTH ] =
L"%s kan %s niet zien.", // Cannot see person trying to talk to L"%s kan %s niet zien.", // Cannot see person trying to talk to
L"Attachment removed", L"Attachment removed",
L"Kan niet een ander voertuig bereiken aangezien u reeds 2 hebt", L"Kan niet een ander voertuig bereiken aangezien u reeds 2 hebt",
// added by Flugente for defusing/setting up trap networks // TODO.Translate
L"Choose detonation frequency (1 - 4) or defuse frequency (A - D):",
L"Set defusing frequency:",
L"Set detonation frequency (1 - 4) and defusing frequency (A - D):",
L"Set detonation time in turns (1 - 4) and defusing frequency (A - D):",
L"Select tripwire hierarchy (1 - 4) and network (A - D):",
}; };
//Varying helptext explains (for the "Go to Sector/Map" checkbox) what will happen given different circumstances in the "exiting sector" interface. //Varying helptext explains (for the "Go to Sector/Map" checkbox) what will happen given different circumstances in the "exiting sector" interface.
+7
View File
@@ -2913,6 +2913,13 @@ CHAR16 TacticalStr[][ MED_STRING_LENGTH ] =
L"%s cannot see %s.", // Cannot see person trying to talk to L"%s cannot see %s.", // Cannot see person trying to talk to
L"Attachment removed", L"Attachment removed",
L"Can not gain another vehicle as you already have 2", L"Can not gain another vehicle as you already have 2",
// added by Flugente for defusing/setting up trap networks
L"Choose detonation frequency (1 - 4) or defuse frequency (A - D):",
L"Set defusing frequency:",
L"Set detonation frequency (1 - 4) and defusing frequency (A - D):",
L"Set detonation time in turns (1 - 4) and defusing frequency (A - D):",
L"Select tripwire hierarchy (1 - 4) and network (A - D):",
}; };
//Varying helptext explains (for the "Go to Sector/Map" checkbox) what will happen given different circumstances in the "exiting sector" interface. //Varying helptext explains (for the "Go to Sector/Map" checkbox) what will happen given different circumstances in the "exiting sector" interface.
+7
View File
@@ -2912,6 +2912,13 @@ CHAR16 TacticalStr[][ MED_STRING_LENGTH ] =
L"%s ne peut pas voir %s.", // Cannot see person trying to talk to L"%s ne peut pas voir %s.", // Cannot see person trying to talk to
L"Accessoire retiré", L"Accessoire retiré",
L"Ne peut pas gagner un autre véhicule car vous en avez déjà 2", L"Ne peut pas gagner un autre véhicule car vous en avez déjà 2",
// added by Flugente for defusing/setting up trap networks // TODO.Translate
L"Choose detonation frequency (1 - 4) or defuse frequency (A - D):",
L"Set defusing frequency:",
L"Set detonation frequency (1 - 4) and defusing frequency (A - D):",
L"Set detonation time in turns (1 - 4) and defusing frequency (A - D):",
L"Select tripwire hierarchy (1 - 4) and network (A - D):",
}; };
//Varying helptext explains (for the "Go to Sector/Map" checkbox) what will happen given different circumstances in the "exiting sector" interface. //Varying helptext explains (for the "Go to Sector/Map" checkbox) what will happen given different circumstances in the "exiting sector" interface.
+7
View File
@@ -2917,6 +2917,13 @@ CHAR16 TacticalStr[][ MED_STRING_LENGTH ] =
L"%s kann %s nicht sehen.", // Cannot see person trying to talk to L"%s kann %s nicht sehen.", // Cannot see person trying to talk to
L"Anbringung entfernt", L"Anbringung entfernt",
L"Sie können kein weiteres Fahrzeug mehr verwenden, da Sie bereits 2 haben", L"Sie können kein weiteres Fahrzeug mehr verwenden, da Sie bereits 2 haben",
// added by Flugente for defusing/setting up trap networks // TODO.Translate
L"Choose detonation frequency (1 - 4) or defuse frequency (A - D):",
L"Set defusing frequency:",
L"Set detonation frequency (1 - 4) and defusing frequency (A - D):",
L"Set detonation time in turns (1 - 4) and defusing frequency (A - D):",
L"Select tripwire hierarchy (1 - 4) and network (A - D):",
}; };
//Varying helptext explains (for the "Go to Sector/Map" checkbox) what will happen given different circumstances in the "exiting sector" interface. //Varying helptext explains (for the "Go to Sector/Map" checkbox) what will happen given different circumstances in the "exiting sector" interface.
+7 -1
View File
@@ -2897,7 +2897,6 @@ CHAR16 TacticalStr[][ MED_STRING_LENGTH ] =
L"Il veicolo può viaggiare solo tra i settori", L"Il veicolo può viaggiare solo tra i settori",
L"Non è in grado di fasciarsi da solo ora", L"Non è in grado di fasciarsi da solo ora",
L"Sentiero bloccato per %s", L"Sentiero bloccato per %s",
// L"I tuoi mercenari, che erano stati catturati dall'esercito di Deidranna, sono stati imprigionati qui!",
L"I mercenari catturati dall'esercito di Deidranna, sono stati imprigionati qui!", L"I mercenari catturati dall'esercito di Deidranna, sono stati imprigionati qui!",
L"Serratura manomessa", L"Serratura manomessa",
L"Serratura distrutta", L"Serratura distrutta",
@@ -2906,6 +2905,13 @@ CHAR16 TacticalStr[][ MED_STRING_LENGTH ] =
L"%s non riesce a vedere %s.", // Cannot see person trying to talk to L"%s non riesce a vedere %s.", // Cannot see person trying to talk to
L"Attachment removed", L"Attachment removed",
L"Non può guadagnare un altro veicolo poichè già avete 2", L"Non può guadagnare un altro veicolo poichè già avete 2",
// added by Flugente for defusing/setting up trap networks // TODO.Translate
L"Choose detonation frequency (1 - 4) or defuse frequency (A - D):",
L"Set defusing frequency:",
L"Set detonation frequency (1 - 4) and defusing frequency (A - D):",
L"Set detonation time in turns (1 - 4) and defusing frequency (A - D):",
L"Select tripwire hierarchy (1 - 4) and network (A - D):",
}; };
//Varying helptext explains (for the "Go to Sector/Map" checkbox) what will happen given different circumstances in the "exiting sector" interface. //Varying helptext explains (for the "Go to Sector/Map" checkbox) what will happen given different circumstances in the "exiting sector" interface.
+7
View File
@@ -2920,6 +2920,13 @@ CHAR16 TacticalStr[][ MED_STRING_LENGTH ] =
L"%s nie widzi - %s.", // Cannot see person trying to talk to L"%s nie widzi - %s.", // Cannot see person trying to talk to
L"Dodatek usunięty", L"Dodatek usunięty",
L"Nie możesz zdobyć kolejnego pojazdu, ponieważ posiadasz już 2", L"Nie możesz zdobyć kolejnego pojazdu, ponieważ posiadasz już 2",
// added by Flugente for defusing/setting up trap networks // TODO.Translate
L"Choose detonation frequency (1 - 4) or defuse frequency (A - D):",
L"Set defusing frequency:",
L"Set detonation frequency (1 - 4) and defusing frequency (A - D):",
L"Set detonation time in turns (1 - 4) and defusing frequency (A - D):",
L"Select tripwire hierarchy (1 - 4) and network (A - D):",
}; };
//Varying helptext explains (for the "Go to Sector/Map" checkbox) what will happen given different circumstances in the "exiting sector" interface. //Varying helptext explains (for the "Go to Sector/Map" checkbox) what will happen given different circumstances in the "exiting sector" interface.
+7
View File
@@ -2913,6 +2913,13 @@ CHAR16 TacticalStr[][ MED_STRING_LENGTH ] =
L"%s не видит %s.", // Cannot see person trying to talk to L"%s не видит %s.", // Cannot see person trying to talk to
L"Навеска снята", L"Навеска снята",
L"Вы не можете содержать еще одну машину, довольствуйтесь уже имеющимися двумя.", L"Вы не можете содержать еще одну машину, довольствуйтесь уже имеющимися двумя.",
// added by Flugente for defusing/setting up trap networks // TODO.Translate
L"Choose detonation frequency (1 - 4) or defuse frequency (A - D):",
L"Set defusing frequency:",
L"Set detonation frequency (1 - 4) and defusing frequency (A - D):",
L"Set detonation time in turns (1 - 4) and defusing frequency (A - D):",
L"Select tripwire hierarchy (1 - 4) and network (A - D):",
}; };
//Varying helptext explains (for the "Go to Sector/Map" checkbox) what will happen given different circumstances in the "exiting sector" interface. //Varying helptext explains (for the "Go to Sector/Map" checkbox) what will happen given different circumstances in the "exiting sector" interface.
+7
View File
@@ -2914,6 +2914,13 @@ CHAR16 TacticalStr[][ MED_STRING_LENGTH ] =
L"%s cannot see %s.", // Cannot see person trying to talk to L"%s cannot see %s.", // Cannot see person trying to talk to
L"Attachment removed", L"Attachment removed",
L"Can not gain another vehicle as you already have 2", L"Can not gain another vehicle as you already have 2",
// added by Flugente for defusing/setting up trap networks // TODO.Translate
L"Choose detonation frequency (1 - 4) or defuse frequency (A - D):",
L"Set defusing frequency:",
L"Set detonation frequency (1 - 4) and defusing frequency (A - D):",
L"Set detonation time in turns (1 - 4) and defusing frequency (A - D):",
L"Select tripwire hierarchy (1 - 4) and network (A - D):",
}; };
//Varying helptext explains (for the "Go to Sector/Map" checkbox) what will happen given different circumstances in the "exiting sector" interface. //Varying helptext explains (for the "Go to Sector/Map" checkbox) what will happen given different circumstances in the "exiting sector" interface.