From 20d677c51924d31a0707387c533b19bbd95ef22e Mon Sep 17 00:00:00 2001 From: Wanne Date: Fri, 20 Apr 2012 10:40:16 +0000 Subject: [PATCH] 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 1 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 and 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 and are not used anymore, as those properties can be set via flags in . 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 --- MessageBoxScreen.cpp | 266 ++++++++++++++++++++++++++----- MessageBoxScreen.h | 5 +- Multiplayer/client.cpp | 4 + Tactical/DisplayCover.cpp | 259 +++++++++++++++++++++++++----- Tactical/DisplayCover.h | 2 +- Tactical/Handle Items.cpp | 99 +++++++++--- Tactical/Item Types.cpp | 13 ++ Tactical/Item Types.h | 50 ++++++ Tactical/Items.cpp | 112 ++++++++++--- Tactical/Items.h | 6 +- Tactical/Soldier Control.cpp | 4 +- Tactical/UI Cursors.cpp | 8 +- Tactical/Weapons.h | 2 + Tactical/XML_Explosive.cpp | 43 +++-- Tactical/bullets.cpp | 2 +- TileEngine/Explosion Control.cpp | 247 ++++++++++++++++++++++------ TileEngine/Explosion Control.h | 8 +- Utils/Text.h | 8 + Utils/XML_Items.cpp | 7 + Utils/_ChineseText.cpp | 7 + Utils/_DutchText.cpp | 7 + Utils/_EnglishText.cpp | 7 + Utils/_FrenchText.cpp | 7 + Utils/_GermanText.cpp | 7 + Utils/_ItalianText.cpp | 8 +- Utils/_PolishText.cpp | 7 + Utils/_RussianText.cpp | 7 + Utils/_TaiwaneseText.cpp | 7 + 28 files changed, 1012 insertions(+), 197 deletions(-) diff --git a/MessageBoxScreen.cpp b/MessageBoxScreen.cpp index 052b68a4..55ba137a 100644 --- a/MessageBoxScreen.cpp +++ b/MessageBoxScreen.cpp @@ -215,8 +215,15 @@ INT32 DoMessageBox( UINT8 ubStyle, const STR16 zString, UINT32 uiExitScreen, UIN gMsgBox.fRenderBox = TRUE; 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 - 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 ) { @@ -348,11 +355,117 @@ INT32 DoMessageBox( UINT8 ubStyle, const STR16 zString, UINT32 uiExitScreen, UIN DEFAULT_MOVE_CALLBACK, (GUI_CALLBACK)NumberedMsgBoxCallback ); MSYS_SetBtnUserData( gMsgBox.uiButton[3], 0, 4); 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) { @@ -853,10 +966,24 @@ UINT32 ExitMsgBox( INT8 ubExitCode ) //Delete buttons! if ( gMsgBox.usFlags & MSG_BOX_FLAG_FOUR_NUMBERED_BUTTONS ) { - RemoveButton( gMsgBox.uiButton[0] ); - RemoveButton( gMsgBox.uiButton[1] ); - RemoveButton( gMsgBox.uiButton[2] ); - RemoveButton( gMsgBox.uiButton[3] ); + for (UINT8 i = 0; i < 4; ++i) + { + RemoveButton( gMsgBox.uiButton[i] ); + } + } + 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 else if (gMsgBox.usFlags & MSG_BOX_FLAG_INPUTBOX) @@ -1079,10 +1206,24 @@ UINT32 MessageBoxScreenHandle( ) { if ( gMsgBox.usFlags & MSG_BOX_FLAG_FOUR_NUMBERED_BUTTONS ) { - MarkAButtonDirty( gMsgBox.uiButton[0] ); - MarkAButtonDirty( gMsgBox.uiButton[1] ); - MarkAButtonDirty( gMsgBox.uiButton[2] ); - MarkAButtonDirty( gMsgBox.uiButton[3] ); + for (UINT8 i = 0; i < 4; ++i) + { + MarkAButtonDirty( gMsgBox.uiButton[i] ); + } + } + 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 ) @@ -1227,39 +1368,82 @@ UINT32 MessageBoxScreenHandle( ) 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 - 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; + 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; + } + } + } } } diff --git a/MessageBoxScreen.h b/MessageBoxScreen.h index cb7109af..72e8ebb3 100644 --- a/MessageBoxScreen.h +++ b/MessageBoxScreen.h @@ -18,6 +18,9 @@ #define MSG_BOX_FLAG_GENERIC 0x0800 // 2 user-defined text buttons // OJW - Adding text chatbox #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 #define MSG_BOX_RETURN_OK 1 // ENTER or on OK button @@ -66,7 +69,7 @@ typedef struct }; struct { - UINT32 uiButton[4]; + UINT32 uiButton[16]; }; }; BOOLEAN fRenderBox; diff --git a/Multiplayer/client.cpp b/Multiplayer/client.cpp index 15e2f6c5..d3528058 100644 --- a/Multiplayer/client.cpp +++ b/Multiplayer/client.cpp @@ -3067,6 +3067,10 @@ void recievePLANTEXPLOSIVE (RPCParameters *rpcParameters) else (*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 // loop through world bombs and find the one linked to the item we just created UINT32 uiCount; diff --git a/Tactical/DisplayCover.cpp b/Tactical/DisplayCover.cpp index a7e31131..653433fa 100644 --- a/Tactical/DisplayCover.cpp +++ b/Tactical/DisplayCover.cpp @@ -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 } } } diff --git a/Tactical/DisplayCover.h b/Tactical/DisplayCover.h index 068b686a..e5d5cd3e 100644 --- a/Tactical/DisplayCover.h +++ b/Tactical/DisplayCover.h @@ -47,6 +47,6 @@ void SwitchMineViewOff(); void ToggleTrapNetworkView(); void ToggleHostileTrapsView(); -void SwitchMinesDrawMode(); +void SwitchMinesDrawModeForNetworks(); #endif diff --git a/Tactical/Handle Items.cpp b/Tactical/Handle Items.cpp index 55d12612..20c62493 100644 --- a/Tactical/Handle Items.cpp +++ b/Tactical/Handle Items.cpp @@ -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; } diff --git a/Tactical/Item Types.cpp b/Tactical/Item Types.cpp index 5af1599e..9dd8b0d9 100644 --- a/Tactical/Item Types.cpp +++ b/Tactical/Item Types.cpp @@ -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 diff --git a/Tactical/Item Types.h b/Tactical/Item Types.h index 0de77cac..496606e6 100644 --- a/Tactical/Item Types.h +++ b/Tactical/Item Types.h @@ -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; diff --git a/Tactical/Items.cpp b/Tactical/Items.cpp index 4bbf7bbb..69106e67 100644 --- a/Tactical/Items.cpp +++ b/Tactical/Items.cpp @@ -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 ); diff --git a/Tactical/Items.h b/Tactical/Items.h index d5d18f00..e568d941 100644 --- a/Tactical/Items.h +++ b/Tactical/Items.h @@ -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 ); diff --git a/Tactical/Soldier Control.cpp b/Tactical/Soldier Control.cpp index 90cfadb4..f406c3b9 100644 --- a/Tactical/Soldier Control.cpp +++ b/Tactical/Soldier Control.cpp @@ -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 diff --git a/Tactical/UI Cursors.cpp b/Tactical/UI Cursors.cpp index 3136dcac..7def00e3 100644 --- a/Tactical/UI Cursors.cpp +++ b/Tactical/UI Cursors.cpp @@ -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; } diff --git a/Tactical/Weapons.h b/Tactical/Weapons.h index 86454d2e..51fe4874 100644 --- a/Tactical/Weapons.h +++ b/Tactical/Weapons.h @@ -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 diff --git a/Tactical/XML_Explosive.cpp b/Tactical/XML_Explosive.cpp index c69673e2..f4b1876a 100644 --- a/Tactical/XML_Explosive.cpp +++ b/Tactical/XML_Explosive.cpp @@ -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\r\n"); - FilePrintf(hFile,"\t\t%d\r\n", cnt ); - FilePrintf(hFile,"\t\t%d\r\n", Explosive[cnt].ubType ); - FilePrintf(hFile,"\t\t%d\r\n", Explosive[cnt].ubDamage ); - FilePrintf(hFile,"\t\t%d\r\n", Explosive[cnt].ubStunDamage ); - FilePrintf(hFile,"\t\t%d\r\n", Explosive[cnt].ubRadius ); - FilePrintf(hFile,"\t\t%d\r\n", Explosive[cnt].ubVolume ); - FilePrintf(hFile,"\t\t%d\r\n", Explosive[cnt].ubVolatility ); - FilePrintf(hFile,"\t\t%d\r\n", Explosive[cnt].ubAnimationID ); + FilePrintf(hFile,"\t\t%d\r\n", cnt ); + FilePrintf(hFile,"\t\t%d\r\n", Explosive[cnt].ubType ); + FilePrintf(hFile,"\t\t%d\r\n", Explosive[cnt].ubDamage ); + FilePrintf(hFile,"\t\t%d\r\n", Explosive[cnt].ubStunDamage ); + FilePrintf(hFile,"\t\t%d\r\n", Explosive[cnt].ubRadius ); + FilePrintf(hFile,"\t\t%d\r\n", Explosive[cnt].ubVolume ); + FilePrintf(hFile,"\t\t%d\r\n", Explosive[cnt].ubVolatility ); + FilePrintf(hFile,"\t\t%d\r\n", Explosive[cnt].ubAnimationID ); FilePrintf(hFile,"\t\t%d\r\n", Explosive[cnt].ubDuration ); - FilePrintf(hFile,"\t\t%d\r\n", Explosive[cnt].ubStartRadius ); + FilePrintf(hFile,"\t\t%d\r\n", Explosive[cnt].ubStartRadius ); FilePrintf(hFile,"\t\t%d\r\n", Explosive[cnt].ubMagSize ); - FilePrintf(hFile,"\t\t%d\r\n", (UINT8)Explosive[cnt].fExplodeOnImpact ); + FilePrintf(hFile,"\t\t%d\r\n", (UINT8)Explosive[cnt].fExplodeOnImpact ); + + FilePrintf(hFile,"\t\t%d\r\n", Explosive[cnt].usNumFragments ); + FilePrintf(hFile,"\t\t%d\r\n", Explosive[cnt].ubFragType ); + FilePrintf(hFile,"\t\t%d\r\n", Explosive[cnt].ubFragDamage ); + FilePrintf(hFile,"\t\t%d\r\n", Explosive[cnt].fExplodeOnImpact ); + FilePrintf(hFile,"\t\t%d\r\n", Explosive[cnt].ubHorizontalDegree ); + FilePrintf(hFile,"\t\t%d\r\n", Explosive[cnt].ubVerticalDegree ); FilePrintf(hFile,"\t\r\n"); } diff --git a/Tactical/bullets.cpp b/Tactical/bullets.cpp index 8d0c297b..f3c8ce8a 100644 --- a/Tactical/bullets.cpp +++ b/Tactical/bullets.cpp @@ -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 diff --git a/TileEngine/Explosion Control.cpp b/TileEngine/Explosion Control.cpp index ec7809b1..23578738 100644 --- a/TileEngine/Explosion Control.cpp +++ b/TileEngine/Explosion Control.cpp @@ -104,7 +104,7 @@ BOOLEAN ExpAffect( INT32 sBombGridNo, INT32 sGridNo, UINT32 uiDist, UINT16 usIte UINT8 DetermineFlashbangEffect( SOLDIERTYPE *pSoldier, INT8 ubExplosionDir, BOOLEAN fInBuilding); // 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 void AddToShouldBecomeHostileOrSayQuoteList( UINT8 ubID ); @@ -271,12 +271,12 @@ void RecountExplosions( void ) // 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 if (is_networked) { 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); } #endif @@ -346,15 +346,15 @@ void InternalIgniteExplosion( UINT8 ubOwner, INT16 sX, INT16 sY, INT16 sZ, INT32 if (Explosive[ Item[ usItem ].ubClassIndex ].usNumFragments > 0 ) { // 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 ) @@ -3609,8 +3609,8 @@ void AddBombToQueue( UINT32 uiWorldBombIndex, UINT32 uiTimeStamp, BOOL fFromRemo gfExplosionQueueActive = TRUE; } -// Flugente: activate everything connected to a tripwire in the surrounding if sGridNo on level bLevel -BOOLEAN ActivateSurroundingTripwire( UINT8 ubID, INT32 sGridNo, INT8 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, UINT32 ubFlag ) { UINT32 uiTimeStamp= GetJA2Clock(); BOOLEAN fFoundMine = FALSE; @@ -3644,29 +3644,63 @@ BOOLEAN ActivateSurroundingTripwire( UINT8 ubID, INT32 sGridNo, INT8 bLevel ) // tripwire just gets activated if ( Item[pObj->usItem].tripwire == 1 ) { - OBJECTTYPE 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.... - RemoveItemFromPool( adjgrid, gWorldBombs[ uiWorldBombIndex ].iItemIndex, bLevel ); + // check if a) tripwire belongs to the same tripwire network and b) its of the same or lower hierarchy level + BOOLEAN samenetwork = FALSE; + BOOLEAN sameorlowerhierarchy = FALSE; + + if ( ubWireNetworkFlag <= ubFlag ) // hierarchy of a group is sorted, so this suffices + sameorlowerhierarchy = TRUE; - // if no other bomb exists here - if ( FindWorldItemForBombInGridNo(adjgrid, bLevel) == -1 ) + 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! - if ( gpWorldLevelData[adjgrid].uiFlags & MAPELEMENT_PLAYER_MINE_PRESENT ) + for (INT8 j = 0; j < 4; ++j) { - 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 ); + 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 - // 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); + if ( ( (ubFlag & samenetworkflag) != 0 ) && ( (ubWireNetworkFlag & samenetworkflag) != 0 ) ) + samenetwork = TRUE; + + if ( samenetwork ) + break; + } + } + + if ( samenetwork && sameorlowerhierarchy ) + { + // 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 + + OBJECTTYPE newtripwireObject; + CreateItem( pObj->usItem, (*pObj)[0]->data.objectStatus, &newtripwireObject ); + + // 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 else @@ -3767,12 +3801,12 @@ void HandleExplosionQueue( void ) // bomb objects only store the SIDE who placed the bomb! :-( 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 { // 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(); + // 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 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) ) { // 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 - if ( ((*pObj)[0]->data.misc.ubBombOwner) > 1 ) - { - if ( MercPtrs[((*pObj)[0]->data.misc.ubBombOwner - 2)]->ubProfile != NO_PROFILE && - MercPtrs[((*pObj)[0]->data.misc.ubBombOwner - 2)]->bTeam == gbPlayerNum ) + // Found a remote bomb, so check to see if it has the same frequency + if ((*pObj)[0]->data.misc.bFrequency == bFrequency) + { + // SANDRO - added merc records and some exp + 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; - - // put this bomb on the queue - AddBombToQueue( uiWorldBombIndex, uiTimeStamp ); - if (pObj->usItem != ACTION_ITEM || (*pObj)[0]->data.misc.bActionValue == ACTION_ITEM_BLOW_UP) + } + else // defuse bombs + { + // check for frequency + if ((*pObj)[0]->data.bDefuseFrequency == bFrequency) { - 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; 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.... 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.. if ( newtripwireObject[0]->data.objectStatus > (INT16)Random(50) ) - fFoundMine = ActivateSurroundingTripwire(ubID, sGridNo, bLevel); + fFoundMine = ActivateSurroundingTripwire(ubID, sGridNo, bLevel, ubWireNetworkFlag); } 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 // 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. -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 ubFragRange = Explosive[Item[usItem].ubClassIndex].ubFragRange; 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 dRandomY = ((FLOAT)Random(2000) / 1000.0f) - 1.0f; - FLOAT dRandomZ = ((FLOAT)Random(2000) / 1000.0f) - 1.0f; + FLOAT dRandomX = 0; + FLOAT dRandomY = 0; + 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 dDeltaY = (dRandomY * ubFragRange); diff --git a/TileEngine/Explosion Control.h b/TileEngine/Explosion Control.h index 96fbd189..ee5a56f1 100644 --- a/TileEngine/Explosion Control.h +++ b/TileEngine/Explosion Control.h @@ -98,8 +98,8 @@ extern EXPLOSIONTYPE gExplosionData[ NUM_EXPLOSION_SLOTS ]; extern UINT8 gubElementsOnExplosionQueue; extern BOOLEAN gfExplosionQueueActive; -void IgniteExplosion( UINT8 ubOwner, INT16 sX, INT16 sY, INT16 sZ, INT32 sGridNo, UINT16 usItem, INT8 bLevel ); -void InternalIgniteExplosion( UINT8 ubOwner, INT16 sX, INT16 sY, INT16 sZ, INT32 sGridNo, UINT16 usItem, BOOLEAN fLocate, 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, UINT8 ubDirection = DIRECTION_IRRELEVANT ); 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 AddBombToQueue( UINT32 uiWorldBombIndex, UINT32 uiTimeStamp, BOOL fFromRemoteClient = FALSE ); -// Flugente: activate everything connected to a tripwire in the surrounding if sGridNo on level bLevel -BOOLEAN ActivateSurroundingTripwire( UINT8 ubID, INT32 sGridNo, INT8 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, UINT32 ubFlag ); extern void ToggleActionItemsByFrequency( INT8 bFrequency ); extern void PerformItemAction( INT32 sGridNo, OBJECTTYPE * pObj ); diff --git a/Utils/Text.h b/Utils/Text.h index dea8dbbc..0e6f1065 100644 --- a/Utils/Text.h +++ b/Utils/Text.h @@ -801,6 +801,14 @@ enum NO_LOS_TO_TALK_TARGET, ATTACHMENT_REMOVED, 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 }; diff --git a/Utils/XML_Items.cpp b/Utils/XML_Items.cpp index 8f9e3b9b..bc6291e5 100644 --- a/Utils/XML_Items.cpp +++ b/Utils/XML_Items.cpp @@ -259,6 +259,7 @@ itemStartElementHandle(void *userData, const XML_Char *name, const XML_Char **at strcmp(name, "AttachmentClass") == 0 || strcmp(name, "TripWireActivation") == 0 || strcmp(name, "TripWire") == 0 || + strcmp(name, "Directional") == 0 || strcmp(name, "fFlags") == 0 )) { @@ -1295,6 +1296,11 @@ itemEndElementHandle(void *userData, const XML_Char *name) pData->curElement = ELEMENT; 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--; } @@ -1904,6 +1910,7 @@ BOOLEAN WriteItemStats() FilePrintf(hFile,"\t\t%d\r\n", Item[cnt].tripwireactivation ); FilePrintf(hFile,"\t\t%d\r\n", Item[cnt].tripwire ); + FilePrintf(hFile,"\t\t%d\r\n", Item[cnt].directional ); FilePrintf(hFile,"\t\r\n"); } diff --git a/Utils/_ChineseText.cpp b/Utils/_ChineseText.cpp index 26078d3a..e98c7550 100644 --- a/Utils/_ChineseText.cpp +++ b/Utils/_ChineseText.cpp @@ -2913,6 +2913,13 @@ CHAR16 TacticalStr[][ MED_STRING_LENGTH ] = L"%s看不见%s。", // Cannot see person trying to talk to 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. diff --git a/Utils/_DutchText.cpp b/Utils/_DutchText.cpp index 393625f5..250b659b 100644 --- a/Utils/_DutchText.cpp +++ b/Utils/_DutchText.cpp @@ -2910,6 +2910,13 @@ CHAR16 TacticalStr[][ MED_STRING_LENGTH ] = L"%s kan %s niet zien.", // Cannot see person trying to talk to L"Attachment removed", 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. diff --git a/Utils/_EnglishText.cpp b/Utils/_EnglishText.cpp index 3600135a..d54e9427 100644 --- a/Utils/_EnglishText.cpp +++ b/Utils/_EnglishText.cpp @@ -2913,6 +2913,13 @@ CHAR16 TacticalStr[][ MED_STRING_LENGTH ] = L"%s cannot see %s.", // Cannot see person trying to talk to L"Attachment removed", 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. diff --git a/Utils/_FrenchText.cpp b/Utils/_FrenchText.cpp index f74f456d..d6d01e72 100644 --- a/Utils/_FrenchText.cpp +++ b/Utils/_FrenchText.cpp @@ -2912,6 +2912,13 @@ CHAR16 TacticalStr[][ MED_STRING_LENGTH ] = L"%s ne peut pas voir %s.", // Cannot see person trying to talk to L"Accessoire retiré", 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. diff --git a/Utils/_GermanText.cpp b/Utils/_GermanText.cpp index d11f97f0..a455f725 100644 --- a/Utils/_GermanText.cpp +++ b/Utils/_GermanText.cpp @@ -2917,6 +2917,13 @@ CHAR16 TacticalStr[][ MED_STRING_LENGTH ] = L"%s kann %s nicht sehen.", // Cannot see person trying to talk to L"Anbringung entfernt", 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. diff --git a/Utils/_ItalianText.cpp b/Utils/_ItalianText.cpp index 07e78b38..bf81d92e 100644 --- a/Utils/_ItalianText.cpp +++ b/Utils/_ItalianText.cpp @@ -2897,7 +2897,6 @@ CHAR16 TacticalStr[][ MED_STRING_LENGTH ] = L"Il veicolo può viaggiare solo tra i settori", L"Non è in grado di fasciarsi da solo ora", 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"Serratura manomessa", 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"Attachment removed", 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. diff --git a/Utils/_PolishText.cpp b/Utils/_PolishText.cpp index 7c017345..77460d49 100644 --- a/Utils/_PolishText.cpp +++ b/Utils/_PolishText.cpp @@ -2920,6 +2920,13 @@ CHAR16 TacticalStr[][ MED_STRING_LENGTH ] = L"%s nie widzi - %s.", // Cannot see person trying to talk to L"Dodatek usunięty", 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. diff --git a/Utils/_RussianText.cpp b/Utils/_RussianText.cpp index e0cb9e00..7ca952e9 100644 --- a/Utils/_RussianText.cpp +++ b/Utils/_RussianText.cpp @@ -2913,6 +2913,13 @@ CHAR16 TacticalStr[][ MED_STRING_LENGTH ] = L"%s не видит %s.", // Cannot see person trying to talk to 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. diff --git a/Utils/_TaiwaneseText.cpp b/Utils/_TaiwaneseText.cpp index 657fb135..59146e34 100644 --- a/Utils/_TaiwaneseText.cpp +++ b/Utils/_TaiwaneseText.cpp @@ -2914,6 +2914,13 @@ CHAR16 TacticalStr[][ MED_STRING_LENGTH ] = L"%s cannot see %s.", // Cannot see person trying to talk to L"Attachment removed", 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.