diff --git a/GameSettings.cpp b/GameSettings.cpp index 213722f4..a9da1e40 100644 --- a/GameSettings.cpp +++ b/GameSettings.cpp @@ -1715,6 +1715,7 @@ void LoadGameExternalOptions() gGameExternalOptions.fSoldiersWearAnyArmour = iniReader.ReadBoolean("Tactical Gameplay Settings", "SOLDIERS_ALWAYS_WEAR_ANY_ARMOR", FALSE); gGameExternalOptions.fRobotNoReadytime = iniReader.ReadBoolean("Tactical Gameplay Settings", "ROBOT_NO_READYTIME", FALSE); + gGameExternalOptions.fRobotUpgradeable = iniReader.ReadBoolean("Tactical Gameplay Settings", "ROBOT_UPGRADEABLE", TRUE); // improved Interrupt System (info: multiplayer game ALWAYS use the old interrupt system, because the new one causes crashes, no problem so far) gGameExternalOptions.fImprovedInterruptSystem = iniReader.ReadBoolean("Tactical Gameplay Settings", "IMPROVED_INTERRUPT_SYSTEM", TRUE); diff --git a/GameSettings.h b/GameSettings.h index 019608fe..23a2dfb0 100644 --- a/GameSettings.h +++ b/GameSettings.h @@ -1566,6 +1566,7 @@ typedef struct UINT8 ubGridResolutionNight; //DBrot: how precise we want to show their location - adjust for shorter night time ranges ... or don't BOOLEAN fRobotNoReadytime; //DBrot: should the robot need to ready his gun? + BOOLEAN fRobotUpgradeable; // rftr: is madlab's robot upgradeable? // Flugente: externalised squad names BOOLEAN fUseXMLSquadNames; diff --git a/Strategic/Map Screen Interface Map Inventory.cpp b/Strategic/Map Screen Interface Map Inventory.cpp index 32dbf1d3..dafeaf18 100644 --- a/Strategic/Map Screen Interface Map Inventory.cpp +++ b/Strategic/Map Screen Interface Map Inventory.cpp @@ -2549,6 +2549,10 @@ void BeginInventoryPoolPtr( OBJECTTYPE *pInventorySlot ) } } } + else if (AM_A_ROBOT(pSoldier)) + { + // intentionally do nothing for madlab's robot + } else { if (AutoPlaceObject(pSoldier,gpItemPointer,FALSE,NO_SLOT,TRUE)) //doesn't work for vehicles :p diff --git a/Strategic/mapscreen.cpp b/Strategic/mapscreen.cpp index 64584a39..dc5e0378 100644 --- a/Strategic/mapscreen.cpp +++ b/Strategic/mapscreen.cpp @@ -114,10 +114,12 @@ #include "Auto Bandage.h" // added by Flugente #include "Food.h" // added by Flugente #include "Drugs And Alcohol.h" // added by Flugente + #include "WordWrap.h" #endif #include "connect.h" //hayden #include "InterfaceItemImages.h" +#include "vobject.h" #ifdef JA2UB #include "laptop.h" @@ -261,6 +263,16 @@ struct UILayout_CharInvText SGPPoint CamoPercent; INT32 PercentWidth; INT32 PercentHeight; + + SGPPoint RobotWeaponLabel; + SGPPoint RobotAmmoLabel; + SGPPoint RobotTargetingLabel; + SGPPoint RobotTargetingBonus; + SGPPoint RobotChassisLabel; + SGPPoint RobotChassisBonus; + SGPPoint RobotUtilityLabel; + SGPPoint RobotUtilityBonus; + SGPPoint RobotInventoryLabel; }; struct UILayout_CharInv @@ -540,6 +552,7 @@ UINT32 guiMapInvSecondHandBlockout; UINT32 guiULICONS; UINT32 guiNewMailIcons; UINT32 guiLEVELMARKER; // the white rectangle highlighting the current level on the map border +UINT32 guiMapScreenAttachmentSlot; // misc mouse regions MOUSE_REGION gCharInfoFaceRegion; @@ -1261,6 +1274,16 @@ void InitializeInvPanelCoords() UI_CHARINV.Text.PercentWidth = 20; UI_CHARINV.Text.PercentHeight = 10; + UI_CHARINV.Text.RobotWeaponLabel = {x + 15, y + 140}; + UI_CHARINV.Text.RobotAmmoLabel = {x + 140, y + 140}; + UI_CHARINV.Text.RobotTargetingLabel = {x + 15, y + 190}; + UI_CHARINV.Text.RobotTargetingBonus = {x + 85, y + 200}; + UI_CHARINV.Text.RobotChassisLabel = {x + 15, y + 240}; + UI_CHARINV.Text.RobotChassisBonus = {x + 85, y + 250}; + UI_CHARINV.Text.RobotUtilityLabel = {x + 15, y + 290}; + UI_CHARINV.Text.RobotUtilityBonus = {x + 85, y + 300}; + UI_CHARINV.Text.RobotInventoryLabel = {x + 15, y + 340}; + UI_CHARINV.BodyPanel = { x + 31, y + 8 }; // X, Y Location of Map screen's Camouflage region @@ -1856,6 +1879,31 @@ BOOLEAN InitializeInvPanelCoordsVehicle( ) return ( TRUE ); } +BOOLEAN InitializeInvPanelCoordsRobot() +{ + InitializeInvPanelCoordsNew(); + + const auto x = UI_CHARINV.Region.x; + const auto y = UI_CHARINV.Region.y; + + // Inventory slots + if (iResolution >= _640x480 && iResolution < _800x600) + { + // NIV is not usable at 640x480, so nothing happens + } + else + { + gMapScreenInvPocketXY[HANDPOS].sX = x + 21; gMapScreenInvPocketXY[HANDPOS].sY = y + 150; + gMapScreenInvPocketXY[14].sX = x + 146; gMapScreenInvPocketXY[14].sY = y + 150; + gMapScreenInvPocketXY[15].sX = x + 21; gMapScreenInvPocketXY[15].sY = y + 200; + gMapScreenInvPocketXY[16].sX = x + 21; gMapScreenInvPocketXY[16].sY = y + 250; + gMapScreenInvPocketXY[17].sX = x + 21; gMapScreenInvPocketXY[17].sY = y + 300; + gMapScreenInvPocketXY[18].sX = x + 21; gMapScreenInvPocketXY[18].sY = y + 350; + } + + return TRUE; +} + // the tries to select a mapscreen character by his soldier ID BOOLEAN SetInfoChar( UINT8 ubID ) { @@ -5114,6 +5162,10 @@ UINT32 MapScreenHandle(void) FilenameForBPP("INTERFACE\\BullsEye.sti", VObjectDesc.ImageFile); CHECKF(AddVideoObject(&VObjectDesc, &guiBULLSEYE)); + VObjectDesc.fCreateFlags = VOBJECT_CREATE_FROMFILE; + FilenameForBPP("INTERFACE\\ATTACHMENT_SLOT.STI", VObjectDesc.ImageFile); + CHECKF(AddVideoObject( &VObjectDesc, &guiMapScreenAttachmentSlot)); + HandleLoadOfMapBottomGraphics( ); // load the militia pop up box @@ -9403,7 +9455,7 @@ void CreateDestroyMapInvButton() if (bSelectedInfoChar != -1 && gCharactersList[bSelectedInfoChar].fValid) { SOLDIERTYPE* pSoldier = MercPtrs[gCharactersList[bSelectedInfoChar].usSolID]; - if (!(pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE)) + if (!(pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE) && !AM_A_ROBOT(pSoldier)) { InitInvSlotInterface(gMapScreenInvPocketXY, &gSCamoXY, MAPInvMoveCallback, MAPInvClickCallback, MAPInvMoveCamoCallback, MAPInvClickCamoCallback, FALSE); } @@ -9471,7 +9523,7 @@ void BltCharInvPanel() SOLDIERTYPE *pSoldier; CHAR16 sString[ 32 ]; INT16 usX, usY; - UINT8 disOpt = 0; + UINT8 mapInvIndex = 0; // make sure we're here legally // In widescreen UI, draw an empty inv panel if no accessible inventory @@ -9499,7 +9551,19 @@ void BltCharInvPanel() InitInventoryVehicle(gMapScreenInvPocketXY, MAPInvMoveCallback, MAPInvClickCallback, FALSE); fResetMapCoords=FALSE; } - disOpt = 2; + mapInvIndex = 2; + } + else if (UsingNewInventorySystem() && AM_A_ROBOT(pSoldier)) + { + if (fResetMapCoords) + { + InitializeInvPanelCoordsRobot(); + InitInventoryRobot(gMapScreenInvPocketXY, MAPInvMoveCallback, MAPInvClickCallback, FALSE); + + fResetMapCoords = FALSE; + } + + mapInvIndex = 3; } else if((UsingNewInventorySystem() == true)) { @@ -9510,7 +9574,7 @@ void BltCharInvPanel() InitInventorySoldier(gMapScreenInvPocketXY, MAPInvMoveCallback, MAPInvClickCallback, FALSE, TRUE); fResetMapCoords=FALSE; } - disOpt = 1; + mapInvIndex = 1; } else { @@ -9521,9 +9585,20 @@ void BltCharInvPanel() pDestBuf = (UINT16*)LockVideoSurface(guiSAVEBUFFER, &uiDestPitchBYTES); GetVideoObject(&hCharListHandle, guiMAPINV); - Blt8BPPDataTo16BPPBufferTransparent( pDestBuf, uiDestPitchBYTES, hCharListHandle, UI_CHARINV.Region.x, UI_CHARINV.Region.y, disOpt); + Blt8BPPDataTo16BPPBufferTransparent( pDestBuf, uiDestPitchBYTES, hCharListHandle, UI_CHARINV.Region.x, UI_CHARINV.Region.y, mapInvIndex); UnLockVideoSurface( guiSAVEBUFFER ); - + + // this soldier is a robot - the above initialisation set up the UI background, and this will draw the individual attachment slots + if (UsingNewInventorySystem() && AM_A_ROBOT(pSoldier)) + { + // draw slot for robot's installed weapon + BltVideoObjectFromIndex(guiSAVEBUFFER, guiMapScreenAttachmentSlot, 1, UI_CHARINV.Text.RobotWeaponLabel.iX, UI_CHARINV.Text.RobotWeaponLabel.iY + 10, VO_BLT_SRCTRANSPARENCY, NULL); + + // draw robot upgrade slots + for (int a = 0; a <= NUM_INV_SLOTS; ++a) + if (robotInv[a]) + BltVideoObjectFromIndex(guiSAVEBUFFER, guiMapScreenAttachmentSlot, 1, gMapScreenInvPocketXY[a].sX - 6, gMapScreenInvPocketXY[a].sY, VO_BLT_SRCTRANSPARENCY, NULL); + } if (!isWidescreenUI()) { @@ -9574,7 +9649,7 @@ void BltCharInvPanel() SetFontForeground( MAP_INV_STATS_TITLE_FONT_COLOR ); // CHRISL: Only display next three values if we're a merc - if(!(pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE)) + if(!(pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE) && !AM_A_ROBOT(pSoldier)) { // print armor/weight/camo labels mprintf(UI_CHARINV.Text.ArmorLabel.iX, UI_CHARINV.Text.ArmorLabel.iY, pInvPanelTitleStrings[ 0 ] ); @@ -9694,8 +9769,118 @@ void BltCharInvPanel() swprintf( pStr, gzMiscItemStatsFasthelp[35], totalweight / 10.0 ); SetRegionFastHelpText( &(gMapMercWeightRegion), pStr ); + } } + else if (AM_A_ROBOT(pSoldier)) + { + // draw robot upgrade text labels + mprintf(UI_CHARINV.Text.RobotWeaponLabel.iX, UI_CHARINV.Text.RobotWeaponLabel.iY, szRobotText[ ROBOT_TEXT_INSTALLED_WEAPON ] ); + mprintf(UI_CHARINV.Text.RobotAmmoLabel.iX, UI_CHARINV.Text.RobotAmmoLabel.iY, szRobotText[ ROBOT_TEXT_SLOT_AMMO ] ); + mprintf(UI_CHARINV.Text.RobotTargetingLabel.iX, UI_CHARINV.Text.RobotTargetingLabel.iY, szRobotText[ ROBOT_TEXT_SLOT_TARGETING ] ); + mprintf(UI_CHARINV.Text.RobotChassisLabel.iX, UI_CHARINV.Text.RobotChassisLabel.iY, szRobotText[ ROBOT_TEXT_SLOT_CHASSIS ] ); + mprintf(UI_CHARINV.Text.RobotUtilityLabel.iX, UI_CHARINV.Text.RobotUtilityLabel.iY, szRobotText[ ROBOT_TEXT_SLOT_UTILITY ] ); + mprintf(UI_CHARINV.Text.RobotInventoryLabel.iX, UI_CHARINV.Text.RobotInventoryLabel.iY, szRobotText[ ROBOT_TEXT_SLOT_INVENTORY ] ); + + // draw robot upgrade bonus text + CHAR16 text[500]; + UINT32 fontColour = FONT_MCOLOR_RED; + + // robot targeting bonus + if (Item[pSoldier->inv[ROBOT_TARGETING_SLOT].usItem].fProvidesRobotLaserBonus) + { + swprintf(text, szRobotText[ROBOT_TEXT_LASER]); + fontColour = FONT_MCOLOR_LTGREEN; + } + else if (Item[pSoldier->inv[ROBOT_TARGETING_SLOT].usItem].fProvidesRobotNightVision) + { + swprintf(text, szRobotText[ROBOT_TEXT_NIGHT_VISION]); + fontColour = FONT_MCOLOR_LTGREEN; + } + else if (Item[pSoldier->inv[ROBOT_TARGETING_SLOT].usItem].bRobotTargetingSkillGrant > 0) + { + swprintf(text, szRobotText[ROBOT_TEXT_SKILL_GRANTED], gzMercSkillTextNew[Item[pSoldier->inv[ROBOT_TARGETING_SLOT].usItem].bRobotTargetingSkillGrant]); + fontColour = FONT_MCOLOR_LTGREEN; + } + else + { + swprintf(text, szRobotText[ROBOT_TEXT_NO_BONUS]); + fontColour = FONT_MCOLOR_RED; + } + DisplayWrappedString(UI_CHARINV.Text.RobotTargetingBonus.iX, UI_CHARINV.Text.RobotTargetingBonus.iY, 170, 2, FONT10ARIAL, fontColour, text, FONT_MCOLOR_BLACK, FALSE, 0); + + // robot chassis bonus + if (Item[pSoldier->inv[ROBOT_CHASSIS_SLOT].usItem].bRobotStrBonus > 0 || Item[pSoldier->inv[ROBOT_CHASSIS_SLOT].usItem].bRobotAgiBonus > 0 || Item[pSoldier->inv[ROBOT_CHASSIS_SLOT].usItem].bRobotDexBonus > 0) + { + swprintf(text, szRobotText[ROBOT_TEXT_STAT_BONUSES]); + fontColour = FONT_MCOLOR_LTGREEN; + } + else if (Item[pSoldier->inv[ROBOT_CHASSIS_SLOT].usItem].fProvidesRobotCamo) + { + swprintf(text, szRobotText[ROBOT_TEXT_CAMO]); + fontColour = FONT_MCOLOR_LTGREEN; + } + else if (Item[pSoldier->inv[ROBOT_CHASSIS_SLOT].usItem].fRobotDamageReductionModifier > 0.0f && Item[pSoldier->inv[ROBOT_CHASSIS_SLOT].usItem].fRobotDamageReductionModifier < 1.0f) + { + swprintf(text, szRobotText[ROBOT_TEXT_PLATE]); + fontColour = FONT_MCOLOR_LTGREEN; + } + else if (Item[pSoldier->inv[ROBOT_CHASSIS_SLOT].usItem].bRobotChassisSkillGrant > 0) + { + swprintf(text, szRobotText[ROBOT_TEXT_SKILL_GRANTED], gzMercSkillTextNew[Item[pSoldier->inv[ROBOT_CHASSIS_SLOT].usItem].bRobotChassisSkillGrant]); + fontColour = FONT_MCOLOR_LTGREEN; + } + else + { + swprintf(text, szRobotText[ROBOT_TEXT_NO_BONUS]); + fontColour = FONT_MCOLOR_RED; + } + DisplayWrappedString(UI_CHARINV.Text.RobotChassisBonus.iX, UI_CHARINV.Text.RobotChassisBonus.iY, 170, 2, FONT10ARIAL, fontColour, text, FONT_MCOLOR_BLACK, FALSE, 0); + + // robot utility bonus + if ( HasItemFlag( pSoldier->inv[ROBOT_UTILITY_SLOT].usItem, CLEANING_KIT ) ) + { + swprintf(text, L"%s", szRobotText[ROBOT_TEXT_CLEANING_KIT]); + fontColour = FONT_MCOLOR_LTGREEN; + } + else if ( HasItemFlag(pSoldier->inv[ROBOT_UTILITY_SLOT].usItem, RADIO_SET ) ) + { + swprintf(text, L"%s", szRobotText[ROBOT_TEXT_RADIO]); + fontColour = FONT_MCOLOR_LTGREEN; + } + else if (Item[pSoldier->inv[ROBOT_UTILITY_SLOT].usItem].metaldetector == 1) + { + swprintf(text, L"%s", szRobotText[ROBOT_TEXT_METAL_DETECTOR]); + fontColour = FONT_MCOLOR_LTGREEN; + } + else if (Item[pSoldier->inv[ROBOT_UTILITY_SLOT].usItem].xray == 1) + { + swprintf(text, L"%s", szRobotText[ROBOT_TEXT_XRAY]); + fontColour = FONT_MCOLOR_LTGREEN; + } + else if (Item[pSoldier->inv[ROBOT_UTILITY_SLOT].usItem].bRobotUtilitySkillGrant > 0) + { + swprintf(text, szRobotText[ROBOT_TEXT_SKILL_GRANTED], gzMercSkillTextNew[Item[pSoldier->inv[ROBOT_UTILITY_SLOT].usItem].bRobotUtilitySkillGrant]); + fontColour = FONT_MCOLOR_LTGREEN; + } + else + { + swprintf(text, L"%s", szRobotText[ROBOT_TEXT_NO_BONUS]); + fontColour = FONT_MCOLOR_RED; + } + DisplayWrappedString(UI_CHARINV.Text.RobotUtilityBonus.iX, UI_CHARINV.Text.RobotUtilityBonus.iY, 170, 2, FONT10ARIAL, fontColour, text, FONT_MCOLOR_BLACK, FALSE, 0); + } + + if(!(pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE) && !AM_A_ROBOT(pSoldier)) + { + MSYS_EnableRegion(&gMapMercCamoRegion); + MSYS_EnableRegion(&gMapMercWeightRegion); + } + else + { + MSYS_DisableRegion(&gMapMercCamoRegion); + MSYS_DisableRegion(&gMapMercWeightRegion); + } if( InKeyRingPopup( ) ) { @@ -9921,7 +10106,7 @@ void MAPInvClickCallback( MOUSE_REGION *pRegion, INT32 iReason ) if ( pSoldier->inv[ uiHandPos ].exists() == false ) { - if ( gGameSettings.fOptions[TOPTION_ENABLE_INVENTORY_POPUPS] == TRUE && !IsVehicle( pSoldier ) ) // the_bob : enable popups for picking items from sector inv + if ( gGameSettings.fOptions[TOPTION_ENABLE_INVENTORY_POPUPS] == TRUE && !IsVehicle( pSoldier ) && !AM_A_ROBOT(pSoldier)) // the_bob : enable popups for picking items from sector inv { if ( _KeyDown(CTRL) ) { @@ -9942,11 +10127,18 @@ void MAPInvClickCallback( MOUSE_REGION *pRegion, INT32 iReason ) return; } + // rftr: robot can't unequip weapon + if (AM_A_ROBOT(pSoldier) && uiHandPos == HANDPOS) + { + DoMessageBox(MSG_BOX_BASIC_STYLE, szRobotText[ROBOT_TEXT_CANNOT_CHANGE_INSTALLED_WEAPON], guiCurrentScreen, (UINT8)MSG_BOX_FLAG_OK, NULL, NULL); + return; + } + /* CHRISL: For New Inventory system. Are we removing an existing LBE item? If so, we need to pull all items in the relevant IC Group pockets out of the soldiers inventory and put them into the LBE items inventory. But first, find out if we already have a LBE item inventory for this item and this merc. If we do, remove the items from it and place them into the sector the LBE inventory is located in.*/ - if((UsingNewInventorySystem() == true) && !(pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE)) + if((UsingNewInventorySystem() == true) && !(pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE) && !AM_A_ROBOT(pSoldier)) { /*if we pick up a backpack without reactivating the drop pack button, and we have a dropkey, reactivate the button*/ @@ -10064,6 +10256,13 @@ void MAPInvClickCallback( MOUSE_REGION *pRegion, INT32 iReason ) } else if ( ValidAttachment( usNewItemIndex, usOldItemIndex ) ) { + // rftr: robot can't equip weapon attachments + if (AM_A_ROBOT(pSoldier) && uiHandPos == HANDPOS) + { + DoMessageBox(MSG_BOX_BASIC_STYLE, szRobotText[ROBOT_TEXT_CANNOT_ADD_ATTACHMENTS], guiCurrentScreen, (UINT8)MSG_BOX_FLAG_OK, NULL, NULL); + return; + } + // it's an attempt to attach; bring up the inventory panel if ( !InItemDescriptionBox( ) ) { @@ -10118,7 +10317,7 @@ void MAPInvClickCallback( MOUSE_REGION *pRegion, INT32 iReason ) // else handle normally } - if((UsingNewInventorySystem() == true) && !(pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE)) + if((UsingNewInventorySystem() == true) && !(pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE) && !AM_A_ROBOT(pSoldier)) { if((uiHandPos == VESTPOCKPOS || uiHandPos == LTHIGHPOCKPOS || uiHandPos == RTHIGHPOCKPOS || uiHandPos == CPACKPOCKPOS || uiHandPos == BPACKPOCKPOS) && CanItemFitInPosition(pSoldier, gpItemPointer, uiHandPos, FALSE)) { @@ -10216,6 +10415,13 @@ void MAPInvClickCallback( MOUSE_REGION *pRegion, INT32 iReason ) return; } + // rftr: robot can't equip weapon attachments + if (AM_A_ROBOT(pSoldier) && uiHandPos == HANDPOS) + { + DoMessageBox(MSG_BOX_BASIC_STYLE, szRobotText[ROBOT_TEXT_CANNOT_ADD_ATTACHMENTS], guiCurrentScreen, (UINT8)MSG_BOX_FLAG_OK, NULL, NULL); + return; + } + // Some global stuff here - for esc, etc // Check for # of slots in item // CHRISL: Use new ItemSlotLimit function if we're using the new inventory system @@ -14913,8 +15119,8 @@ BOOLEAN MapCharacterHasAccessibleInventory( INT8 bCharNumber ) // ( pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE ) || // And added this instead: ( (!gGameExternalOptions.fVehicleInventory) && (pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE) ) || - ( AM_A_ROBOT( pSoldier ) ) || - ( pSoldier->ubWhatKindOfMercAmI == MERC_TYPE__EPC ) || + ( AM_A_ROBOT( pSoldier ) && !gGameExternalOptions.fRobotUpgradeable) || + ( pSoldier->ubWhatKindOfMercAmI == MERC_TYPE__EPC && !AM_A_ROBOT( pSoldier ) ) || ( pSoldier->stats.bLife < OKLIFE ) ) { diff --git a/Strategic/mapscreen.h b/Strategic/mapscreen.h index 01a70728..16188e05 100644 --- a/Strategic/mapscreen.h +++ b/Strategic/mapscreen.h @@ -175,6 +175,7 @@ BOOLEAN MapCharacterHasAccessibleInventory( INT8 bCharNumber ); BOOLEAN InitializeInvPanelCoordsOld( ); BOOLEAN InitializeInvPanelCoordsNew( ); BOOLEAN InitializeInvPanelCoordsVehicle( ); +BOOLEAN InitializeInvPanelCoordsRobot( ); void initMapViewAndBorderCoordinates(void); // HEADROCK HAM 3.6: Calculate daily cost for all mercs who have one. diff --git a/Tactical/Interface Items.cpp b/Tactical/Interface Items.cpp index 7d9c0e81..9ea7ae75 100644 --- a/Tactical/Interface Items.cpp +++ b/Tactical/Interface Items.cpp @@ -1343,6 +1343,22 @@ void InitInventoryVehicle(INV_REGION_DESC *pRegionDesc, MOUSE_CALLBACK INVMoveCa MSYS_SetRegionUserData( &gSMInvRegion[ cnt ], 0, cnt ); } } +void InitInventoryRobot(INV_REGION_DESC *pRegionDesc, MOUSE_CALLBACK INVMoveCallback, MOUSE_CALLBACK INVClickCallback, BOOLEAN fSetHighestPrioity) +{ + for(int cnt=INV_START_POS; cntflags.uiStatusFlags & SOLDIER_VEHICLE) && UsingNewInventorySystem() == true && !vehicleInv[sPocket]) return lbePocket; + if(pSoldier && AM_A_ROBOT(pSoldier) && !robotInv[sPocket]) + return lbePocket; switch (icClass[sPocket]) { @@ -2542,6 +2560,10 @@ void INVRenderINVPanelItem( SOLDIERTYPE *pSoldier, INT16 sPocket, UINT8 fDirtyLe if((pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE) && UsingNewInventorySystem() == true && !vehicleInv[sPocket]) return; + if(pSoldier && AM_A_ROBOT(pSoldier) && !robotInv[sPocket] && UsingNewInventorySystem() && sPocket != HANDPOS) + return; + + INT16 sX, sY, newX, newY; INT16 sBarX, sBarY; OBJECTTYPE *pObject; @@ -2559,7 +2581,7 @@ void INVRenderINVPanelItem( SOLDIERTYPE *pSoldier, INT16 sPocket, UINT8 fDirtyLe sX = gSMInvData[ sPocket ].sX; sY = gSMInvData[ sPocket ].sY; - if ( UsingNewInventorySystem() && !(pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE)) + if ( UsingNewInventorySystem() && !(pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE) && !(AM_A_ROBOT(pSoldier)) ) { // If sPocket is not an equiped pocket, gather pocket information if(icClass[sPocket] != ITEM_NOT_FOUND) @@ -2758,6 +2780,9 @@ void INVRenderINVPanelItem( SOLDIERTYPE *pSoldier, INT16 sPocket, UINT8 fDirtyLe } #endif + if (AM_A_ROBOT(pSoldier) && sPocket == HANDPOS) + fHatchItOut = FALSE; + if ( fHatchItOut ) { //shadooow: hatch all pockets that we cannot put item into due to insufficient action points with red @@ -14478,6 +14503,8 @@ BOOLEAN CheckPocketEmpty( SOLDIERTYPE *pSoldier, INT16 sPocket ) return FALSE; if((pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE) && UsingNewInventorySystem() == true && !vehicleInv[sPocket]) return FALSE; + if(pSoldier && AM_A_ROBOT(pSoldier) && !robotInv[sPocket] && UsingNewInventorySystem()) + return FALSE; BOOLEAN bResult = FALSE; INT16 lbePocket = ITEM_NOT_FOUND; diff --git a/Tactical/Interface Items.h b/Tactical/Interface Items.h index ed0c9edb..607890ff 100644 --- a/Tactical/Interface Items.h +++ b/Tactical/Interface Items.h @@ -241,6 +241,7 @@ void InitInvData(INV_REGIONS &InvData, BOOLEAN fBigPocket, INT16 sBarDx, INT16 s void InitInventoryOld(); void InitInventoryNew(); void InitInventoryVehicle(INV_REGION_DESC *pRegionDesc, MOUSE_CALLBACK INVMoveCallback, MOUSE_CALLBACK INVClickCallback, BOOLEAN fSetHighestPrioity); +void InitInventoryRobot(INV_REGION_DESC *pRegionDesc, MOUSE_CALLBACK INVMoveCallback, MOUSE_CALLBACK INVClickCallback, BOOLEAN fSetHighestPrioity); void InitInventorySoldier(INV_REGION_DESC *pRegionDesc, MOUSE_CALLBACK INVMoveCallback, MOUSE_CALLBACK INVClickCallback, BOOLEAN fSetHighestPrioity, BOOLEAN fNIVmode); diff --git a/Tactical/Item Types.h b/Tactical/Item Types.h index dfe3bd19..d96b32b1 100644 --- a/Tactical/Item Types.h +++ b/Tactical/Item Types.h @@ -1202,6 +1202,18 @@ typedef struct // Flugente: a modifier for administration effectiveness UINT8 usAdministrationModifier; + + // rftr: robot attachments + FLOAT fRobotDamageReductionModifier; + INT8 bRobotStrBonus; + INT8 bRobotAgiBonus; + INT8 bRobotDexBonus; + INT8 bRobotTargetingSkillGrant; + INT8 bRobotChassisSkillGrant; + INT8 bRobotUtilitySkillGrant; + BOOLEAN fProvidesRobotCamo; + BOOLEAN fProvidesRobotNightVision; + BOOLEAN fProvidesRobotLaserBonus; } INVTYPE; @@ -1724,6 +1736,14 @@ const INT8 oldInv[NUM_INV_SLOTS] = { 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, // Determines which pockets to use for vehicles in the new inventory system. const INT8 vehicleInv[NUM_INV_SLOTS]= { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0}; +// Determines which pockets to use for Madlab's Robot in the new inventory system. +const INT8 robotInv[NUM_INV_SLOTS]= { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +#define ROBOT_AMMO_SLOT 14 +#define ROBOT_TARGETING_SLOT 15 +#define ROBOT_CHASSIS_SLOT 16 +#define ROBOT_UTILITY_SLOT 17 +#define ROBOT_INVENTORY_SLOT 18 + // Determines the default pocket const INT16 icDefault[NUM_INV_SLOTS] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,//0-13 diff --git a/Tactical/Items.cpp b/Tactical/Items.cpp index cf3746a7..078d2298 100644 --- a/Tactical/Items.cpp +++ b/Tactical/Items.cpp @@ -1493,6 +1493,12 @@ UINT8 ItemSlotLimit( OBJECTTYPE * pObject, INT16 bSlot, SOLDIERTYPE *pSoldier, B if (pSoldier != NULL && (pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE)) { pIndex = VEHICLE_POCKET_TYPE; } + else if (pSoldier && AM_A_ROBOT(pSoldier)) { + if (bSlot != ROBOT_AMMO_SLOT) + return 1; + + pIndex = VEHICLE_POCKET_TYPE; + } // IC Group Slots else if (bSlot == GUNSLINGPOCKPOS) { pIndex = GUNSLING_POCKET_TYPE; @@ -1637,6 +1643,12 @@ INT8 FindMetalDetectorInHand( SOLDIERTYPE * pSoldier ) return( SECONDHANDPOS ); } + // rftr: a metal detector can be installed into the robot + if ( pSoldier && AM_A_ROBOT(pSoldier) && (&(pSoldier->inv[ROBOT_UTILITY_SLOT]))->exists() && Item[pSoldier->inv[ROBOT_UTILITY_SLOT].usItem].metaldetector ) + { + return( ROBOT_UTILITY_SLOT ); + } + return( NO_SLOT ); } @@ -1822,6 +1834,8 @@ INT8 FindEmptySlotWithin( SOLDIERTYPE * pSoldier, INT8 bLower, INT8 bUpper ) continue; if((pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE) && !vehicleInv[bLoop]) continue; + if(AM_A_ROBOT(pSoldier) && !robotInv[bLoop]) + continue; if (pSoldier->inv[bLoop].exists() == false) { if (bLoop == SECONDHANDPOS && Item[pSoldier->inv[HANDPOS].usItem].twohanded ) @@ -6273,6 +6287,77 @@ BOOLEAN CanItemFitInVehicle( SOLDIERTYPE *pSoldier, OBJECTTYPE *pObj, INT8 bPos, return( TRUE ); } +BOOLEAN CanItemFitInRobot(SOLDIERTYPE* pSoldier, OBJECTTYPE* pObj, INT8 bPos, BOOLEAN fDoingPlacement) +{ + if((UsingNewInventorySystem() == false) || !(AM_A_ROBOT(pSoldier))) + return(FALSE); + if(!robotInv[bPos]) + return(FALSE); + + switch (bPos) + { + case ROBOT_AMMO_SLOT: + // no ammo boxes or ammo crates, and calibre has to match equipped gun + return + (Item[pObj->usItem].usItemClass & IC_AMMO) && + (Magazine[Item[pObj->usItem].ubClassIndex].ubMagType != AMMO_BOX) && + (Magazine[Item[pObj->usItem].ubClassIndex].ubMagType != AMMO_CRATE) && + (Magazine[Item[pObj->usItem].ubClassIndex].ubCalibre == Weapon[pSoldier->inv[HANDPOS].usItem].ubCalibre); + + case ROBOT_TARGETING_SLOT: + if (Item[pObj->usItem].fProvidesRobotLaserBonus) + return(TRUE); + + if (Item[pObj->usItem].fProvidesRobotNightVision) + return(TRUE); + + if (Item[pObj->usItem].bRobotTargetingSkillGrant > 0) + return(TRUE); + + return(FALSE); + + case ROBOT_CHASSIS_SLOT: + if (Item[pObj->usItem].bRobotStrBonus > 0 || Item[pObj->usItem].bRobotAgiBonus > 0 || Item[pObj->usItem].bRobotDexBonus > 0) + return(TRUE); + + if (Item[pObj->usItem].fProvidesRobotCamo) + return(TRUE); + + if (Item[pObj->usItem].fRobotDamageReductionModifier > 0.0f && Item[pObj->usItem].fRobotDamageReductionModifier < 1.0f) + return(TRUE); + + if (Item[pObj->usItem].bRobotChassisSkillGrant > 0) + return(TRUE); + + return(FALSE); + + case ROBOT_UTILITY_SLOT: + if (HasItemFlag(pObj->usItem, CLEANING_KIT)) + return(TRUE); + + if (HasItemFlag( pObj->usItem, RADIO_SET )) + return(TRUE); + + if (Item[pObj->usItem].metaldetector == 1) + return(TRUE); + + if (Item[pObj->usItem].xray == 1) + return(TRUE); + + if (Item[pObj->usItem].bRobotUtilitySkillGrant > 0) + return(TRUE); + + return(FALSE); + + // anything except ammo goes in the inventory, but has no effect on the robot + case ROBOT_INVENTORY_SLOT: + return (Item[pObj->usItem].usItemClass & IC_AMMO) == 0; + + // item doesn't fall into any of the above categories + default: + return(FALSE); + } +} BOOLEAN CanItemFitInPosition( SOLDIERTYPE *pSoldier, OBJECTTYPE *pObj, INT8 bPos, BOOLEAN fDoingPlacement ) { @@ -6285,6 +6370,8 @@ BOOLEAN CanItemFitInPosition( SOLDIERTYPE *pSoldier, OBJECTTYPE *pObj, INT8 bPos { if ( pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE ) return ( CanItemFitInVehicle( pSoldier, pObj, bPos, fDoingPlacement ) ); + else if ( AM_A_ROBOT(pSoldier) && bPos != HANDPOS) + return ( CanItemFitInRobot( pSoldier, pObj, bPos, fDoingPlacement ) ); } else if ( !oldInv[bPos] ) return(FALSE); @@ -6654,6 +6741,67 @@ BOOLEAN PlaceObject( SOLDIERTYPE * pSoldier, INT8 bPos, OBJECTTYPE * pObj ) return( FALSE ); } + if (AM_A_ROBOT(pSoldier)) + { + if (bPos == ROBOT_AMMO_SLOT) + { + PlayJA2Sample( ATTACH_TO_GUN, RATE_11025, SoundVolume( MIDVOLUME, pSoldier->sGridNo ), 1, SoundDir( pSoldier->sGridNo ) ); + } + else if (bPos == ROBOT_TARGETING_SLOT || bPos == ROBOT_CHASSIS_SLOT || bPos == ROBOT_UTILITY_SLOT) + { + PlayJA2Sample(REMOVING_TEXT, RATE_11025, SoundVolume(MIDVOLUME, pSoldier->sGridNo), 1, SoundDir(pSoldier->sGridNo)); + + const INT8 targetingSkill = Item[pObj->usItem].bRobotTargetingSkillGrant; + const INT8 chassisSkill = Item[pObj->usItem].bRobotChassisSkillGrant; + const INT8 utilitySkill = Item[pObj->usItem].bRobotUtilitySkillGrant; + if (gGameOptions.fNewTraitSystem && (targetingSkill > 0 || chassisSkill > 0 || utilitySkill > 0)) + { + BOOLEAN profileSet = FALSE; + BOOLEAN soldierSet = FALSE; + for (int a = 0; a < 30; ++a) + { + if (!profileSet && gMercProfiles[pSoldier->ubProfile].bSkillTraits[a] == 0) + { + profileSet = TRUE; + switch (bPos) + { + case ROBOT_TARGETING_SLOT: + gMercProfiles[pSoldier->ubProfile].bSkillTraits[a] = targetingSkill; + break; + + case ROBOT_CHASSIS_SLOT: + gMercProfiles[pSoldier->ubProfile].bSkillTraits[a] = chassisSkill; + break; + + case ROBOT_UTILITY_SLOT: + gMercProfiles[pSoldier->ubProfile].bSkillTraits[a] = utilitySkill; + break; + } + } + + if (!soldierSet && pSoldier->stats.ubSkillTraits[a] == 0) + { + soldierSet = TRUE; + switch (bPos) + { + case ROBOT_TARGETING_SLOT: + pSoldier->stats.ubSkillTraits[a] = targetingSkill; + break; + + case ROBOT_CHASSIS_SLOT: + pSoldier->stats.ubSkillTraits[a] = chassisSkill; + break; + + case ROBOT_UTILITY_SLOT: + pSoldier->stats.ubSkillTraits[a] = utilitySkill; + break; + } + } + } + } + } + } + // If the position is either head slot, then the item must be IC_FACE (checked in // CanItemFitInPosition). if ( bPos == HEAD1POS ) @@ -6695,7 +6843,7 @@ BOOLEAN PlaceObject( SOLDIERTYPE * pSoldier, INT8 bPos, OBJECTTYPE * pObj ) } // Lesh: bugfix - replacing weapon in auto with another weapon w/o auto-mode - if (bPos == HANDPOS && Item[ pObj->usItem ].usItemClass == IC_GUN) + if (bPos == HANDPOS && Item[ pObj->usItem ].usItemClass == IC_GUN && !AM_A_ROBOT(pSoldier)) { //Madd: added code for nosemiauto tag if (!Weapon[ Item[pObj->usItem].ubClassIndex ].NoSemiAuto) @@ -6872,6 +7020,12 @@ BOOLEAN PlaceObject( SOLDIERTYPE * pSoldier, INT8 bPos, OBJECTTYPE * pObj ) } //if we didn't reload, then we know we are stacking or swapping! + if (bPos == HANDPOS && AM_A_ROBOT(pSoldier)) + { + DoMessageBox(MSG_BOX_BASIC_STYLE, szRobotText[ROBOT_TEXT_CANNOT_CHANGE_INSTALLED_WEAPON], guiCurrentScreen, (UINT8)MSG_BOX_FLAG_OK, NULL, NULL); + return FALSE; + } + if (IsSlotASmallPocket(bPos) == true && FitsInSmallPocket(pObj) == false) { //there is nothing we can do, just return return FALSE; @@ -10082,7 +10236,7 @@ void ActivateXRayDevice( SOLDIERTYPE * pSoldier ) SOLDIERTYPE * pSoldier2; UINT32 uiSlot; - if ( Item[pSoldier->inv[ HANDPOS ].usItem].needsbatteries && pSoldier->inv[ HANDPOS ].exists() == true) + if ( Item[pSoldier->inv[ HANDPOS ].usItem].needsbatteries && pSoldier->inv[ HANDPOS ].exists() == true && !AM_A_ROBOT(pSoldier) ) { // check for batteries OBJECTTYPE* pBatteries = FindAttachedBatteries( &(pSoldier->inv[HANDPOS]) ); @@ -11281,6 +11435,13 @@ INT16 GetNightVisionRangeBonus( SOLDIERTYPE * pSoldier, UINT8 bLightLevel ) UINT16 usItem; INVTYPE *pItem; + if (AM_A_ROBOT(pSoldier) && Item[pSoldier->inv[ROBOT_TARGETING_SLOT].usItem].fProvidesRobotNightVision) + { + return bonus += BonusReduceMore( + NightBonusScale( Item[pSoldier->inv[ROBOT_TARGETING_SLOT].usItem].nightvisionrangebonus, bLightLevel ), + (pSoldier->inv[ROBOT_TARGETING_SLOT])[0]->data.objectStatus ); + } + //ADB and AXP 28.03.2007: CtH bug fix: We also want to check on a firing weapon, "raised" alone is not enough ;) bool usingGunScope = WeaponReady(pSoldier); // CHRISL: @@ -11379,6 +11540,13 @@ INT16 GetCaveVisionRangeBonus( SOLDIERTYPE * pSoldier, UINT8 bLightLevel ) UINT16 usItem; INVTYPE *pItem; + if (AM_A_ROBOT(pSoldier) && Item[pSoldier->inv[ROBOT_TARGETING_SLOT].usItem].fProvidesRobotNightVision) + { + return bonus += BonusReduceMore( + NightBonusScale( Item[pSoldier->inv[ROBOT_TARGETING_SLOT].usItem].cavevisionrangebonus, bLightLevel ), + (pSoldier->inv[ROBOT_TARGETING_SLOT])[0]->data.objectStatus ); + } + //ADB and AXP 28.03.2007: CtH bug fix: We also want to check on a firing weapon, "raised" alone is not enough ;) bool usingGunScope = WeaponReady(pSoldier); // CHRISL: @@ -12615,46 +12783,56 @@ INT16 GetWornCamo( SOLDIERTYPE * pSoldier ) INT8 bLoop; INT16 ttl=0; - for (bLoop = HELMETPOS; bLoop <= LEGPOS; ++bLoop) + if (AM_A_ROBOT(pSoldier)) { - if ( pSoldier->inv[bLoop].exists() ) + if (Item[pSoldier->inv[ROBOT_CHASSIS_SLOT].usItem].fProvidesRobotCamo) { - ttl += GetCamoBonus(&pSoldier->inv[bLoop]); - if ( UsingNewInventorySystem() ) - if ( bLoop == VESTPOS && pSoldier->inv[VESTPOCKPOS].exists() ) - { - // silversurfer: Using LBE vest. Only apply partial bonus from armor vest. - ttl -= (INT16)( ( 1.0 - gItemSettings.fCamoLBEoverVestModifier ) * Item[ pSoldier->inv[bLoop].usItem ].camobonus ); - } - else if ( bLoop == LEGPOS ) - { - FLOAT fLegPenalty = 0; - // depending on how many leg LBE we use the camo effect of the armor pants is higher or lower - fLegPenalty += pSoldier->inv[LTHIGHPOCKPOS].exists(); - fLegPenalty += pSoldier->inv[RTHIGHPOCKPOS].exists(); - // Using thigh rigs. Only apply partial bonus from armor pants. - if ( fLegPenalty > 0 ) - ttl -= (INT16)( ( 1.0 - gItemSettings.fCamoLBEoverPantsModifier ) * Item[ pSoldier->inv[bLoop].usItem ].camobonus * fLegPenalty / 2 ); - } + ttl += GetCamoBonus(&pSoldier->inv[ROBOT_CHASSIS_SLOT]); } } - - // CHRISL: Add additional loop for LBE items while using new inventory system - if( UsingNewInventorySystem() ) + else { - for (bLoop = VESTPOCKPOS; bLoop <= BPACKPOCKPOS; ++bLoop) + for (bLoop = HELMETPOS; bLoop <= LEGPOS; ++bLoop) { - if ( pSoldier->inv[bLoop].exists() == true ) + if ( pSoldier->inv[bLoop].exists() ) + { ttl += GetCamoBonus(&pSoldier->inv[bLoop]); + if ( UsingNewInventorySystem() ) + if ( bLoop == VESTPOS && pSoldier->inv[VESTPOCKPOS].exists() ) + { + // silversurfer: Using LBE vest. Only apply partial bonus from armor vest. + ttl -= (INT16)( ( 1.0 - gItemSettings.fCamoLBEoverVestModifier ) * Item[ pSoldier->inv[bLoop].usItem ].camobonus ); + } + else if ( bLoop == LEGPOS ) + { + FLOAT fLegPenalty = 0; + // depending on how many leg LBE we use the camo effect of the armor pants is higher or lower + fLegPenalty += pSoldier->inv[LTHIGHPOCKPOS].exists(); + fLegPenalty += pSoldier->inv[RTHIGHPOCKPOS].exists(); + // Using thigh rigs. Only apply partial bonus from armor pants. + if ( fLegPenalty > 0 ) + ttl -= (INT16)( ( 1.0 - gItemSettings.fCamoLBEoverPantsModifier ) * Item[ pSoldier->inv[bLoop].usItem ].camobonus * fLegPenalty / 2 ); + } + } } - //tais: guns can be camouflaged, this will make gun camo have effect when in main/second hand or on gunsling, did a check for guns and nothing else, hope that's enough. - if (pSoldier->inv[HANDPOS].exists() == true && Item[pSoldier->inv[HANDPOS].usItem].usItemClass & IC_WEAPON) - ttl += GetCamoBonus(&pSoldier->inv[HANDPOS]); - if (pSoldier->inv[SECONDHANDPOS].exists() == true && Item[pSoldier->inv[SECONDHANDPOS].usItem].usItemClass & IC_WEAPON) - ttl += GetCamoBonus(&pSoldier->inv[SECONDHANDPOS]); - if (pSoldier->inv[GUNSLINGPOCKPOS].exists() == true && Item[pSoldier->inv[GUNSLINGPOCKPOS].usItem].usItemClass & IC_WEAPON) - ttl += GetCamoBonus(&pSoldier->inv[GUNSLINGPOCKPOS]); + // CHRISL: Add additional loop for LBE items while using new inventory system + if( UsingNewInventorySystem() ) + { + for (bLoop = VESTPOCKPOS; bLoop <= BPACKPOCKPOS; ++bLoop) + { + if ( pSoldier->inv[bLoop].exists() == true ) + ttl += GetCamoBonus(&pSoldier->inv[bLoop]); + } + + //tais: guns can be camouflaged, this will make gun camo have effect when in main/second hand or on gunsling, did a check for guns and nothing else, hope that's enough. + if (pSoldier->inv[HANDPOS].exists() == true && Item[pSoldier->inv[HANDPOS].usItem].usItemClass & IC_WEAPON) + ttl += GetCamoBonus(&pSoldier->inv[HANDPOS]); + if (pSoldier->inv[SECONDHANDPOS].exists() == true && Item[pSoldier->inv[SECONDHANDPOS].usItem].usItemClass & IC_WEAPON) + ttl += GetCamoBonus(&pSoldier->inv[SECONDHANDPOS]); + if (pSoldier->inv[GUNSLINGPOCKPOS].exists() == true && Item[pSoldier->inv[GUNSLINGPOCKPOS].usItem].usItemClass & IC_WEAPON) + ttl += GetCamoBonus(&pSoldier->inv[GUNSLINGPOCKPOS]); + } } return __max(0, __min( ttl, ( 100 - gGameExternalOptions.bCamoKitArea ) ) ); @@ -12664,46 +12842,56 @@ INT16 GetWornUrbanCamo( SOLDIERTYPE * pSoldier ) INT8 bLoop; INT16 ttl=0; - for (bLoop = HELMETPOS; bLoop <= LEGPOS; ++bLoop) + if (AM_A_ROBOT(pSoldier)) { - if ( pSoldier->inv[bLoop].exists() ) + if (Item[pSoldier->inv[ROBOT_CHASSIS_SLOT].usItem].fProvidesRobotCamo) { - ttl += GetUrbanCamoBonus(&pSoldier->inv[bLoop]); - if ( UsingNewInventorySystem() ) - if ( bLoop == VESTPOS && pSoldier->inv[VESTPOCKPOS].exists() ) - { - // silversurfer: Using LBE vest. Only apply partial bonus from armor vest. - ttl -= (INT16)( ( 1.0 - gItemSettings.fCamoLBEoverVestModifier ) * Item[ pSoldier->inv[bLoop].usItem ].urbanCamobonus ); - } - else if ( bLoop == LEGPOS ) - { - FLOAT fLegPenalty = 0; - // depending on how many leg LBE we use the camo effect of the armor pants is higher or lower - fLegPenalty += pSoldier->inv[LTHIGHPOCKPOS].exists(); - fLegPenalty += pSoldier->inv[RTHIGHPOCKPOS].exists(); - // Using thigh rigs. Only apply partial bonus from armor pants. - if ( fLegPenalty > 0 ) - ttl -= (INT16)( ( 1.0 - gItemSettings.fCamoLBEoverPantsModifier ) * Item[ pSoldier->inv[bLoop].usItem ].urbanCamobonus * fLegPenalty / 2 ); - } + ttl += GetUrbanCamoBonus(&pSoldier->inv[ROBOT_CHASSIS_SLOT]); } } - - // CHRISL: Add additional loop for LBE items while using new inventory system - if( UsingNewInventorySystem() ) + else { - for (bLoop = VESTPOCKPOS; bLoop <= BPACKPOCKPOS; ++bLoop) + for (bLoop = HELMETPOS; bLoop <= LEGPOS; ++bLoop) { - if ( pSoldier->inv[bLoop].exists() == true ) + if (pSoldier->inv[bLoop].exists()) + { ttl += GetUrbanCamoBonus(&pSoldier->inv[bLoop]); + if (UsingNewInventorySystem()) + if (bLoop == VESTPOS && pSoldier->inv[VESTPOCKPOS].exists()) + { + // silversurfer: Using LBE vest. Only apply partial bonus from armor vest. + ttl -= (INT16)((1.0 - gItemSettings.fCamoLBEoverVestModifier) * Item[pSoldier->inv[bLoop].usItem].urbanCamobonus); + } + else if (bLoop == LEGPOS) + { + FLOAT fLegPenalty = 0; + // depending on how many leg LBE we use the camo effect of the armor pants is higher or lower + fLegPenalty += pSoldier->inv[LTHIGHPOCKPOS].exists(); + fLegPenalty += pSoldier->inv[RTHIGHPOCKPOS].exists(); + // Using thigh rigs. Only apply partial bonus from armor pants. + if (fLegPenalty > 0) + ttl -= (INT16)((1.0 - gItemSettings.fCamoLBEoverPantsModifier) * Item[pSoldier->inv[bLoop].usItem].urbanCamobonus * fLegPenalty / 2); + } + } } - //tais: guns can be camouflaged, this will make gun camo have effect when in main/second hand or on gunsling, did a check for guns and nothing else, hope that's enough. - if (pSoldier->inv[HANDPOS].exists() == true && Item[pSoldier->inv[HANDPOS].usItem].usItemClass & IC_WEAPON) - ttl += GetUrbanCamoBonus(&pSoldier->inv[HANDPOS]); - if (pSoldier->inv[SECONDHANDPOS].exists() == true && Item[pSoldier->inv[SECONDHANDPOS].usItem].usItemClass & IC_WEAPON) - ttl += GetUrbanCamoBonus(&pSoldier->inv[SECONDHANDPOS]); - if (pSoldier->inv[GUNSLINGPOCKPOS].exists() == true && Item[pSoldier->inv[GUNSLINGPOCKPOS].usItem].usItemClass & IC_WEAPON) - ttl += GetUrbanCamoBonus(&pSoldier->inv[GUNSLINGPOCKPOS]); + // CHRISL: Add additional loop for LBE items while using new inventory system + if (UsingNewInventorySystem()) + { + for (bLoop = VESTPOCKPOS; bLoop <= BPACKPOCKPOS; ++bLoop) + { + if (pSoldier->inv[bLoop].exists() == true) + ttl += GetUrbanCamoBonus(&pSoldier->inv[bLoop]); + } + + //tais: guns can be camouflaged, this will make gun camo have effect when in main/second hand or on gunsling, did a check for guns and nothing else, hope that's enough. + if (pSoldier->inv[HANDPOS].exists() == true && Item[pSoldier->inv[HANDPOS].usItem].usItemClass & IC_WEAPON) + ttl += GetUrbanCamoBonus(&pSoldier->inv[HANDPOS]); + if (pSoldier->inv[SECONDHANDPOS].exists() == true && Item[pSoldier->inv[SECONDHANDPOS].usItem].usItemClass & IC_WEAPON) + ttl += GetUrbanCamoBonus(&pSoldier->inv[SECONDHANDPOS]); + if (pSoldier->inv[GUNSLINGPOCKPOS].exists() == true && Item[pSoldier->inv[GUNSLINGPOCKPOS].usItem].usItemClass & IC_WEAPON) + ttl += GetUrbanCamoBonus(&pSoldier->inv[GUNSLINGPOCKPOS]); + } } return __max(0, __min( ttl, ( 100 - gGameExternalOptions.bCamoKitArea ) ) ); @@ -12713,46 +12901,56 @@ INT16 GetWornDesertCamo( SOLDIERTYPE * pSoldier ) INT8 bLoop; INT16 ttl=0; - for (bLoop = HELMETPOS; bLoop <= LEGPOS; bLoop++) + if (AM_A_ROBOT(pSoldier)) { - if ( pSoldier->inv[bLoop].exists() == true ) + if (Item[pSoldier->inv[ROBOT_CHASSIS_SLOT].usItem].fProvidesRobotCamo) { - ttl += GetDesertCamoBonus(&pSoldier->inv[bLoop]); - if ( UsingNewInventorySystem() ) - if ( bLoop == VESTPOS && pSoldier->inv[VESTPOCKPOS].exists() ) - { - // silversurfer: Using LBE vest. Only apply partial bonus from armor vest. - ttl -= (INT16)( ( 1.0 - gItemSettings.fCamoLBEoverVestModifier ) * Item[ pSoldier->inv[bLoop].usItem ].desertCamobonus ); - } - else if ( bLoop == LEGPOS ) - { - FLOAT fLegPenalty = 0; - // depending on how many leg LBE we use the camo effect of the armor pants is higher or lower - fLegPenalty += pSoldier->inv[LTHIGHPOCKPOS].exists(); - fLegPenalty += pSoldier->inv[RTHIGHPOCKPOS].exists(); - // Using thigh rigs. Only apply partial bonus from armor pants. - if ( fLegPenalty > 0 ) - ttl -= (INT16)( ( 1.0 - gItemSettings.fCamoLBEoverPantsModifier ) * Item[ pSoldier->inv[bLoop].usItem ].desertCamobonus * fLegPenalty / 2 ); - } + ttl += GetDesertCamoBonus(&pSoldier->inv[ROBOT_CHASSIS_SLOT]); } } - - // CHRISL: Add additional loop for LBE items while using new inventory system - if((UsingNewInventorySystem() == true)) + else { - for (bLoop = VESTPOCKPOS; bLoop <= BPACKPOCKPOS; bLoop++) + for (bLoop = HELMETPOS; bLoop <= LEGPOS; bLoop++) { - if ( pSoldier->inv[bLoop].exists() == true ) + if (pSoldier->inv[bLoop].exists() == true) + { ttl += GetDesertCamoBonus(&pSoldier->inv[bLoop]); + if (UsingNewInventorySystem()) + if (bLoop == VESTPOS && pSoldier->inv[VESTPOCKPOS].exists()) + { + // silversurfer: Using LBE vest. Only apply partial bonus from armor vest. + ttl -= (INT16)((1.0 - gItemSettings.fCamoLBEoverVestModifier) * Item[pSoldier->inv[bLoop].usItem].desertCamobonus); + } + else if (bLoop == LEGPOS) + { + FLOAT fLegPenalty = 0; + // depending on how many leg LBE we use the camo effect of the armor pants is higher or lower + fLegPenalty += pSoldier->inv[LTHIGHPOCKPOS].exists(); + fLegPenalty += pSoldier->inv[RTHIGHPOCKPOS].exists(); + // Using thigh rigs. Only apply partial bonus from armor pants. + if (fLegPenalty > 0) + ttl -= (INT16)((1.0 - gItemSettings.fCamoLBEoverPantsModifier) * Item[pSoldier->inv[bLoop].usItem].desertCamobonus * fLegPenalty / 2); + } + } } - //tais: guns can be camouflaged, this will make gun camo have effect when in main/second hand or on gunsling, did a check for guns and nothing else, hope that's enough. - if (pSoldier->inv[HANDPOS].exists() == true && Item[pSoldier->inv[HANDPOS].usItem].usItemClass & IC_WEAPON) - ttl += GetDesertCamoBonus(&pSoldier->inv[HANDPOS]); - if (pSoldier->inv[SECONDHANDPOS].exists() == true && Item[pSoldier->inv[SECONDHANDPOS].usItem].usItemClass & IC_WEAPON) - ttl += GetDesertCamoBonus(&pSoldier->inv[SECONDHANDPOS]); - if (pSoldier->inv[GUNSLINGPOCKPOS].exists() == true && Item[pSoldier->inv[GUNSLINGPOCKPOS].usItem].usItemClass & IC_WEAPON) - ttl += GetDesertCamoBonus(&pSoldier->inv[GUNSLINGPOCKPOS]); + // CHRISL: Add additional loop for LBE items while using new inventory system + if ((UsingNewInventorySystem() == true)) + { + for (bLoop = VESTPOCKPOS; bLoop <= BPACKPOCKPOS; bLoop++) + { + if (pSoldier->inv[bLoop].exists() == true) + ttl += GetDesertCamoBonus(&pSoldier->inv[bLoop]); + } + + //tais: guns can be camouflaged, this will make gun camo have effect when in main/second hand or on gunsling, did a check for guns and nothing else, hope that's enough. + if (pSoldier->inv[HANDPOS].exists() == true && Item[pSoldier->inv[HANDPOS].usItem].usItemClass & IC_WEAPON) + ttl += GetDesertCamoBonus(&pSoldier->inv[HANDPOS]); + if (pSoldier->inv[SECONDHANDPOS].exists() == true && Item[pSoldier->inv[SECONDHANDPOS].usItem].usItemClass & IC_WEAPON) + ttl += GetDesertCamoBonus(&pSoldier->inv[SECONDHANDPOS]); + if (pSoldier->inv[GUNSLINGPOCKPOS].exists() == true && Item[pSoldier->inv[GUNSLINGPOCKPOS].usItem].usItemClass & IC_WEAPON) + ttl += GetDesertCamoBonus(&pSoldier->inv[GUNSLINGPOCKPOS]); + } } return __max(0, __min( ttl, ( 100 - gGameExternalOptions.bCamoKitArea ) ) ); } @@ -12761,46 +12959,56 @@ INT16 GetWornSnowCamo( SOLDIERTYPE * pSoldier ) INT8 bLoop; INT16 ttl=0; - for (bLoop = HELMETPOS; bLoop <= LEGPOS; ++bLoop) + if (AM_A_ROBOT(pSoldier)) { - if ( pSoldier->inv[bLoop].exists() == true ) + if (Item[pSoldier->inv[ROBOT_CHASSIS_SLOT].usItem].fProvidesRobotCamo) { - ttl += GetSnowCamoBonus(&pSoldier->inv[bLoop]); - if ( UsingNewInventorySystem() ) - if ( bLoop == VESTPOS && pSoldier->inv[VESTPOCKPOS].exists() ) - { - // silversurfer: Using LBE vest. Only apply partial bonus from armor vest. - ttl -= (INT16)( ( 1.0 - gItemSettings.fCamoLBEoverVestModifier ) * Item[ pSoldier->inv[bLoop].usItem ].snowCamobonus ); - } - else if ( bLoop == LEGPOS ) - { - FLOAT fLegPenalty = 0; - // depending on how many leg LBE we use the camo effect of the armor pants is higher or lower - fLegPenalty += pSoldier->inv[LTHIGHPOCKPOS].exists(); - fLegPenalty += pSoldier->inv[RTHIGHPOCKPOS].exists(); - // Using thigh rigs. Only apply partial bonus from armor pants. - if ( fLegPenalty > 0 ) - ttl -= (INT16)( ( 1.0 - gItemSettings.fCamoLBEoverPantsModifier ) * Item[ pSoldier->inv[bLoop].usItem ].snowCamobonus * fLegPenalty / 2 ); - } + ttl += GetSnowCamoBonus(&pSoldier->inv[ROBOT_CHASSIS_SLOT]); } } - - // CHRISL: Add additional loop for LBE items while using new inventory system - if((UsingNewInventorySystem() == true)) + else { - for (bLoop = VESTPOCKPOS; bLoop <= BPACKPOCKPOS; bLoop++) + for (bLoop = HELMETPOS; bLoop <= LEGPOS; ++bLoop) { - if ( pSoldier->inv[bLoop].exists() == true ) + if (pSoldier->inv[bLoop].exists() == true) + { ttl += GetSnowCamoBonus(&pSoldier->inv[bLoop]); + if (UsingNewInventorySystem()) + if (bLoop == VESTPOS && pSoldier->inv[VESTPOCKPOS].exists()) + { + // silversurfer: Using LBE vest. Only apply partial bonus from armor vest. + ttl -= (INT16)((1.0 - gItemSettings.fCamoLBEoverVestModifier) * Item[pSoldier->inv[bLoop].usItem].snowCamobonus); + } + else if (bLoop == LEGPOS) + { + FLOAT fLegPenalty = 0; + // depending on how many leg LBE we use the camo effect of the armor pants is higher or lower + fLegPenalty += pSoldier->inv[LTHIGHPOCKPOS].exists(); + fLegPenalty += pSoldier->inv[RTHIGHPOCKPOS].exists(); + // Using thigh rigs. Only apply partial bonus from armor pants. + if (fLegPenalty > 0) + ttl -= (INT16)((1.0 - gItemSettings.fCamoLBEoverPantsModifier) * Item[pSoldier->inv[bLoop].usItem].snowCamobonus * fLegPenalty / 2); + } + } } - //tais: guns can be camouflaged, this will make gun camo have effect when in main/second hand or on gunsling, did a check for guns and nothing else, hope that's enough. - if (pSoldier->inv[HANDPOS].exists() == true && Item[pSoldier->inv[HANDPOS].usItem].usItemClass & IC_WEAPON) - ttl += GetSnowCamoBonus(&pSoldier->inv[HANDPOS]); - if (pSoldier->inv[SECONDHANDPOS].exists() == true && Item[pSoldier->inv[SECONDHANDPOS].usItem].usItemClass & IC_WEAPON) - ttl += GetSnowCamoBonus(&pSoldier->inv[SECONDHANDPOS]); - if (pSoldier->inv[GUNSLINGPOCKPOS].exists() == true && Item[pSoldier->inv[GUNSLINGPOCKPOS].usItem].usItemClass & IC_WEAPON) - ttl += GetSnowCamoBonus(&pSoldier->inv[GUNSLINGPOCKPOS]); + // CHRISL: Add additional loop for LBE items while using new inventory system + if ((UsingNewInventorySystem() == true)) + { + for (bLoop = VESTPOCKPOS; bLoop <= BPACKPOCKPOS; bLoop++) + { + if (pSoldier->inv[bLoop].exists() == true) + ttl += GetSnowCamoBonus(&pSoldier->inv[bLoop]); + } + + //tais: guns can be camouflaged, this will make gun camo have effect when in main/second hand or on gunsling, did a check for guns and nothing else, hope that's enough. + if (pSoldier->inv[HANDPOS].exists() == true && Item[pSoldier->inv[HANDPOS].usItem].usItemClass & IC_WEAPON) + ttl += GetSnowCamoBonus(&pSoldier->inv[HANDPOS]); + if (pSoldier->inv[SECONDHANDPOS].exists() == true && Item[pSoldier->inv[SECONDHANDPOS].usItem].usItemClass & IC_WEAPON) + ttl += GetSnowCamoBonus(&pSoldier->inv[SECONDHANDPOS]); + if (pSoldier->inv[GUNSLINGPOCKPOS].exists() == true && Item[pSoldier->inv[GUNSLINGPOCKPOS].usItem].usItemClass & IC_WEAPON) + ttl += GetSnowCamoBonus(&pSoldier->inv[GUNSLINGPOCKPOS]); + } } return __max(0, __min( ttl, ( 100 - gGameExternalOptions.bCamoKitArea ) ) ); } diff --git a/Tactical/Items.h b/Tactical/Items.h index 264d6acc..d0e2649b 100644 --- a/Tactical/Items.h +++ b/Tactical/Items.h @@ -131,6 +131,7 @@ attachmentList ReInitMergedItem(SOLDIERTYPE* pSoldier, OBJECTTYPE* pObj, UINT16 void EjectAmmoAndPlace(SOLDIERTYPE* pSoldier, OBJECTTYPE* pObj, UINT8 subObject = 0); BOOLEAN CanItemFitInVehicle( SOLDIERTYPE *pSoldier, OBJECTTYPE *pObj, INT8 bPos, BOOLEAN fDoingPlacement ); +BOOLEAN CanItemFitInRobot( SOLDIERTYPE *pSoldier, OBJECTTYPE *pObj, INT8 bPos, BOOLEAN fDoingPlacement ); BOOLEAN CanItemFitInPosition( SOLDIERTYPE *pSoldier, OBJECTTYPE *pObj, INT8 bPos, BOOLEAN fDoingPlacement ); void DistributeStatus(OBJECTTYPE* pSourceObject, OBJECTTYPE* pTargetObject, INT16 bMaxPoints); diff --git a/Tactical/LOS.cpp b/Tactical/LOS.cpp index 5689f2b8..303196f0 100644 --- a/Tactical/LOS.cpp +++ b/Tactical/LOS.cpp @@ -8640,6 +8640,10 @@ void AdjustTargetCenterPoint( SOLDIERTYPE *pShooter, INT32 iTargetGridNo, FLOAT //INT32 iLaserRange = GetBestLaserRange(&(pShooter->inv[pSoldier->ubAttackingHand])); INT16 sLaserRange = GetBestLaserRange(pWeapon); + if (AM_A_ROBOT(pShooter) && Item[pShooter->inv[ROBOT_TARGETING_SLOT].usItem].fProvidesRobotLaserBonus) + { + sLaserRange = max(sLaserRange, GetBestLaserRange(&pShooter->inv[ROBOT_TARGETING_SLOT])); + } // laser pointers can provide a percentage bonus to base aperture if (sLaserRange > 0 && ( gGameCTHConstants.LASER_PERFORMANCE_BONUS_HIP + gGameCTHConstants.LASER_PERFORMANCE_BONUS_IRON + gGameCTHConstants.LASER_PERFORMANCE_BONUS_SCOPE != 0) ) diff --git a/Tactical/SkillCheck.cpp b/Tactical/SkillCheck.cpp index ff8f1831..e367aaba 100644 --- a/Tactical/SkillCheck.cpp +++ b/Tactical/SkillCheck.cpp @@ -50,6 +50,14 @@ INT16 EffectiveStrength( SOLDIERTYPE *pSoldier, BOOLEAN fTrainer ) iEffStrength = 0; } + if (AM_A_ROBOT(pSoldier)) + { + if (Item[pSoldier->inv[ROBOT_CHASSIS_SLOT].usItem].bRobotStrBonus > 0) + { + iEffStrength += Item[pSoldier->inv[ROBOT_CHASSIS_SLOT].usItem].bRobotStrBonus; + } + } + // Flugente: diseases can affect stat effectivity INT16 diseaseeffect = 0; if ( gGameExternalOptions.fDisease ) @@ -93,6 +101,14 @@ INT16 EffectiveAgility( SOLDIERTYPE * pSoldier, BOOLEAN fTrainer ) iEffAgility = pSoldier->stats.bAgility; + if (AM_A_ROBOT(pSoldier)) + { + if (Item[pSoldier->inv[ROBOT_CHASSIS_SLOT].usItem].bRobotAgiBonus > 0) + { + iEffAgility += Item[pSoldier->inv[ROBOT_CHASSIS_SLOT].usItem].bRobotAgiBonus; + } + } + if ( !fTrainer ) iEffAgility += pSoldier->bExtraAgility; @@ -266,6 +282,14 @@ INT16 EffectiveDexterity( SOLDIERTYPE * pSoldier, BOOLEAN fTrainer ) iEffDexterity = pSoldier->stats.bDexterity; + if (AM_A_ROBOT(pSoldier)) + { + if (Item[pSoldier->inv[ROBOT_CHASSIS_SLOT].usItem].bRobotDexBonus > 0) + { + iEffDexterity += Item[pSoldier->inv[ROBOT_CHASSIS_SLOT].usItem].bRobotDexBonus; + } + } + if ( !fTrainer ) iEffDexterity += pSoldier->bExtraDexterity; diff --git a/Tactical/Soldier Control.cpp b/Tactical/Soldier Control.cpp index 4d7ffc5d..b15fc7dd 100644 --- a/Tactical/Soldier Control.cpp +++ b/Tactical/Soldier Control.cpp @@ -1993,7 +1993,7 @@ INT16 SOLDIERTYPE::CalcActionPoints( void ) } // If tired, reduce action points accordingly (by up to 1/2) - if ( this->bBreath < 100 && !(this->flags.uiStatusFlags & SOLDIER_VEHICLE) ) + if ( this->bBreath < 100 && !(this->flags.uiStatusFlags & SOLDIER_VEHICLE) && !AM_A_ROBOT(this)) ubPoints -= (ubPoints * (100 - this->bBreath)) / 200; if ( this->sWeightCarriedAtTurnStart > 100 ) @@ -18078,6 +18078,32 @@ void SOLDIERTYPE::SoldierPropertyUpkeep( ) if ( this->usSkillCooldown[SOLDIER_COOLDOWN_DRUGUSER_COMBAT] ) this->usSkillCooldown[SOLDIER_COOLDOWN_DRUGUSER_COMBAT]--; + if (AM_A_ROBOT(this) && Item[this->inv[ROBOT_UTILITY_SLOT].usItem].xray == 1) + { + if (this->usSkillCooldown[SOLDIER_COOLDOWN_ROBOT_XRAY]) + this->usSkillCooldown[SOLDIER_COOLDOWN_ROBOT_XRAY]--; + else if(this->bInSector) + { + // this allows the robot to do an x-ray ping if there are enemies in sector + SOLDIERTYPE* pTeamSoldier = Menptr; + INT32 cnt = 0; + for (; cnt < TOTAL_SOLDIERS; pTeamSoldier++, cnt++) + { + if (pTeamSoldier->bActive && pTeamSoldier->bInSector && pTeamSoldier->stats.bLife > 0) + { + if (!pTeamSoldier->aiData.bNeutral && (pTeamSoldier->bSide != 0)) + { + this->usSkillCooldown[SOLDIER_COOLDOWN_ROBOT_XRAY] += 2; + ActivateXRayDevice(this); + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szRobotText[ROBOT_TEXT_XRAY_ACTIVATED] ); + break; + } + } + } + + } + } + // if soldier was seen this turn, increase his observed counter if ( this->usSoldierFlagMask & SOLDIER_ENEMY_OBSERVEDTHISTURN ) { @@ -18589,6 +18615,15 @@ STR16 SOLDIERTYPE::PrintSkillDesc( INT8 iSkill, INT32 sGridNo ) BOOLEAN SOLDIERTYPE::CanUseRadio( BOOLEAN fCheckForAP ) { + // special case: robot upgraded with a radio set + if (AM_A_ROBOT(this)) + { + if (HasItemFlag(this->inv[ROBOT_UTILITY_SLOT].usItem, RADIO_SET)) + return !fCheckForAP || EnoughPoints(this, APBPConstants[AP_RADIO], 0, FALSE); + + return FALSE; + } + // only radio operators can use this equipment if ( !NUM_SKILL_TRAITS( this, RADIO_OPERATOR_NT ) ) return FALSE; @@ -18620,6 +18655,9 @@ BOOLEAN SOLDIERTYPE::UseRadio( ) else pObj = GetObjectWithFlag( RADIO_SET ); + if (AM_A_ROBOT(this)) + pObj = &(inv[ROBOT_UTILITY_SLOT]); + if ( pObj && HasItemFlag( pObj->usItem, RADIO_SET ) ) { // status % chance of success diff --git a/Tactical/Soldier Control.h b/Tactical/Soldier Control.h index 1e605d50..f3d2b65c 100644 --- a/Tactical/Soldier Control.h +++ b/Tactical/Soldier Control.h @@ -644,6 +644,7 @@ enum { SOLDIER_COOLDOWN_CRYO, // counts how many turns character will be frozen SOLDIER_COOLDOWN_INTEL_PENALTY, // after being discovered, we can't gain intel from the assignment for this many hours SOLDIER_COOLDOWN_DRUGUSER_COMBAT, // after a drug user deliberately took drugs, he will not do so on his own for a while + SOLDIER_COOLDOWN_ROBOT_XRAY, // rftr: robot can use x-ray detector SOLDIER_COOLDOWN_MAX = 20, // enough space for fillers }; diff --git a/Tactical/Tactical Turns.cpp b/Tactical/Tactical Turns.cpp index 64836d5e..42fd6adf 100644 --- a/Tactical/Tactical Turns.cpp +++ b/Tactical/Tactical Turns.cpp @@ -246,28 +246,31 @@ void HandleTacticalEndTurn( ) cnt = gTacticalStatus.Team[ gbPlayerNum ].bFirstID; for ( pSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; cnt++,pSoldier++) { - if ( pSoldier->bActive && pSoldier->stats.bLife > 0 && !( pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE ) && !( AM_A_ROBOT( pSoldier ) ) ) + if ( pSoldier->bActive && pSoldier->stats.bLife > 0 && !( pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE ) ) { // Handle everything from getting breath back, to bleeding, etc pSoldier->EVENT_BeginMercTurn( TRUE, 0 ); - // Handle Player services - HandlePlayerServices( pSoldier ); - - // if time is up, turn off xray - if ( pSoldier->uiXRayActivatedTime && uiTime > pSoldier->uiXRayActivatedTime + XRAY_TIME ) + if (!AM_A_ROBOT(pSoldier)) { - TurnOffXRayEffects( pSoldier ); - } + // Handle Player services + HandlePlayerServices( pSoldier ); - // Handle stat changes if ness. - //if ( fCheckStats ) - //{ - //// UpdateStats( pSoldier ); - //} - - // Flugente: update multi-turn actions - pSoldier->UpdateMultiTurnAction(); + // if time is up, turn off xray + if ( pSoldier->uiXRayActivatedTime && uiTime > pSoldier->uiXRayActivatedTime + XRAY_TIME ) + { + TurnOffXRayEffects( pSoldier ); + } + + // Handle stat changes if ness. + //if ( fCheckStats ) + //{ + //// UpdateStats( pSoldier ); + //} + + // Flugente: update multi-turn actions + pSoldier->UpdateMultiTurnAction(); + } } } diff --git a/Tactical/Weapons.cpp b/Tactical/Weapons.cpp index 8eaf8192..cf4a45fb 100644 --- a/Tactical/Weapons.cpp +++ b/Tactical/Weapons.cpp @@ -3085,7 +3085,27 @@ BOOLEAN UseGunNCTH( SOLDIERTYPE *pSoldier , INT32 sTargetGridNo ) if ( !PreRandom( uiDepreciateTest ) && ( (*pObjAttHand)[0]->data.objectStatus > 1) ) { - (*pObjAttHand)[0]->data.objectStatus--; + if (AM_A_ROBOT(pSoldier) && HasItemFlag(pSoldier->inv[ROBOT_UTILITY_SLOT].usItem, CLEANING_KIT)) + { + OBJECTTYPE* pRobotCleaningKit = &pSoldier->inv[ROBOT_UTILITY_SLOT]; + if ((*pRobotCleaningKit)[0]->data.objectStatus > 0) + { + (*pRobotCleaningKit)[0]->data.objectStatus--; + if ((*pRobotCleaningKit)[0]->data.objectStatus <= 0) + { + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szRobotText[ROBOT_TEXT_CLEANING_KIT_DEPLETED] ); + pRobotCleaningKit->RemoveObjectsFromStack(1); + } + } + else + { + (*pObjAttHand)[0]->data.objectStatus--; + } + } + else + { + (*pObjAttHand)[0]->data.objectStatus--; + } } // reduce monster smell (gunpowder smell) @@ -3881,7 +3901,27 @@ BOOLEAN UseGun( SOLDIERTYPE *pSoldier , INT32 sTargetGridNo ) if ( !PreRandom( uiDepreciateTest ) && ( (*pObjUsed)[0]->data.objectStatus > 1) ) { - (*pObjUsed)[0]->data.objectStatus--; + if (AM_A_ROBOT(pSoldier) && HasItemFlag(pSoldier->inv[ROBOT_UTILITY_SLOT].usItem, CLEANING_KIT)) + { + OBJECTTYPE* pRobotCleaningKit = &pSoldier->inv[ROBOT_UTILITY_SLOT]; + if ((*pRobotCleaningKit)[0]->data.objectStatus > 0) + { + (*pRobotCleaningKit)[0]->data.objectStatus--; + if ((*pRobotCleaningKit)[0]->data.objectStatus <= 0) + { + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szRobotText[ROBOT_TEXT_CLEANING_KIT_DEPLETED] ); + pRobotCleaningKit->RemoveObjectsFromStack(1); + } + } + else + { + (*pObjUsed)[0]->data.objectStatus--; + } + } + else + { + (*pObjUsed)[0]->data.objectStatus--; + } } // reduce monster smell (gunpowder smell) @@ -7431,9 +7471,17 @@ UINT32 CalcChanceToHitGun(SOLDIERTYPE *pSoldier, INT32 sGridNo, INT16 ubAimTime, // Equipment Modifiers iChance += GetGearToHitBonus ( pSoldier ); - INT16 moda = GetToHitBonus( pInHand, iRange, bLightLevel, stance && iRange > MIN_PRONE_RANGE ); - INT16 modb = GetToHitBonus( pInHand, iRange, bLightLevel, gAnimControl[ pSoldier->usAnimState ].ubEndHeight && iRange > MIN_PRONE_RANGE ); - iChance += (INT32)((gGameExternalOptions.ubProneModifierPercentage * moda + (100 - gGameExternalOptions.ubProneModifierPercentage) * modb)/100); + if (AM_A_ROBOT(pSoldier) && Item[pSoldier->inv[ROBOT_TARGETING_SLOT].usItem].fProvidesRobotLaserBonus) + { + iChance += GetToHitBonus(&(pSoldier->inv[ROBOT_TARGETING_SLOT]), iRange, bLightLevel, FALSE); + } + else + { + INT16 moda = GetToHitBonus(pInHand, iRange, bLightLevel, stance && iRange > MIN_PRONE_RANGE); + INT16 modb = GetToHitBonus(pInHand, iRange, bLightLevel, gAnimControl[pSoldier->usAnimState].ubEndHeight && iRange > MIN_PRONE_RANGE); + iChance += (INT32)((gGameExternalOptions.ubProneModifierPercentage * moda + (100 - gGameExternalOptions.ubProneModifierPercentage) * modb) / 100); + } + ///////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////// @@ -8071,6 +8119,24 @@ INT32 BulletImpact( SOLDIERTYPE *pFirer, BULLET *pBullet, SOLDIERTYPE * pTarget, } } + // robot plating damage resistance + if (AM_A_ROBOT(pTarget)) + { + FLOAT robotDamageReduction = Item[pTarget->inv[ROBOT_CHASSIS_SLOT].usItem].fRobotDamageReductionModifier; + if (robotDamageReduction > 0.0f && robotDamageReduction < 1.0f) + { + // apply damage reduction, then degrade armour plate based on original damage + damagefactor *= Item[pTarget->inv[ROBOT_CHASSIS_SLOT].usItem].fRobotDamageReductionModifier; + OBJECTTYPE* pRobotPlate = &(pTarget->inv[ROBOT_CHASSIS_SLOT]); + (*pRobotPlate)[0]->data.objectStatus -= max(1, iOrigImpact/12); + if((*pRobotPlate)[0]->data.objectStatus <= 0) + { + ScreenMsg(FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szRobotText[ROBOT_TEXT_PLATE_DESTROYED]); + pRobotPlate->RemoveObjectsFromStack(1); + } + } + } + iOrigImpact = iOrigImpact * damagefactor; // plus/minus up to 25% due to "random" factors (major organs hit or missed, @@ -9940,6 +10006,42 @@ void HandleTacticalEffectsOfEquipmentChange( SOLDIERTYPE *pSoldier, UINT32 uiInv } } } + + if (AM_A_ROBOT(pSoldier) && gGameOptions.fNewTraitSystem ) + { + const INT8 targetingSkill = Item[usOldItem].bRobotTargetingSkillGrant; + const INT8 chassisSkill = Item[usOldItem].bRobotChassisSkillGrant; + const INT8 utilitySkill = Item[usOldItem].bRobotUtilitySkillGrant; + for (int a = 0; a < 30; ++a) + { + if (targetingSkill > 0) + { + if (pSoldier->stats.ubSkillTraits[a] == targetingSkill) + pSoldier->stats.ubSkillTraits[a] = 0; + + if (gMercProfiles[pSoldier->ubProfile].bSkillTraits[a] == targetingSkill) + gMercProfiles[pSoldier->ubProfile].bSkillTraits[a] = 0; + } + + if (chassisSkill > 0) + { + if (pSoldier->stats.ubSkillTraits[a] == chassisSkill) + pSoldier->stats.ubSkillTraits[a] = 0; + + if (gMercProfiles[pSoldier->ubProfile].bSkillTraits[a] == chassisSkill) + gMercProfiles[pSoldier->ubProfile].bSkillTraits[a] = 0; + } + + if (utilitySkill > 0) + { + if (pSoldier->stats.ubSkillTraits[a] == utilitySkill) + pSoldier->stats.ubSkillTraits[a] = 0; + + if (gMercProfiles[pSoldier->ubProfile].bSkillTraits[a] == utilitySkill) + gMercProfiles[pSoldier->ubProfile].bSkillTraits[a] = 0; + } + } + } } @@ -11064,6 +11166,11 @@ void CalcMagFactorSimple( SOLDIERTYPE *pSoldier, FLOAT d2DDistance, INT16 bAimTi iHighestMagFactor = 1.0; } + if (AM_A_ROBOT(pSoldier) && Item[pSoldier->inv[ROBOT_TARGETING_SLOT].usItem].fProvidesRobotLaserBonus) + { + gCTHDisplay.iBestLaserRange = max(gCTHDisplay.iBestLaserRange, GetBestLaserRange(&pSoldier->inv[ROBOT_TARGETING_SLOT])); + } + gCTHDisplay.FinalMagFactor = iHighestMagFactor; } diff --git a/Utils/Text.h b/Utils/Text.h index 5b1418d0..4fde38c1 100644 --- a/Utils/Text.h +++ b/Utils/Text.h @@ -3137,6 +3137,32 @@ extern STR16 szRebelCommandHelpText[]; extern STR16 szRebelCommandAdminActionsText[]; extern STR16 szRebelCommandDirectivesText[]; +extern STR16 szRobotText[]; +enum { + ROBOT_TEXT_CANNOT_CHANGE_INSTALLED_WEAPON, + ROBOT_TEXT_CANNOT_ADD_ATTACHMENTS, + ROBOT_TEXT_INSTALLED_WEAPON, + ROBOT_TEXT_SLOT_AMMO, + ROBOT_TEXT_SLOT_TARGETING, + ROBOT_TEXT_SLOT_CHASSIS, + ROBOT_TEXT_SLOT_UTILITY, + ROBOT_TEXT_SLOT_INVENTORY, + ROBOT_TEXT_NO_BONUS, + ROBOT_TEXT_LASER, + ROBOT_TEXT_NIGHT_VISION, + ROBOT_TEXT_CLEANING_KIT, + ROBOT_TEXT_CLEANING_KIT_DEPLETED, + ROBOT_TEXT_METAL_DETECTOR, + ROBOT_TEXT_XRAY, + ROBOT_TEXT_XRAY_ACTIVATED, + ROBOT_TEXT_RADIO, + ROBOT_TEXT_STAT_BONUSES, + ROBOT_TEXT_CAMO, + ROBOT_TEXT_PLATE, + ROBOT_TEXT_PLATE_DESTROYED, + ROBOT_TEXT_SKILL_GRANTED, +}; + #define TACTICAL_INVENTORY_DIALOG_NUM 16 #define TACTICAL_COVER_DIALOG_NUM 16 diff --git a/Utils/XML_Items.cpp b/Utils/XML_Items.cpp index ff8c850d..f6238df5 100644 --- a/Utils/XML_Items.cpp +++ b/Utils/XML_Items.cpp @@ -299,7 +299,18 @@ itemStartElementHandle(void *userData, const XML_Char *name, const XML_Char **at strcmp(name, "emptybloodbag" ) == 0 || strcmp(name, "medicalsplint" ) == 0 || strcmp(name, "sFireResistance" ) == 0 || - strcmp(name, "usAdministrationModifier" ) == 0)) + strcmp(name, "usAdministrationModifier" ) == 0) || + strcmp(name, "RobotDamageReduction") == 0 || + strcmp(name, "RobotStrBonus") == 0 || + strcmp(name, "RobotAgiBonus") == 0 || + strcmp(name, "RobotDexBonus") == 0 || + strcmp(name, "RobotTargetingSkillGrant") == 0 || + strcmp(name, "RobotChassisSkillGrant") == 0 || + strcmp(name, "RobotUtilitySkillGrant") == 0 || + strcmp(name, "ProvidesRobotCamo") == 0 || + strcmp(name, "ProvidesRobotNightVision") == 0 || + strcmp(name, "ProvidesRobotLaserBonus") == 0 + ) { pData->curElement = ELEMENT_PROPERTY; //DebugMsg(TOPIC_JA2, DBG_LEVEL_3, String("itemStartElementHandle: going into element, name = %s",name) ); @@ -1553,6 +1564,56 @@ itemEndElementHandle(void *userData, const XML_Char *name) pData->curElement = ELEMENT; pData->curItem.usAdministrationModifier = (UINT8)atol( pData->szCharData ); } + else if (strcmp(name, "RobotDamageReduction") == 0) + { + pData->curElement = ELEMENT; + pData->curItem.fRobotDamageReductionModifier = (FLOAT)atof(pData->szCharData); + } + else if (strcmp(name, "RobotStrBonus") == 0) + { + pData->curElement = ELEMENT; + pData->curItem.bRobotStrBonus = (INT8)atol(pData->szCharData); + } + else if (strcmp(name, "RobotAgiBonus") == 0) + { + pData->curElement = ELEMENT; + pData->curItem.bRobotAgiBonus = (INT8)atol(pData->szCharData); + } + else if (strcmp(name, "RobotDexBonus") == 0) + { + pData->curElement = ELEMENT; + pData->curItem.bRobotDexBonus = (INT8)atol(pData->szCharData); + } + else if (strcmp(name, "RobotTargetingSkillGrant") == 0) + { + pData->curElement = ELEMENT; + pData->curItem.bRobotTargetingSkillGrant = (INT8)atol(pData->szCharData); + } + else if (strcmp(name, "RobotChassisSkillGrant") == 0) + { + pData->curElement = ELEMENT; + pData->curItem.bRobotChassisSkillGrant = (INT8)atol(pData->szCharData); + } + else if (strcmp(name, "RobotUtilitySkillGrant") == 0) + { + pData->curElement = ELEMENT; + pData->curItem.bRobotUtilitySkillGrant = (INT8)atol(pData->szCharData); + } + else if (strcmp(name, "ProvidesRobotCamo") == 0) + { + pData->curElement = ELEMENT; + pData->curItem.fProvidesRobotCamo = (BOOLEAN)atol(pData->szCharData); + } + else if (strcmp(name, "ProvidesRobotNightVision") == 0) + { + pData->curElement == ELEMENT; + pData->curItem.fProvidesRobotNightVision = (BOOLEAN)atol(pData->szCharData); + } + else if (strcmp(name, "ProvidesRobotLaserBonus") == 0) + { + pData->curElement == ELEMENT; + pData->curItem.fProvidesRobotLaserBonus = (BOOLEAN)atol(pData->szCharData); + } --pData->maxReadDepth; @@ -2197,6 +2258,16 @@ BOOLEAN WriteItemStats() FilePrintf(hFile,"\t\t%d\r\n", Item[cnt].usRiotShieldGraphic ); FilePrintf(hFile,"\t\t%d\r\n", Item[cnt].sFireResistance ); FilePrintf(hFile,"\t\t%d\r\n", Item[cnt].usAdministrationModifier ); + FilePrintf(hFile,"\t\t%f\r\n", Item[cnt].fRobotDamageReductionModifier ); + FilePrintf(hFile,"\t\t%d\r\n", Item[cnt].bRobotStrBonus ); + FilePrintf(hFile,"\t\t%d\r\n", Item[cnt].bRobotAgiBonus ); + FilePrintf(hFile,"\t\t%d\r\n", Item[cnt].bRobotDexBonus ); + FilePrintf(hFile,"\t\t%d\r\n", Item[cnt].bRobotTargetingSkillGrant ); + FilePrintf(hFile,"\t\t%d\r\n", Item[cnt].bRobotChassisSkillGrant ); + FilePrintf(hFile,"\t\t%d\r\n", Item[cnt].bRobotUtilitySkillGrant ); + FilePrintf(hFile,"\t\t%d\r\n", Item[cnt].fProvidesRobotCamo ); + FilePrintf(hFile,"\t\t%d\r\n", Item[cnt].fProvidesRobotNightVision ); + FilePrintf(hFile,"\t\t%d\r\n", Item[cnt].fProvidesRobotLaserBonus ); FilePrintf(hFile,"\t\r\n"); } diff --git a/Utils/_ChineseText.cpp b/Utils/_ChineseText.cpp index 70f1e3f0..38bbebb7 100644 --- a/Utils/_ChineseText.cpp +++ b/Utils/_ChineseText.cpp @@ -12002,6 +12002,32 @@ STR16 szRebelCommandDirectivesText[] = L"升级此项将会增加每天志愿者人数。", //L"Improving this directive will increase the number of volunteers gained per day.", }; +STR16 szRobotText[] = // TODO: Translate +{ + L"The robot's installed weapon cannot be changed.", + L"It is not possible to add attachments to the robot's weapon.", + L"Installed Weapon", + L"Reserve Ammo", + L"Targeting Upgrade", + L"Chassis Upgrade", + L"Utility Upgrade", + L"Storage", + L"No Bonus", + L"The laser bonuses of this item are applied to the robot.", + L"The night- and cave-vision bonuses of this item are applied to the robot.", + L"This kit degrades instead of the robot's weapon.", + L"The robot's cleaning kit was depleted!", + L"Mines adjacent to the robot are automatically flagged.", + L"Periodic X-Ray scans during combat. No batteries required.", + L"The robot has activated an x-ray scan!", + L"The robot can use the radio set.", + L"The robot's chassis is strengthened, giving it better combat performance.", + L"The camouflage bonuses of this item are applied to the robot.", + L"The robot is tougher and takes less damage.", + L"The robot's extra armour plating was destroyed!", + L"The robot gains the benefit of the %s skill trait.", +}; + // WANNE: Some Chinese specific strings that needs to be in unicode! STR16 ChineseSpecString1 = L"%%"; //defined in _ChineseText.cpp as this file is already unicode STR16 ChineseSpecString2 = L"*%3d%%%%"; //defined in _ChineseText.cpp as this file is already unicode diff --git a/Utils/_DutchText.cpp b/Utils/_DutchText.cpp index 4a53394f..ebe387a2 100644 --- a/Utils/_DutchText.cpp +++ b/Utils/_DutchText.cpp @@ -11998,4 +11998,30 @@ STR16 szRebelCommandDirectivesText[] = // TODO.Translate L"Improving this directive will increase the number of volunteers gained per day.", }; +STR16 szRobotText[] = // TODO: Translate +{ + L"The robot's installed weapon cannot be changed.", + L"It is not possible to add attachments to the robot's weapon.", + L"Installed Weapon", + L"Reserve Ammo", + L"Targeting Upgrade", + L"Chassis Upgrade", + L"Utility Upgrade", + L"Storage", + L"No Bonus", + L"The laser bonuses of this item are applied to the robot.", + L"The night- and cave-vision bonuses of this item are applied to the robot.", + L"This kit degrades instead of the robot's weapon.", + L"The robot's cleaning kit was depleted!", + L"Mines adjacent to the robot are automatically flagged.", + L"Periodic X-Ray scans during combat. No batteries required.", + L"The robot has activated an x-ray scan!", + L"The robot can use the radio set.", + L"The robot's chassis is strengthened, giving it better combat performance.", + L"The camouflage bonuses of this item are applied to the robot.", + L"The robot is tougher and takes less damage.", + L"The robot's extra armour plating was destroyed!", + L"The robot gains the benefit of the %s skill trait.", +}; + #endif //DUTCH diff --git a/Utils/_EnglishText.cpp b/Utils/_EnglishText.cpp index d9ccca36..dede95f0 100644 --- a/Utils/_EnglishText.cpp +++ b/Utils/_EnglishText.cpp @@ -12002,4 +12002,30 @@ STR16 szRebelCommandDirectivesText[] = L"Improving this directive will increase the number of volunteers gained per day.", }; +STR16 szRobotText[] = +{ + L"The robot's installed weapon cannot be changed.", + L"It is not possible to add attachments to the robot's weapon.", + L"Installed Weapon", + L"Reserve Ammo", + L"Targeting Upgrade", + L"Chassis Upgrade", + L"Utility Upgrade", + L"Storage", + L"No Bonus", + L"The laser bonuses of this item are applied to the robot.", + L"The night- and cave-vision bonuses of this item are applied to the robot.", + L"This kit degrades instead of the robot's weapon.", + L"The robot's cleaning kit was depleted!", + L"Mines adjacent to the robot are automatically flagged.", + L"Periodic X-Ray scans during combat. No batteries required.", + L"The robot has activated an x-ray scan!", + L"The robot can use the radio set.", + L"The robot's chassis is strengthened, giving it better combat performance.", + L"The camouflage bonuses of this item are applied to the robot.", + L"The robot is tougher and takes less damage.", + L"The robot's extra armour plating was destroyed!", + L"The robot gains the benefit of the %s skill trait.", +}; + #endif //ENGLISH diff --git a/Utils/_FrenchText.cpp b/Utils/_FrenchText.cpp index d074af95..33ffe5bb 100644 --- a/Utils/_FrenchText.cpp +++ b/Utils/_FrenchText.cpp @@ -11980,4 +11980,30 @@ STR16 szRebelCommandDirectivesText[] = // TODO.Translate L"Improving this directive will increase the number of volunteers gained per day.", }; +STR16 szRobotText[] = // TODO: Translate +{ + L"The robot's installed weapon cannot be changed.", + L"It is not possible to add attachments to the robot's weapon.", + L"Installed Weapon", + L"Reserve Ammo", + L"Targeting Upgrade", + L"Chassis Upgrade", + L"Utility Upgrade", + L"Storage", + L"No Bonus", + L"The laser bonuses of this item are applied to the robot.", + L"The night- and cave-vision bonuses of this item are applied to the robot.", + L"This kit degrades instead of the robot's weapon.", + L"The robot's cleaning kit was depleted!", + L"Mines adjacent to the robot are automatically flagged.", + L"Periodic X-Ray scans during combat. No batteries required.", + L"The robot has activated an x-ray scan!", + L"The robot can use the radio set.", + L"The robot's chassis is strengthened, giving it better combat performance.", + L"The camouflage bonuses of this item are applied to the robot.", + L"The robot is tougher and takes less damage.", + L"The robot's extra armour plating was destroyed!", + L"The robot gains the benefit of the %s skill trait.", +}; + #endif //FRENCH diff --git a/Utils/_GermanText.cpp b/Utils/_GermanText.cpp index eff28f50..b712334b 100644 --- a/Utils/_GermanText.cpp +++ b/Utils/_GermanText.cpp @@ -11903,4 +11903,30 @@ STR16 szRebelCommandDirectivesText[] = // TODO.Translate L"Improving this directive will increase the number of volunteers gained per day.", }; +STR16 szRobotText[] = // TODO: Translate +{ + L"The robot's installed weapon cannot be changed.", + L"It is not possible to add attachments to the robot's weapon.", + L"Installed Weapon", + L"Reserve Ammo", + L"Targeting Upgrade", + L"Chassis Upgrade", + L"Utility Upgrade", + L"Storage", + L"No Bonus", + L"The laser bonuses of this item are applied to the robot.", + L"The night- and cave-vision bonuses of this item are applied to the robot.", + L"This kit degrades instead of the robot's weapon.", + L"The robot's cleaning kit was depleted!", + L"Mines adjacent to the robot are automatically flagged.", + L"Periodic X-Ray scans during combat. No batteries required.", + L"The robot has activated an x-ray scan!", + L"The robot can use the radio set.", + L"The robot's chassis is strengthened, giving it better combat performance.", + L"The camouflage bonuses of this item are applied to the robot.", + L"The robot is tougher and takes less damage.", + L"The robot's extra armour plating was destroyed!", + L"The robot gains the benefit of the %s skill trait.", +}; + #endif //GERMAN diff --git a/Utils/_ItalianText.cpp b/Utils/_ItalianText.cpp index 45173aca..ef24d1ff 100644 --- a/Utils/_ItalianText.cpp +++ b/Utils/_ItalianText.cpp @@ -11989,4 +11989,30 @@ STR16 szRebelCommandDirectivesText[] = // TODO.Translate L"Improving this directive will increase the number of volunteers gained per day.", }; +STR16 szRobotText[] = // TODO: Translate +{ + L"The robot's installed weapon cannot be changed.", + L"It is not possible to add attachments to the robot's weapon.", + L"Installed Weapon", + L"Reserve Ammo", + L"Targeting Upgrade", + L"Chassis Upgrade", + L"Utility Upgrade", + L"Storage", + L"No Bonus", + L"The laser bonuses of this item are applied to the robot.", + L"The night- and cave-vision bonuses of this item are applied to the robot.", + L"This kit degrades instead of the robot's weapon.", + L"The robot's cleaning kit was depleted!", + L"Mines adjacent to the robot are automatically flagged.", + L"Periodic X-Ray scans during combat. No batteries required.", + L"The robot has activated an x-ray scan!", + L"The robot can use the radio set.", + L"The robot's chassis is strengthened, giving it better combat performance.", + L"The camouflage bonuses of this item are applied to the robot.", + L"The robot is tougher and takes less damage.", + L"The robot's extra armour plating was destroyed!", + L"The robot gains the benefit of the %s skill trait.", +}; + #endif //ITALIAN diff --git a/Utils/_PolishText.cpp b/Utils/_PolishText.cpp index 3178af98..f34b4490 100644 --- a/Utils/_PolishText.cpp +++ b/Utils/_PolishText.cpp @@ -12002,4 +12002,30 @@ STR16 szRebelCommandDirectivesText[] = // TODO.Translate L"Improving this directive will increase the number of volunteers gained per day.", }; +STR16 szRobotText[] = // TODO: Translate +{ + L"The robot's installed weapon cannot be changed.", + L"It is not possible to add attachments to the robot's weapon.", + L"Installed Weapon", + L"Reserve Ammo", + L"Targeting Upgrade", + L"Chassis Upgrade", + L"Utility Upgrade", + L"Storage", + L"No Bonus", + L"The laser bonuses of this item are applied to the robot.", + L"The night- and cave-vision bonuses of this item are applied to the robot.", + L"This kit degrades instead of the robot's weapon.", + L"The robot's cleaning kit was depleted!", + L"Mines adjacent to the robot are automatically flagged.", + L"Periodic X-Ray scans during combat. No batteries required.", + L"The robot has activated an x-ray scan!", + L"The robot can use the radio set.", + L"The robot's chassis is strengthened, giving it better combat performance.", + L"The camouflage bonuses of this item are applied to the robot.", + L"The robot is tougher and takes less damage.", + L"The robot's extra armour plating was destroyed!", + L"The robot gains the benefit of the %s skill trait.", +}; + #endif //POLISH diff --git a/Utils/_RussianText.cpp b/Utils/_RussianText.cpp index 42d29e97..ff75bcb2 100644 --- a/Utils/_RussianText.cpp +++ b/Utils/_RussianText.cpp @@ -11996,4 +11996,30 @@ STR16 szRebelCommandDirectivesText[] = // TODO.Translate L"Improving this directive will increase the number of volunteers gained per day.", }; +STR16 szRobotText[] = // TODO: Translate +{ + L"The robot's installed weapon cannot be changed.", + L"It is not possible to add attachments to the robot's weapon.", + L"Installed Weapon", + L"Reserve Ammo", + L"Targeting Upgrade", + L"Chassis Upgrade", + L"Utility Upgrade", + L"Storage", + L"No Bonus", + L"The laser bonuses of this item are applied to the robot.", + L"The night- and cave-vision bonuses of this item are applied to the robot.", + L"This kit degrades instead of the robot's weapon.", + L"The robot's cleaning kit was depleted!", + L"Mines adjacent to the robot are automatically flagged.", + L"Periodic X-Ray scans during combat. No batteries required.", + L"The robot has activated an x-ray scan!", + L"The robot can use the radio set.", + L"The robot's chassis is strengthened, giving it better combat performance.", + L"The camouflage bonuses of this item are applied to the robot.", + L"The robot is tougher and takes less damage.", + L"The robot's extra armour plating was destroyed!", + L"The robot gains the benefit of the %s skill trait.", +}; + #endif //RUSSIAN