From ea1892c7887a70b145736a597940edadb8cb8f6f Mon Sep 17 00:00:00 2001 From: Flugente Date: Sun, 17 May 2020 20:52:27 +0000 Subject: [PATCH] New feature: factories allows facilities to create items For more info, see http://thepit.ja-galaxy-forum.com/index.php?t=msg&goto=360075&#msg_360075 Requires GameDir >= r2534 git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@8804 3b4a5df2-a311-0410-b5c6-a8a6f20db521 --- GameSettings.cpp | 3 + GameSettings.h | 3 + GameVersion.cpp | 4 +- Laptop/FacilityProduction.cpp | 576 +++++++++++++++++++++++++ Laptop/FacilityProduction.h | 16 + Laptop/Laptop_VS2005.vcproj | 8 + Laptop/Laptop_VS2008.vcproj | 8 + Laptop/Laptop_VS2010.vcxproj | 2 + Laptop/Laptop_VS2010.vcxproj.filters | 6 + Laptop/Laptop_VS2013.vcxproj | 2 + Laptop/Laptop_VS2013.vcxproj.filters | 6 + Laptop/Laptop_VS2017.vcxproj | 2 + Laptop/Laptop_VS2019.vcxproj | 2 + Laptop/laptop.cpp | 44 ++ Laptop/laptop.h | 4 + Strategic/Campaign Types.h | 30 ++ Strategic/Hourly Update.cpp | 334 ++++++++++++++ Strategic/LuaInitNPCs.cpp | 35 ++ Strategic/LuaInitNPCs.h | 2 + Strategic/Map Screen Interface Map.cpp | 55 ++- Strategic/Player Command.cpp | 29 +- Strategic/XML_FacilityTypes.cpp | 157 ++++++- Utils/Text.h | 2 + Utils/_ChineseText.cpp | 16 + Utils/_DutchText.cpp | 16 + Utils/_EnglishText.cpp | 16 + Utils/_FrenchText.cpp | 16 + Utils/_GermanText.cpp | 16 + Utils/_ItalianText.cpp | 16 + Utils/_PolishText.cpp | 16 + Utils/_RussianText.cpp | 16 + 31 files changed, 1446 insertions(+), 12 deletions(-) create mode 100644 Laptop/FacilityProduction.cpp create mode 100644 Laptop/FacilityProduction.h diff --git a/GameSettings.cpp b/GameSettings.cpp index d7c21d1a..f8eeaa99 100644 --- a/GameSettings.cpp +++ b/GameSettings.cpp @@ -1864,6 +1864,9 @@ void LoadGameExternalOptions() // HEADROCK HAM 3.6: Controls how important the character's stats are, in insuring he/she gets better results (or smaller damage) from using facilities. The higher this is, the more dangerous all facilities are. gGameExternalOptions.ubFacilityDangerRate = iniReader.ReadInteger("Strategic Gameplay Settings","FACILITY_DANGER_RATE", 50, 0, 100); + // Flugente: factories + gGameExternalOptions.fFactories = iniReader.ReadBoolean("Strategic Gameplay Settings", "FACTORIES", FALSE ); + // 2Points: Use new repair algorithm (Items are priorized based on type and damage to item, starting from equipped weapons, going to armor, then inventory) gGameExternalOptions.fAdditionalRepairMode = iniReader.ReadBoolean("Strategic Gameplay Settings", "ADDITIONAL_REPAIR_MODE", FALSE); diff --git a/GameSettings.h b/GameSettings.h index 289b8b6e..bbbae45a 100644 --- a/GameSettings.h +++ b/GameSettings.h @@ -1507,6 +1507,9 @@ typedef struct // Flugente: externalised squad names BOOLEAN fUseXMLSquadNames; + // Flugente: factories + BOOLEAN fFactories; + //dnl ch68 090913 Reinforcements Setttings UINT16 sMinDelayEnemyReinforcements; UINT16 sRndDelayEnemyReinforcements; diff --git a/GameVersion.cpp b/GameVersion.cpp index abb7b60a..22b3f7bd 100644 --- a/GameVersion.cpp +++ b/GameVersion.cpp @@ -55,8 +55,8 @@ #endif -CHAR8 czVersionNumber[16] = { "Build 20.04.27" }; //YY.MM.DD +CHAR8 czVersionNumber[16] = { "Build 20.05.17" }; //YY.MM.DD CHAR16 zTrackingNumber[16] = { L"Z" }; -CHAR16 zRevisionNumber[16] = { L"Revision 8794" }; +CHAR16 zRevisionNumber[16] = { L"Revision 8804" }; // SAVE_GAME_VERSION is defined in header, change it there diff --git a/Laptop/FacilityProduction.cpp b/Laptop/FacilityProduction.cpp new file mode 100644 index 00000000..3b69b6e2 --- /dev/null +++ b/Laptop/FacilityProduction.cpp @@ -0,0 +1,576 @@ +/** +* @file +* @author Flugente (bears-pit.com) +*/ + +#ifdef PRECOMPILEDHEADERS +#include "Laptop All.h" +#else +#include "laptop.h" +#include "insurance.h" +#include "WCheck.h" +#include "Utilities.h" +#include "WordWrap.h" +#include "Line.h" +#include "Text.h" +#include "FacilityProduction.h" +#include "Map Screen Interface.h" +#include "Quests.h" +#include "finances.h" +#include "Strategic Town Loyalty.h" +#include "strategic.h" +#include "BaseTable.h" +#endif + +/*#define MERCOMP_FONT_COLOR 2 +#define CAMPHIS_FONT_BIG FONT14ARIAL +#define CAMPHIS_FONT_MED FONT12ARIAL +#define CAMPHIS_FONT_SMALL FONT10ARIAL*/ + +#define MERCOMP_FONT_SHADOW FONT_MCOLOR_WHITE + +/*#define CAMPAIGN_HISTORY_LINK_START_X LAPTOP_SCREEN_UL_X +#define CAMPAIGN_HISTORY_LINK_START_Y LAPTOP_SCREEN_WEB_UL_Y + 5 +#define CAMPAIGN_HISTORY_LINK_TEXT_WIDTH 107 +#define CAMPAIGN_HISTORY_LINK_STEP_Y 14 + +#define BACKGROUND_WIDTH 125 +#define CAMPAIGN_HISTORY_BACKGROUND_HEIGHT 100 + +#define CAMPAIGN_HISTORY_BIG_TITLE_X 115 + LAPTOP_SCREEN_UL_X +#define CAMPAIGN_HISTORY_BIG_TITLE_Y 10 + LAPTOP_SCREEN_WEB_UL_Y*/ + +#define NUM_LINKS 0 +#define MCA_START_CONTENT_Y (LAPTOP_SCREEN_WEB_UL_Y + NUM_LINKS * 17) + +//extern UINT32 guiInsuranceBackGround; +//extern UINT32 guiInsuranceBigRedLineImage; +//extern UINT32 guiMercCompareBulletImage; +//extern UINT32 guiMercCompareLogoImage; + +//link to the various pages +//MOUSE_REGION gLinkRegion_Production[NUM_LINKS]; + +UINT32 gCHECKBOXLib = 0; + +/*void SelectLinkRegionCallBack_Production( MOUSE_REGION * pRegion, INT32 iReason ) +{ + if ( iReason & MSYS_CALLBACK_REASON_INIT ) + { + } + else if ( iReason & MSYS_CALLBACK_REASON_LBUTTON_UP ) + { + UINT32 uiLink = MSYS_GetRegionUserData( pRegion, 0 ); + + if ( uiLink == 0 ) + guiCurrentLaptopMode = LAPTOP_MODE_PMC_MAIN; + else if ( uiLink == 1 ) + guiCurrentLaptopMode = LAPTOP_MODE_PMC_CONTRACT_MILITIA; + else if ( uiLink == 2 ) + guiCurrentLaptopMode = LAPTOP_MODE_BROKEN_LINK; + } + else if ( iReason & MSYS_CALLBACK_REASON_RBUTTON_UP ) + { + } +}*/ + +void InitDefaults_Production() +{ + VOBJECT_DESC VObjectDesc; + + /*// load the Insurance bullet graphic and add it + VObjectDesc.fCreateFlags = VOBJECT_CREATE_FROMFILE; + FilenameForBPP( "LAPTOP\\bullet.sti", VObjectDesc.ImageFile ); + CHECKV( AddVideoObject( &VObjectDesc, &guiMercCompareBulletImage ) );*/ + + /*// load the Flower Account Box graphic and add it + VObjectDesc.fCreateFlags = VOBJECT_CREATE_FROMFILE; + FilenameForBPP( "LAPTOP\\BackGroundTile.sti", VObjectDesc.ImageFile ); + CHECKV( AddVideoObject( &VObjectDesc, &guiInsuranceBackGround ) );*/ + + /*// load the red bar on the side of the page and add it + VObjectDesc.fCreateFlags = VOBJECT_CREATE_FROMFILE; + FilenameForBPP( "LAPTOP\\LargeBar.sti", VObjectDesc.ImageFile ); + CHECKV( AddVideoObject( &VObjectDesc, &guiInsuranceBigRedLineImage ) );*/ + + /*VObjectDesc.fCreateFlags = VOBJECT_CREATE_FROMFILE; + FilenameForBPP( "LAPTOP\\PressLogos.sti", VObjectDesc.ImageFile ); + CHECKV( AddVideoObject( &VObjectDesc, &guiMercCompareLogoImage ) );*/ + + VObjectDesc.fCreateFlags = VOBJECT_CREATE_FROMFILE; + FilenameForBPP( "Interface\\OptionsCheckBoxes.sti", VObjectDesc.ImageFile ); + CHECKV( AddVideoObject( &VObjectDesc, &gCHECKBOXLib ) ); + + /*UINT16 usPosX = CAMPAIGN_HISTORY_LINK_START_X; + UINT16 usPosY = CAMPAIGN_HISTORY_LINK_START_Y; + for ( int i = 0; i gProductionVector; + +extern INT32 GetFactoryLeftoverProgress( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ, UINT16 usFacilityType, UINT16 usProductionNumber ); +extern void SetFacilityProductionState( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ, UINT16 usFacilityType, UINT16 usProductionNumber, BOOLEAN aOn ); + +void FilterProductionData() +{ + gProductionVector.clear(); + + for ( UINT16 sector = 0; sector < 256; ++sector ) + { + if ( !StrategicMap[SECTOR_INFO_TO_STRATEGIC_INDEX( sector )].fEnemyControlled ) + { + UINT8 ubTownID = GetTownIdForSector( SECTORX( sector ), SECTORY( sector ) ); + + for ( UINT16 cnt = 0; cnt < NUM_FACILITY_TYPES; ++cnt ) + { + // Is this facility here? + if ( gFacilityLocations[sector][cnt].fFacilityHere ) + { + UINT16 productioncnt = 0; + for ( std::vector::iterator prodit = gFacilityTypes[cnt].ProductionData.begin(), proditend = gFacilityTypes[cnt].ProductionData.end(); prodit != proditend; + ++prodit, ++productioncnt ) + { + PRODUCTIONLINE_DATA data; + data.sector = sector; + data.facilitytype = cnt; + data.productionline = productioncnt; + data.xmldata = ( *prodit ); + + INT32 progress = GetFactoryLeftoverProgress( SECTORX( sector ), SECTORY( sector ), 0, cnt, productioncnt ); + + // despite what is set, several other things can turn a factory off, like loyalty or lua-defined quest checks + if ( progress < -10 + || (ubTownID != BLANK_SECTOR + && gTownLoyalty[ubTownID].ubRating < prodit->usOptional_LoyaltyRequired ) ) + { + data.active = false; + data.can_turnon = false; + } + else + { + data.active = ( progress > -1 ); + data.can_turnon = true; + } + + data.old_state = data.active; + + gProductionVector.push_back( data ); + } + } + } + } + } +} + +void WriteAlteredProductionData() +{ + for ( std::vector::iterator it = gProductionVector.begin(), itend = gProductionVector.end(); it != itend; ++it ) + { + if ( (*it).active != ( *it ).old_state ) + { + SetFacilityProductionState( SECTORX( ( *it ).sector ), SECTORY( ( *it ).sector ), 0, ( *it ).facilitytype, ( *it ).productionline, ( *it ).active ); + } + } +} + +BOOLEAN gfFacilityProductionRedraw = FALSE; + +BOOLEAN EnterFacilityProduction() +{ + InitDefaults_Production(); + + FilterProductionData(); + + gTestPanel3.Create( LAPTOP_SCREEN_UL_X, MCA_START_CONTENT_Y, LAPTOP_SCREEN_LR_X, LAPTOP_SCREEN_WEB_LR_Y ); + gTestPanel3.SetColorLine( Get16BPPColor( FROMRGB( 128, 128, 128 ) ) ); + gTestPanel3.SetColorLineShadow( Get16BPPColor( FROMRGB( 255, 255, 255 ) ) ); + gTestPanel3.SetColorMarked( Get16BPPColor( FROMRGB( 230, 230, 230 ) ) ); + + TestTableTemplate<4>::getInstance().Create( LAPTOP_SCREEN_UL_X + 4, MCA_START_CONTENT_Y + 4, LAPTOP_SCREEN_LR_X - 4, LAPTOP_SCREEN_WEB_LR_Y - 4 ); + TestTableTemplate<4>::getInstance().SetColorSeparator( Get16BPPColor( FROMRGB( 30, 30, 30 ) ) ); + + gTestPanel3.RegisterMemberThingy( &TestTableTemplate<4>::getInstance() ); + + TestTableTemplate<4>::getInstance().SetMouseRegionActive( TRUE ); + + RenderFacilityProduction(); + + return( TRUE ); +} + +void ExitFacilityProduction() +{ + gTestPanel3.Destroy(); + + WriteAlteredProductionData(); + + RemoveDefaults_Production(); +} + +void HandleFacilityProduction() +{ + if ( gfFacilityProductionRedraw ) + { + TestTableTemplate<4>::getInstance().Create( TestTableTemplate<4>::getInstance().GetX(), TestTableTemplate<4>::getInstance().GetY(), + TestTableTemplate<4>::getInstance().GetX() + TestTableTemplate<4>::getInstance().GetWidth(), + TestTableTemplate<4>::getInstance().GetY() + TestTableTemplate<4>::getInstance().GetHeight() ); + + RenderFacilityProduction(); + + gfFacilityProductionRedraw = FALSE; + } +} + +void RenderFacilityProduction() +{ + DisplayDefaults_Production(); + + SetFontShadow( MERCOMP_FONT_SHADOW ); + + gTestPanel3.Display(); + + SetFontShadow( DEFAULT_SHADOW ); + + MarkButtonsDirty(); + RenderWWWProgramTitleBar(); + InvalidateRegion( LAPTOP_SCREEN_UL_X, LAPTOP_SCREEN_WEB_UL_Y, LAPTOP_SCREEN_LR_X, LAPTOP_SCREEN_WEB_LR_Y ); +} + +static CHAR16 gProductionHelpText[100]; + +STR16 Sectornamegetter_Production( UINT32 aNum ) +{ + swprintf( gProductionHelpText, L"NAME NOT FOUND" ); + + if ( aNum < gProductionVector.size() ) + { + GetShortSectorString( SECTORX( gProductionVector[aNum].sector ), SECTORY( gProductionVector[aNum].sector ), gProductionHelpText ); + } + + return gProductionHelpText; +} + +STR16 Product_Production( UINT32 aNum ) +{ + swprintf( gProductionHelpText, L"NOTHING" ); + + if ( aNum < gProductionVector.size() ) + { + if ( wcslen( gProductionVector[aNum].xmldata.szProductionName ) > 0 ) + swprintf( gProductionHelpText, L"%s", gProductionVector[aNum].xmldata.szProductionName ); + else if ( gProductionVector[aNum].xmldata.usItemToCreate != NOTHING ) + swprintf( gProductionHelpText, L"%s", Item[gProductionVector[aNum].xmldata.usItemToCreate].szItemName ); + } + + return gProductionHelpText; +} + +STR16 PreProduct_Production( UINT32 aNum ) +{ + swprintf( gProductionHelpText, L"--" ); + + if ( aNum < gProductionVector.size() ) + { + bool first = true; + for ( std::vector::iterator it = gProductionVector[aNum].xmldata.usOptional_PreProducts.begin(), itend = gProductionVector[aNum].xmldata.usOptional_PreProducts.end(); it != itend; ++it ) + { + if ( it->requiredforonecreation > 1 ) + { + if ( first ) + { + swprintf( gProductionHelpText, L"%s (%d)", Item[it->item].szItemName, it->requiredforonecreation ); + first = false; + } + else + { + swprintf( gProductionHelpText, L"%s, %s (%d)", gProductionHelpText, Item[it->item].szItemName, it->requiredforonecreation ); + } + } + else + { + if ( first ) + { + swprintf( gProductionHelpText, L"%s", Item[it->item].szItemName ); + first = false; + } + else + { + swprintf( gProductionHelpText, L"%s, %s", gProductionHelpText, Item[it->item].szItemName ); + } + } + } + } + + return gProductionHelpText; +} + +UINT8 ColourGetter_Production( UINT32 aNum ) +{ + if ( aNum < gProductionVector.size() ) + { + UINT8 ubTownID = GetTownIdForSector( SECTORX( gProductionVector[aNum].sector ), SECTORY( gProductionVector[aNum].sector ) ); + + if ( ubTownID != BLANK_SECTOR + && gTownLoyalty[ubTownID].ubRating < gProductionVector[aNum].xmldata.usOptional_LoyaltyRequired ) + { + return 164; + } + } + + return 2; +} + +STR16 Loyalty_Production( UINT32 aNum ) +{ + swprintf( gProductionHelpText, L"--" ); + + if ( aNum < gProductionVector.size() && gProductionVector[aNum].xmldata.usOptional_LoyaltyRequired > 0 ) + { + swprintf( gProductionHelpText, L"%d+", gProductionVector[aNum].xmldata.usOptional_LoyaltyRequired ); + } + + return gProductionHelpText; +} + +STR16 Costgetter_Production( UINT32 aNum ) +{ + swprintf( gProductionHelpText, L"--" ); + + if ( aNum < gProductionVector.size() && gProductionVector[aNum].xmldata.sHourlyCost ) + { + swprintf( gProductionHelpText, L"%d$", gProductionVector[aNum].xmldata.sHourlyCost ); + } + + return gProductionHelpText; +} + +STR16 Minutesgetter_Production( UINT32 aNum ) +{ + swprintf( gProductionHelpText, L"--:--" ); + + if ( aNum < gProductionVector.size() ) + { + swprintf( gProductionHelpText, L"%02d:%02d", gProductionVector[aNum].xmldata.sMinutesRequired / 60, gProductionVector[aNum].xmldata.sMinutesRequired % 60 ); + } + + return gProductionHelpText; +} + +BOOLEAN Activegetter_Production( UINT32 aNum ) +{ + if ( aNum < gProductionVector.size() ) + { + return gProductionVector[aNum].active; + } + + return FALSE; +} + +void CheckboxImagegetter_Production( UINT32 aNum, UINT32& arImageLib, UINT16& arImage ) +{ + arImageLib = gCHECKBOXLib; + arImage = 0; + + if ( aNum < gProductionVector.size() ) + { + if ( !gProductionVector[aNum].can_turnon ) + arImage = 4; + else if ( gProductionVector[aNum].active ) + arImage = 2; + } +} + +void Factory_ProgressBar( UINT32 aId, UINT16& arCol1, UINT16& arVal1, UINT16& arCol2, UINT16& arVal2, UINT16& arCol3, UINT16& arVal3, UINT16& arCol4, UINT16& arVal4 ) +{ + if ( aId < gProductionVector.size() ) +{ + INT32 productiontime = GetFactoryLeftoverProgress( SECTORX( gProductionVector[aId].sector ), SECTORY( gProductionVector[aId].sector ), 0, gProductionVector[aId].facilitytype, gProductionVector[aId].productionline ); + + // use stat bar colours, because why not + arCol1 = Get16BPPColor( FROMRGB( gGameExternalOptions.ubStatProgressBarsRed, gGameExternalOptions.ubStatProgressBarsGreen, gGameExternalOptions.ubStatProgressBarsBlue ) ); + + if ( productiontime > -1 && gProductionVector[aId].xmldata.sMinutesRequired > 0 ) + arVal1 = min( 100, 100 * productiontime / gProductionVector[aId].xmldata.sMinutesRequired ); + else + arVal1 = 0; + } +} + +void callbacktoggle( INT32 usId ) +{ + if ( usId < gProductionVector.size() && gProductionVector[usId].can_turnon ) + { + gProductionVector[usId].active = !gProductionVector[usId].active; + + TestTableTemplate<4>::getInstance().SetRefresh(); + } +} + +template<> void TestTableTemplate<4>::SetRefresh() { gfFacilityProductionRedraw = TRUE; } + +template<> void TestTableTemplate<4>::Init( UINT16 sX, UINT16 sY, UINT16 sX_End, UINT16 sY_End ) +{ + ClearColumnDataProvider(); + + // on/off toggle + { + ColumnDataProvider col( L"" ); + col.SetRequiredHeigth( 12 ); + col.SetRequiredLength( 24 ); + col.SetMethodImage( CheckboxImagegetter_Production ); + col.SetNumberOfEntries( gProductionVector.size() ); + col.SetCallBackType( ColumnDataProvider::CDP_TOGGLE ); + + AddColumnDataProvider( col ); + } + + // sector + { + ColumnDataProvider col( pUpdateMapInfoText[15] ); + col.SetMethodString( Sectornamegetter_Production ); + col.SetNumberOfEntries( gProductionVector.size() ); + col.SetCallBackType( ColumnDataProvider::CDP_MILITIA_LIST ); + + AddColumnDataProvider( col ); + } + + // name + { + ColumnDataProvider col( szFactoryText[4] ); + col.SetMethodString( Product_Production ); + col.SetNumberOfEntries( gProductionVector.size() ); + col.SetCallBackType( ColumnDataProvider::CDP_MILITIA_LIST ); + + AddColumnDataProvider( col ); + } + + // required items to use up + { + ColumnDataProvider col( szFactoryText[5] ); + col.SetMethodString( PreProduct_Production ); + col.SetNumberOfEntries( gProductionVector.size() ); + col.SetCallBackType( ColumnDataProvider::CDP_MILITIA_LIST ); + + AddColumnDataProvider( col ); + } + + // loyalty + { + ColumnDataProvider col( pwTownInfoStrings[5] ); + col.SetMethodString( Loyalty_Production ); + col.SetMethodTextColour( ColourGetter_Production ); + col.SetNumberOfEntries( gProductionVector.size() ); + col.SetCallBackType( ColumnDataProvider::CDP_MILITIA_LIST ); + + AddColumnDataProvider( col ); + } + + // cost + { + ColumnDataProvider col( L"$/h" ); + col.SetMethodString( Costgetter_Production ); + col.SetNumberOfEntries( gProductionVector.size() ); + col.SetCallBackType( ColumnDataProvider::CDP_MILITIA_LIST ); + + AddColumnDataProvider( col ); + } + + // current progress + { + ColumnDataProvider col( L"" ); + col.SetMethodStatusBar( Factory_ProgressBar ); + col.SetNumberOfEntries( gProductionVector.size() ); + col.SetCallBackType( ColumnDataProvider::CDP_MILITIA_LIST ); + + AddColumnDataProvider( col ); + } + + // time required + { + ColumnDataProvider col( szFactoryText[6] ); + col.SetMethodString( Minutesgetter_Production ); + col.SetNumberOfEntries( gProductionVector.size() ); + col.SetCallBackType( ColumnDataProvider::CDP_MILITIA_LIST ); + + AddColumnDataProvider( col ); + } + + TestTable::Init( sX, sY, sX_End, sY_End ); +} +////////////////////////// MAIN PAGE //////////////////////////////// diff --git a/Laptop/FacilityProduction.h b/Laptop/FacilityProduction.h new file mode 100644 index 00000000..70b5d4fe --- /dev/null +++ b/Laptop/FacilityProduction.h @@ -0,0 +1,16 @@ +#pragma once +#ifndef __FACILITY_PRODUCTION_WEBSITE_H +#define __FACILITY_PRODUCTION_WEBSITE_H + +/** +* @file +* @author Flugente (bears-pit.com) +*/ + +// main page (explains what this is all about) +BOOLEAN EnterFacilityProduction(); +void ExitFacilityProduction(); +void HandleFacilityProduction(); +void RenderFacilityProduction(); + +#endif //__FACILITY_PRODUCTION_WEBSITE_H diff --git a/Laptop/Laptop_VS2005.vcproj b/Laptop/Laptop_VS2005.vcproj index 5807b379..07b50e4b 100644 --- a/Laptop/Laptop_VS2005.vcproj +++ b/Laptop/Laptop_VS2005.vcproj @@ -462,6 +462,10 @@ RelativePath=".\Encyclopedia_new.h" > + + @@ -824,6 +828,10 @@ RelativePath=".\Encyclopedia_new.cpp" > + + diff --git a/Laptop/Laptop_VS2008.vcproj b/Laptop/Laptop_VS2008.vcproj index 1dd82bff..a2aed9bc 100644 --- a/Laptop/Laptop_VS2008.vcproj +++ b/Laptop/Laptop_VS2008.vcproj @@ -462,6 +462,10 @@ RelativePath=".\Encyclopedia_new.h" > + + @@ -822,6 +826,10 @@ RelativePath=".\Encyclopedia_new.cpp" > + + diff --git a/Laptop/Laptop_VS2010.vcxproj b/Laptop/Laptop_VS2010.vcxproj index 3ed49a16..15da52cf 100644 --- a/Laptop/Laptop_VS2010.vcxproj +++ b/Laptop/Laptop_VS2010.vcxproj @@ -54,6 +54,7 @@ + @@ -145,6 +146,7 @@ + diff --git a/Laptop/Laptop_VS2010.vcxproj.filters b/Laptop/Laptop_VS2010.vcxproj.filters index 650b847f..d0576553 100644 --- a/Laptop/Laptop_VS2010.vcxproj.filters +++ b/Laptop/Laptop_VS2010.vcxproj.filters @@ -257,6 +257,9 @@ Header Files + + + Header Files Header Files @@ -548,6 +551,9 @@ Source Files + + Source Files + Source Files diff --git a/Laptop/Laptop_VS2013.vcxproj b/Laptop/Laptop_VS2013.vcxproj index 2702e9cb..bd787800 100644 --- a/Laptop/Laptop_VS2013.vcxproj +++ b/Laptop/Laptop_VS2013.vcxproj @@ -54,6 +54,7 @@ + @@ -145,6 +146,7 @@ + diff --git a/Laptop/Laptop_VS2013.vcxproj.filters b/Laptop/Laptop_VS2013.vcxproj.filters index 5dd872fd..7f7f84a4 100644 --- a/Laptop/Laptop_VS2013.vcxproj.filters +++ b/Laptop/Laptop_VS2013.vcxproj.filters @@ -237,6 +237,9 @@ Header Files + + Header Files + Header Files @@ -523,6 +526,9 @@ Source Files + + + Source Files Source Files diff --git a/Laptop/Laptop_VS2017.vcxproj b/Laptop/Laptop_VS2017.vcxproj index a3ff7991..1603065e 100644 --- a/Laptop/Laptop_VS2017.vcxproj +++ b/Laptop/Laptop_VS2017.vcxproj @@ -54,6 +54,7 @@ + @@ -145,6 +146,7 @@ + diff --git a/Laptop/Laptop_VS2019.vcxproj b/Laptop/Laptop_VS2019.vcxproj index 010097a9..a711fd99 100644 --- a/Laptop/Laptop_VS2019.vcxproj +++ b/Laptop/Laptop_VS2019.vcxproj @@ -74,6 +74,7 @@ + @@ -165,6 +166,7 @@ + diff --git a/Laptop/laptop.cpp b/Laptop/laptop.cpp index 6f502d47..a4880188 100644 --- a/Laptop/laptop.cpp +++ b/Laptop/laptop.cpp @@ -92,6 +92,7 @@ #include "PMC.h" // added by Flugente #include "MilitiaWebsite.h" // added by Flugente #include "Intelmarket.h" // added by Flugente + #include "FacilityProduction.h" // added by Flugente #endif #include "connect.h" @@ -1075,6 +1076,11 @@ INT32 EnterLaptop() if ( !gGameExternalOptions.fIntelResource ) RemoveBookmark( INTELMARKET_BOOKMARK ); + + if ( gGameExternalOptions.fFactories ) + SetBookMark( PRODUCTION_BOOKMARK ); + else + RemoveBookmark( PRODUCTION_BOOKMARK ); } LoadLoadPending( ); @@ -1521,6 +1527,10 @@ void RenderLaptop() case LAPTOP_MODE_INTELMARKET_ABOUT: RenderIntelmarket_About(); break; + + case LAPTOP_MODE_FACILITY_PRODUCTION: + RenderFacilityProduction(); + break; } if( guiCurrentLaptopMode >= LAPTOP_MODE_WWW ) @@ -1997,6 +2007,10 @@ void EnterNewLaptopMode() case LAPTOP_MODE_INTELMARKET_ABOUT: EnterIntelmarket_About(); break; + + case LAPTOP_MODE_FACILITY_PRODUCTION: + EnterFacilityProduction(); + break; } // first time using webbrowser in this laptop session @@ -2288,6 +2302,10 @@ void HandleLapTopHandles() case LAPTOP_MODE_INTELMARKET_ABOUT: HandleIntelmarket_About(); break; + + case LAPTOP_MODE_FACILITY_PRODUCTION: + HandleFacilityProduction(); + break; } } @@ -2886,6 +2904,10 @@ UINT32 ExitLaptopMode(UINT32 uiMode) case LAPTOP_MODE_INTELMARKET_ABOUT: ExitIntelmarket_About(); break; + + case LAPTOP_MODE_FACILITY_PRODUCTION: + ExitFacilityProduction(); + break; } if( ( uiMode != LAPTOP_MODE_NONE )&&( uiMode < LAPTOP_MODE_WWW ) ) @@ -4551,6 +4573,27 @@ void GoToWebPage(INT32 iPageId ) } } break; + + case PRODUCTION_BOOKMARK: + { + guiCurrentWWWMode = LAPTOP_MODE_FACILITY_PRODUCTION; + guiCurrentLaptopMode = LAPTOP_MODE_FACILITY_PRODUCTION; + + // do we have to have a World Wide Wait + if ( LaptopSaveInfo.fVisitedBookmarkAlready[PRODUCTION_BOOKMARK] == FALSE ) + { + // reset flag and set load pending flag + LaptopSaveInfo.fVisitedBookmarkAlready[PRODUCTION_BOOKMARK] = TRUE; + fLoadPendingFlag = TRUE; + } + else + { + // fast reload + fLoadPendingFlag = TRUE; + fFastLoadFlag = TRUE; + } + } + break; } #ifdef JA2UB @@ -6346,6 +6389,7 @@ void HandleKeyBoardShortCutsForLapTop( UINT16 usEvent, UINT32 usParam, UINT16 us SetBookMark( PMC_BOOKMARK ); SetBookMark( MILITIAROSTER_BOOKMARK ); SetBookMark( INTELMARKET_BOOKMARK ); + SetBookMark( PRODUCTION_BOOKMARK ); } } diff --git a/Laptop/laptop.h b/Laptop/laptop.h index e6615ad6..b2cadc80 100644 --- a/Laptop/laptop.h +++ b/Laptop/laptop.h @@ -169,6 +169,9 @@ enum LAPTOP_MODE_INTELMARKET_BUYINFO, LAPTOP_MODE_INTELMARKET_SELLINFO, LAPTOP_MODE_INTELMARKET_ABOUT, + + // Flugente: facility production + LAPTOP_MODE_FACILITY_PRODUCTION, LAPTOP_MODE_BOBBYR_SHIPMENTS, @@ -251,6 +254,7 @@ enum{ PMC_BOOKMARK, // added by Flugente MILITIAROSTER_BOOKMARK, // added by Flugente INTELMARKET_BOOKMARK, // added by Flugente + PRODUCTION_BOOKMARK, // added by Flugente TEXT_NUM_LAPTOP_BOOKMARKS }; diff --git a/Strategic/Campaign Types.h b/Strategic/Campaign Types.h index 80f53977..c12d5042 100644 --- a/Strategic/Campaign Types.h +++ b/Strategic/Campaign Types.h @@ -283,6 +283,34 @@ typedef struct FACILITYASSIGNMENTTYPE } FACILITYASSIGNMENTTYPE; +// struct needed during production and laptop display +typedef struct PRODUCTION_LINE_PREPRODUCT +{ + UINT16 item; + UINT32 requiredforonecreation; +} PRODUCTION_LINE_PREPRODUCT; + +// -------- added by Flugente: various flags for factories -------- +#define REQUIRES_STAFFING 0x00000001 //1 // the factory can only be activated if the facility is staffed + +typedef struct PRODUCTION_LINE +{ + // determines which items can be produced here with what requirement + CHAR16 szProductionName[30]; + CHAR16 szAdditionalRequirementTips[80]; + UINT16 usItemToCreate; // item that shall be created + INT32 sMinutesRequired; // time required to create one item + INT32 sGridNo_Creation; // the location where the item is dropped at + + UINT32 usProductionFlags; // flagmask for various properties + + INT32 sHourlyCost; // cost for every hour of work (NOT per item). Negative values mean we gain money. + UINT8 usOptional_LoyaltyRequired; // loyalty in the sector must be at least this value. Only applicable in town sectors. + + // this vector contains all the items we need to create what we want in what quantity + std::vector usOptional_PreProducts; +} PRODUCTION_LINE; + // Flugente: facilitytype properties #define FACILITYTYPE_PMCENTRYPOINT 0x00000001 // militia hired from the PMC can only enter Arulco in sectors with facilites with this property @@ -302,6 +330,8 @@ typedef struct FACILITYTYPE FACILITYASSIGNMENTTYPE AssignmentData[ NUM_FACILITY_ASSIGNMENTS ]; // Data about possible assignments that can be done here + std::vector ProductionData; + } FACILITYTYPE; // HEADROCK HAM 3.5: Maximum number of different facility types diff --git a/Strategic/Hourly Update.cpp b/Strategic/Hourly Update.cpp index 1e2ff7b5..a9c0d1ea 100644 --- a/Strategic/Hourly Update.cpp +++ b/Strategic/Hourly Update.cpp @@ -24,6 +24,8 @@ #include "Interface.h" // added by Flugente #include "SkillCheck.h" // added by Flugente #include "Isometric Utils.h" // added by Flugente for NOWHERE + #include "strategic.h" // added by Flugente + #include "message.h" // added by Flugente for ScreenMsg(...) #endif #include "Luaglobal.h" @@ -48,6 +50,7 @@ void HourlyLarryUpdate(); void HourlySmokerUpdate(); void HourlyDisabilityUpdate(); void HourlyStealUpdate(); // Flugente: certain characters might steal equipment (backgrounds) +void HourlyFactoryUpdate(); // Flugente: update factories void HourlySnitchUpdate(); // anv: decreasing cooldown after exposition extern SECTOR_EXT_DATA SectorExternalData[256][4]; @@ -133,6 +136,8 @@ CHAR16 zString[128]; HourlyGatheringInformation(); + HourlyFactoryUpdate(); + #ifdef JA2UB // no UB #else @@ -820,6 +825,335 @@ void HourlyStealUpdate() } } +BOOLEAN RemoveItemInSector( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ, UINT16 usItem, UINT32 usNumToRemove ) +{ + // open sector inv + UINT32 uiTotalNumberOfRealItems = 0; + std::vector pWorldItem;//dnl ch75 271013 + BOOLEAN fReturn = FALSE; + + if ( ( gWorldSectorX == sSectorX ) && ( gWorldSectorY == sSectorY ) && ( gbWorldSectorZ == bSectorZ ) ) + { + uiTotalNumberOfRealItems = guiNumWorldItems; + + pWorldItem = gWorldItems; + } + else + { + // not loaded, load + // get total number, visable and invisible + fReturn = GetNumberOfWorldItemsFromTempItemFile( sSectorX, sSectorY, bSectorZ, &( uiTotalNumberOfRealItems ), FALSE ); + Assert( fReturn ); + + if ( uiTotalNumberOfRealItems > 0 ) + { + // allocate space for the list + pWorldItem.resize( uiTotalNumberOfRealItems );//dnl ch75 271013 + + // now load into mem + LoadWorldItemsFromTempItemFile( sSectorX, sSectorY, bSectorZ, pWorldItem ); + } + } + + if ( !uiTotalNumberOfRealItems ) + return FALSE; + + BOOLEAN removedsth = FALSE; + OBJECTTYPE* pObj = NULL; + for ( UINT32 uiCount = 0; uiCount < uiTotalNumberOfRealItems && usNumToRemove > 0; ++uiCount ) // ... for all items in the world ... + { + if ( pWorldItem[uiCount].fExists + && pWorldItem[uiCount].usFlags & WORLD_ITEM_REACHABLE + && pWorldItem[uiCount].bVisible == VISIBLE ) + { + OBJECTTYPE* pObj = &( pWorldItem[uiCount].object ); // ... get pointer for this item ... + + if ( pObj != NULL && pObj->exists() ) // ... if pointer is not obviously useless ... + { + if ( pObj->usItem == usItem ) + { + if ( usNumToRemove < pObj->ubNumberOfObjects ) + { + pObj->RemoveObjectsFromStack( usNumToRemove ); + usNumToRemove = 0; + } + else + { + usNumToRemove -= pObj->ubNumberOfObjects; + pObj->RemoveObjectsFromStack( pObj->ubNumberOfObjects ); + } + + removedsth = TRUE; + } + } + } + } + + if ( removedsth ) + { + // save the changed inventory + // open sector inv + if ( ( gWorldSectorX == sSectorX ) && ( gWorldSectorY == sSectorY ) && ( gbWorldSectorZ == bSectorZ ) ) + { + guiNumWorldItems = uiTotalNumberOfRealItems; + gWorldItems = pWorldItem; + } + else + { + //Save the Items to the the file + SaveWorldItemsToTempItemFile( sSectorX, sSectorY, bSectorZ, uiTotalNumberOfRealItems, pWorldItem ); + } + + return TRUE; + } + + return FALSE; +} + +UINT32 CountAccessibleItemsInSector( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ, UINT16 usItem ) +{ + UINT32 numfound = 0; + + // open sector inv + UINT32 uiTotalNumberOfRealItems = 0; + std::vector pWorldItem;//dnl ch75 271013 + BOOLEAN fReturn = FALSE; + + if ( ( gWorldSectorX == sSectorX ) && ( gWorldSectorY == sSectorY ) && ( gbWorldSectorZ == bSectorZ ) ) + { + uiTotalNumberOfRealItems = guiNumWorldItems; + + pWorldItem = gWorldItems; + } + else + { + // not loaded, load + // get total number, visable and invisible + fReturn = GetNumberOfWorldItemsFromTempItemFile( sSectorX, sSectorY, bSectorZ, &( uiTotalNumberOfRealItems ), FALSE ); + Assert( fReturn ); + + if ( uiTotalNumberOfRealItems > 0 ) + { + // allocate space for the list + pWorldItem.resize( uiTotalNumberOfRealItems );//dnl ch75 271013 + + // now load into mem + LoadWorldItemsFromTempItemFile( sSectorX, sSectorY, bSectorZ, pWorldItem ); + } + } + + OBJECTTYPE* pObj = NULL; + for ( UINT32 uiCount = 0; uiCount < uiTotalNumberOfRealItems; ++uiCount ) // ... for all items in the world ... + { + if ( pWorldItem[uiCount].fExists + && pWorldItem[uiCount].usFlags & WORLD_ITEM_REACHABLE + && pWorldItem[uiCount].bVisible == VISIBLE ) + { + OBJECTTYPE* pObj = &( pWorldItem[uiCount].object ); // ... get pointer for this item ... + + if ( pObj != NULL && pObj->exists() && pObj->usItem == usItem ) + { + numfound += pObj->ubNumberOfObjects; + } + } + } + + return numfound; +} + +extern void SetFactoryLeftoverProgress( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ, UINT16 usFacilityType, UINT16 usProductionNumber, INT32 sProgressLeft ); +extern INT32 GetFactoryLeftoverProgress( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ, UINT16 usFacilityType, UINT16 usProductionNumber ); + +BOOLEAN GetFacilityProductionState( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ, UINT16 usFacilityType, UINT16 usProductionNumber ) +{ + return GetFactoryLeftoverProgress( sSectorX, sSectorY, bSectorZ, usFacilityType, usProductionNumber ) > -1; +} + +void SetFacilityProductionState( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ, UINT16 usFacilityType, UINT16 usProductionNumber, BOOLEAN aOn ) +{ + return SetFactoryLeftoverProgress( sSectorX, sSectorY, bSectorZ, usFacilityType, usProductionNumber, aOn ? 0 : -1 ); +} + +void HourlyFactoryUpdate() +{ + if ( !gGameExternalOptions.fFactories ) + return; + + // how much money do we currently have? + INT32 balance = GetCurrentBalance(); + INT32 moneyspentonproduction = 0; + + for ( UINT16 sector = 0; sector < 256; ++sector ) + { + if ( !StrategicMap[SECTOR_INFO_TO_STRATEGIC_INDEX( sector )].fEnemyControlled ) + { + UINT8 ubTownID = GetTownIdForSector( SECTORX( sector ), SECTORY( sector ) ); + + CHAR16 wSectorName[64]; + GetSectorIDString( SECTORX( sector ), SECTORY( sector ), 0, wSectorName, FALSE ); + + for ( UINT16 cnt = 0; cnt < NUM_FACILITY_TYPES; ++cnt ) + { + // Is this facility here? + if ( gFacilityLocations[sector][cnt].fFacilityHere ) + { + UINT16 productioncnt = 0; + for ( std::vector::iterator prodit = gFacilityTypes[cnt].ProductionData.begin(), proditend = gFacilityTypes[cnt].ProductionData.end(); prodit != proditend; ++prodit, ++productioncnt ) + { + // get production progress from the previous hour + INT32 productiontime = GetFactoryLeftoverProgress( SECTORX( sector ), SECTORY( sector ), 0, cnt, productioncnt ); + + // negative value means factory is not active + if ( productiontime < 0 ) + continue; + + CHAR16 productionname[64]; + swprintf( productionname, L"%s", wcslen((*prodit ).szProductionName ) > 0 ? ( *prodit ).szProductionName : ( *prodit ).usItemToCreate != NOTHING ? Item[( *prodit ).usItemToCreate].szItemName : L"--" ); + + // check for sufficient loyalty + if ( ubTownID != BLANK_SECTOR + && gTownLoyalty[ubTownID].ubRating < ( *prodit ).usOptional_LoyaltyRequired ) + { + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szFactoryText[0], wSectorName, productionname ); + SetFacilityProductionState( SECTORX( sector ), SECTORY( sector ), 0, cnt, productioncnt, FALSE ); + continue; + } + + // check for funds + if ( moneyspentonproduction + ( *prodit ).sHourlyCost > balance ) + { + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szFactoryText[1], wSectorName, productionname ); + SetFacilityProductionState( SECTORX( sector ), SECTORY( sector ), 0, cnt, productioncnt, FALSE ); + continue; + } + + // check whether facility is staffed if required + if ( ( *prodit ).usProductionFlags & REQUIRES_STAFFING ) + { + bool isstaffed = false; + bool isstaffed_andawake = false; + SOLDIERTYPE *pSoldier = NULL; + UINT32 uiCnt = 0; + for ( uiCnt = 0, pSoldier = MercPtrs[uiCnt]; uiCnt <= gTacticalStatus.Team[gbPlayerNum].bLastID; ++uiCnt, ++pSoldier ) + { + if ( pSoldier->bActive && ( pSoldier->sSectorX == SECTORX( sector ) ) && ( pSoldier->sSectorY == SECTORY( sector ) ) && ( pSoldier->bSectorZ == 0 ) ) + { + if ( pSoldier->sFacilityTypeOperated == cnt ) + { + isstaffed = true; + + // check whether the staffing merc is asleep or has spent enough time on this + if ( !pSoldier->flags.fMercAsleep && EnoughTimeOnAssignment( pSoldier ) ) + { + isstaffed_andawake = true; + break; + } + } + } + } + + // if not staffed at all, shut down + if ( !isstaffed ) + { + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szFactoryText[2], wSectorName, productionname ); + SetFacilityProductionState( SECTORX( sector ), SECTORY( sector ), 0, cnt, productioncnt, FALSE ); + continue; + } + // if staffed but the staffing mercs are not active, skip this cycle + else if ( !isstaffed_andawake ) + { + continue; + } + } + + // add one hour of progress + productiontime += 60; + + // it's possible we might require several preproducts. Get an overview of all that is needed + // struct needed during production and laptop display + typedef struct FACTORY_PREPRODUCT_AVAILABLE + { + PRODUCTION_LINE_PREPRODUCT xml; + UINT32 available; + } FACTORY_PREPRODUCT_AVAILABLE; + + std::vector productionstoragedata; + + for ( std::vector::iterator useitemit = ( *prodit ).usOptional_PreProducts.begin(), useitemitend = ( *prodit ).usOptional_PreProducts.end(); useitemit != useitemitend; ++useitemit ) + { + FACTORY_PREPRODUCT_AVAILABLE data; + data.xml = ( *useitemit ); + data.available = CountAccessibleItemsInSector( SECTORX( sector ), SECTORY( sector ), 0, data.xml.item ); + productionstoragedata.push_back( data ); + } + + UINT32 itemstocreate = 0; + bool insufficientitems = false; + while ( productiontime >= ( *prodit ).sMinutesRequired ) + { + // check whether all items required are available + for ( std::vector::iterator tmpit = productionstoragedata.begin(), tmpitend = productionstoragedata.end(); tmpit != tmpitend; ++tmpit ) + { + if ( ( itemstocreate + 1 ) * ( *tmpit ).xml.requiredforonecreation > ( *tmpit ).available ) + { + insufficientitems = true; + break; + } + } + + if ( insufficientitems ) + break; + + ++itemstocreate; + productiontime -= ( *prodit ).sMinutesRequired; + } + + if ( itemstocreate ) + { + // remove required preproducts + for ( std::vector::iterator tmpit = productionstoragedata.begin(), tmpitend = productionstoragedata.end(); tmpit != tmpitend; ++tmpit ) + { + RemoveItemInSector( SECTORX( sector ), SECTORY( sector ), 0, ( *tmpit ).xml.item, ( *tmpit ).xml.requiredforonecreation * itemstocreate ); + } + + // create produced items and place them + if ( CreateItems( ( *prodit ).usItemToCreate, 100, itemstocreate, &gTempObject ) ) + { + if ( ( gWorldSectorX == SECTORX( sector ) ) && ( gWorldSectorY == SECTORY( sector ) ) && ( gbWorldSectorZ == 0 ) ) + { + AddItemToPool( ( *prodit ).sGridNo_Creation, &gTempObject, 1, 0, ( WOLRD_ITEM_FIND_SWEETSPOT_FROM_GRIDNO | WORLD_ITEM_REACHABLE ), 0 ); + } + else + { + AddItemsToUnLoadedSector( SECTORX( sector ), SECTORY( sector ), 0, + ( *prodit ).sGridNo_Creation, 1, &gTempObject, 0, ( WOLRD_ITEM_FIND_SWEETSPOT_FROM_GRIDNO | WORLD_ITEM_REACHABLE ), 0, 1, FALSE ); + } + } + } + + // if we can no longer produce anything because we don't have the items, shut off + if ( insufficientitems ) + { + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szFactoryText[3], wSectorName, productionname ); + SetFacilityProductionState( SECTORX( sector ), SECTORY( sector ), 0, cnt, productioncnt, FALSE ); + } + // otherwise set new partial progress + else + { + SetFactoryLeftoverProgress( SECTORX( sector ), SECTORY( sector ), 0, cnt, productioncnt, productiontime ); + } + + moneyspentonproduction += ( *prodit ).sHourlyCost; + } + } + } + } + } + + // substract money spent + AddTransactionToPlayersBook ( FACILITY_OPERATIONS, NO_PROFILE, GetWorldTotalMin(), -moneyspentonproduction ); +} + #ifdef JA2UB // no JA25 UB #else diff --git a/Strategic/LuaInitNPCs.cpp b/Strategic/LuaInitNPCs.cpp index 8a1e33b9..0bd34695 100644 --- a/Strategic/LuaInitNPCs.cpp +++ b/Strategic/LuaInitNPCs.cpp @@ -13408,6 +13408,41 @@ void LuaGetIntelAndQuestMapData( INT32 aLevel ) LuaFunction( _LS.L, "GetIntelAndQuestMapData" ).Param( aLevel ).Call( 1 ); } +void SetFactoryLeftoverProgress( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ, UINT16 usFacilityType, UINT16 usProductionNumber, INT32 sProgressLeft ) +{ + const char* filename = "scripts\\strategicmap.lua"; + + LuaScopeState _LS( true ); + + IniFunction( _LS.L(), TRUE ); + IniGlobalGameSetting( _LS.L() ); + + SGP_THROW_IFFALSE( _LS.L.EvalFile( filename ), _BS( "Cannot open file: " ) << filename << _BS::cget ); + + LuaFunction( _LS.L, "SetFactoryLeftoverProgress" ).Param( sSectorX ).Param( sSectorY ).Param( bSectorZ ).Param( usFacilityType ).Param( usProductionNumber ).Param( sProgressLeft ).Call( 6 ); +} + +INT32 GetFactoryLeftoverProgress( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ, UINT16 usFacilityType, UINT16 usProductionNumber ) +{ + const char* filename = "scripts\\strategicmap.lua"; + + LuaScopeState _LS( true ); + + IniFunction( _LS.L(), TRUE ); + IniGlobalGameSetting( _LS.L() ); + + SGP_THROW_IFFALSE( _LS.L.EvalFile( filename ), _BS( "Cannot open file: " ) << filename << _BS::cget ); + + LuaFunction( _LS.L, "GetFactoryLeftoverProgress" ).Param( sSectorX ).Param( sSectorY ).Param( bSectorZ ).Param( usFacilityType ).Param( usProductionNumber ).Call( 5 ); + + if ( lua_gettop( _LS.L() ) >= 0 ) + { + return lua_tointeger( _LS.L(), 1 ); + } + + return 0; +} + extern void AddIntelAndQuestMapDataForSector( INT16 sSectorX, INT16 sSectorY, UINT8 ausMapColour, int asSymbol, STR16 aText, STR16 aText_Short ); static int l_SetIntelAndQuestMapDataForSector( lua_State *L ) diff --git a/Strategic/LuaInitNPCs.h b/Strategic/LuaInitNPCs.h index 0a1a1b14..fd9ef4ca 100644 --- a/Strategic/LuaInitNPCs.h +++ b/Strategic/LuaInitNPCs.h @@ -100,4 +100,6 @@ void LuaGetPhotoData( UINT8 aType ); void LuaSetPhotoState( INT16 asIndex, UINT8 aState ); void LuaVerifyPhotoState( INT16 asIndex ); void LuaGetIntelAndQuestMapData( INT32 aLevel ); +void SetFactoryLeftoverProgress( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ, UINT16 usFacilityType, UINT16 usProductionNumber, INT32 sProgressLeft ); +INT32 GetFactoryLeftoverProgress( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ, UINT16 usFacilityType, UINT16 usProductionNumber ); #endif diff --git a/Strategic/Map Screen Interface Map.cpp b/Strategic/Map Screen Interface Map.cpp index e0442156..74aab231 100644 --- a/Strategic/Map Screen Interface Map.cpp +++ b/Strategic/Map Screen Interface Map.cpp @@ -8344,6 +8344,8 @@ void AddIntelAndQuestMapDataForSector( INT16 sSectorX, INT16 sSectorY, UINT8 aus } } +extern BOOLEAN GetFacilityProductionState( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ, UINT16 usFacilityType, UINT16 usProductionNumber ); + void DetermineMapIntelData( INT32 asSectorZ ) { // clear data @@ -8412,6 +8414,58 @@ void DetermineMapIntelData( INT32 asSectorZ ) } } } + + // Flugente: factories + if ( gGameExternalOptions.fFactories ) + { + for ( UINT16 sector = 0; sector < 256; ++sector ) + { + BOOLEAN productionfound = FALSE; + BOOLEAN activeproductionfound = FALSE; + BOOLEAN inactiveproductionfound = FALSE; + BOOLEAN productionunderenemycontrol = FALSE; + + for ( UINT16 cnt = 0; cnt < NUM_FACILITY_TYPES; ++cnt ) + { + // Is this facility here? + if ( gFacilityLocations[sector][cnt].fFacilityHere ) + { + if ( gFacilityLocations[sector][cnt].ubHidden == 0 || + ( gFacilityLocations[sector][cnt].ubHidden == 1 && SectorInfo[sector].fSurfaceWasEverPlayerControlled ) ) + { + if ( StrategicMap[SECTOR_INFO_TO_STRATEGIC_INDEX( sector )].fEnemyControlled ) + { + // if it's an enemy controlled sector, just check whether there are production lines at all + if ( !gFacilityTypes[cnt].ProductionData.empty() ) + { + productionfound = TRUE; + productionunderenemycontrol = TRUE; + } + } + else + { + UINT16 productioncnt = 0; + for ( std::vector::iterator prodit = gFacilityTypes[cnt].ProductionData.begin(), proditend = gFacilityTypes[cnt].ProductionData.end(); prodit != proditend; + ++prodit, ++productioncnt ) + { + if ( GetFacilityProductionState( SECTORX( sector ), SECTORY( sector ), 0, cnt, productioncnt ) ) + activeproductionfound = TRUE; + else + inactiveproductionfound = TRUE; + + productionfound = TRUE; + } + } + } + } + } + + if ( productionfound ) + { + AddIntelAndQuestMapDataForSector( SECTORX( sector ), SECTORY( sector ), -1, productionunderenemycontrol ? 22 : activeproductionfound ? inactiveproductionfound ? 19 : 20 : 21, L"", L"" ); + } + } + } } // add lua data @@ -8421,7 +8475,6 @@ void DetermineMapIntelData( INT32 asSectorZ ) void ShowIntelOnMap() { INT16 usXPos, usYPos; - CHAR16 sString[256]; INT32 MapItemsFont; if ( iResolution <= _800x600 ) diff --git a/Strategic/Player Command.cpp b/Strategic/Player Command.cpp index 78d42ca9..4852eb70 100644 --- a/Strategic/Player Command.cpp +++ b/Strategic/Player Command.cpp @@ -39,6 +39,8 @@ extern BOOLEAN fMapScreenBottomDirty; extern CPostalService gPostalService; +// Flugente: external sector data +extern SECTOR_EXT_DATA SectorExternalData[256][4]; void AddFacilitiesToBox( INT16 sMapX, INT16 sMapY, UINT32 *uiHandle, BOOLEAN fCityInfoBox ) { @@ -46,15 +48,15 @@ void AddFacilitiesToBox( INT16 sMapX, INT16 sMapY, UINT32 *uiHandle, BOOLEAN fCi // HEADROCK HAM 3.5: Facilities are now read from XMLs, including their names. - UINT32 cnt = 0; UINT32 uiNumFacilities = 0; BOOLEAN fHeaderAdded = FALSE; CHAR16 szFacilityString[30]; + CHAR16 szTmpString[80]; Assert(sMapX > 0 && sMapY > 0 && sMapX < 17 && sMapY < 17); - for ( cnt = 0; cnt < NUM_FACILITY_TYPES; cnt++ ) + for ( UINT16 cnt = 0; cnt < NUM_FACILITY_TYPES; ++cnt ) { if (fCityInfoBox && uiNumFacilities == 0 && !fHeaderAdded ) { @@ -66,6 +68,7 @@ void AddFacilitiesToBox( INT16 sMapX, INT16 sMapY, UINT32 *uiHandle, BOOLEAN fCi fHeaderAdded = TRUE; } } + // Facility type exists at this location? if (gFacilityLocations[SECTOR(sMapX,sMapY)][cnt].fFacilityHere) { @@ -85,7 +88,24 @@ void AddFacilitiesToBox( INT16 sMapX, INT16 sMapY, UINT32 *uiHandle, BOOLEAN fCi } AddSecondColumnMonoString( uiHandle, gFacilityTypes[cnt].szFacilityName ); - uiNumFacilities++; + ++uiNumFacilities; + + // Flugente: factories + if ( gGameExternalOptions.fFactories ) + { + for ( std::vector::iterator prodit = gFacilityTypes[cnt].ProductionData.begin(), proditend = gFacilityTypes[cnt].ProductionData.end(); prodit != proditend; ++prodit ) + { + if ( wcslen( ( *prodit ).szAdditionalRequirementTips ) > 0 ) + { + // Add empty line on the left size to make room for text on the right. + AddMonoString( uiHandle, L"" ); + + swprintf( szTmpString, L"%s", ( *prodit ).szAdditionalRequirementTips ); + AddSecondColumnMonoString( uiHandle, szTmpString ); + ++uiNumFacilities; + } + } + } } } } @@ -178,9 +198,6 @@ void AddFacilitiesToBox( INT16 sMapX, INT16 sMapY, UINT32 *uiHandle, BOOLEAN fCi return; } -// Flugente: external sector data -extern SECTOR_EXT_DATA SectorExternalData[256][4]; - // ALL changes of control to player must be funneled through here! BOOLEAN SetThisSectorAsPlayerControlled( INT16 sMapX, INT16 sMapY, INT8 bMapZ, BOOLEAN fContested ) { diff --git a/Strategic/XML_FacilityTypes.cpp b/Strategic/XML_FacilityTypes.cpp index 5199d05c..5d756175 100644 --- a/Strategic/XML_FacilityTypes.cpp +++ b/Strategic/XML_FacilityTypes.cpp @@ -37,6 +37,8 @@ typedef enum FACILITYTYPE_CONDITIONS_ELEMENT, FACILITYTYPE_RISK, FACILITYTYPE_RISK_ELEMENT, + FACILITYTYPE_PRODUCTION, + FACILITYTYPE_PRODUCTION_ELEMENT, } FACILITYTYPE_PARSE_STAGE; @@ -48,8 +50,10 @@ struct FACILITYTYPE curFacilityTypeData; FACILITYASSIGNMENTTYPE curAssignmentData; + PRODUCTION_LINE curProductionData; INT16 curAssignmentType; INT16 curRisk; + INT16 curProduction; UINT32 maxArraySize; UINT32 curIndex; UINT32 currentDepth; @@ -125,15 +129,29 @@ void InitAssignmentDataArray( facilitytypeParseData *pData ) pData->curAssignmentData.ubMinimumWisdom = 0; // Set RISK data - for (UINT16 cnt = 0; cnt < NUM_RISKS; cnt++) + for (UINT16 cnt = 0; cnt < NUM_RISKS; ++cnt) { pData->curAssignmentData.Risk[cnt].usChance = 0; pData->curAssignmentData.Risk[cnt].bBaseEffect = 0; pData->curAssignmentData.Risk[cnt].ubRange = 0; } - } +void InitProductionDataArray( facilitytypeParseData *pData ) +{ + // Set assignment data from memory + swprintf( pData->curProductionData.szProductionName, L"" ); + swprintf( pData->curProductionData.szAdditionalRequirementTips, L"" ); + pData->curProductionData.usItemToCreate = NOTHING; + pData->curProductionData.sMinutesRequired = 60; + pData->curProductionData.sGridNo_Creation = -1; + + pData->curProductionData.usProductionFlags = 0; + + pData->curProductionData.sHourlyCost = 0; + pData->curProductionData.usOptional_LoyaltyRequired = 0; + pData->curProductionData.usOptional_PreProducts.clear(); +} static void XMLCALL facilitytypeStartElementHandle(void *userData, const XML_Char *name, const XML_Char **atts) @@ -164,6 +182,8 @@ facilitytypeStartElementHandle(void *userData, const XML_Char *name, const XML_C pData->maxReadDepth++; //we are not skipping this element + pData->curProduction = -1; + //pData->curIndex++; } @@ -197,6 +217,35 @@ facilitytypeStartElementHandle(void *userData, const XML_Char *name, const XML_C pData->maxReadDepth++; } + // Encountered Production entry + else if ( pData->curElement == FACILITYTYPE_TYPE && + strcmp( name, "PRODUCTIONLINE" ) == 0 ) + { + // Set value to -1, denoting that we have not yet read which production is being described. + pData->curProduction++; + + // Reset the array + InitProductionDataArray ( pData ); + + pData->curElement = FACILITYTYPE_PRODUCTION; + + pData->maxReadDepth++; + } + // Encountered production data + else if ( pData->curElement == FACILITYTYPE_PRODUCTION && + ( strcmp( name, "szProductionName" ) == 0 || + strcmp( name, "szAdditionalRequirementTips" ) == 0 || + strcmp( name, "usItemToCreate" ) == 0 || + strcmp( name, "sMinutesRequired" ) == 0 || + strcmp( name, "sGridNo_Creation" ) == 0 || + strcmp( name, "requires_staff" ) == 0 || + strcmp( name, "sHourlyCost" ) == 0 || + strcmp( name, "usOptional_LoyaltyRequired" ) == 0 || + strcmp( name, "usOptional_ItemUsedUp" ) == 0 ) ) + { + pData->curElement = FACILITYTYPE_PRODUCTION_ELEMENT; + pData->maxReadDepth++; + } // Encountered assignment data else if(pData->curElement == FACILITYTYPE_ASSIGNMENT && @@ -354,7 +403,6 @@ facilitytypeStartElementHandle(void *userData, const XML_Char *name, const XML_C pData->maxReadDepth++; } - else if(pData->curElement == FACILITYTYPE_RISK && (strcmp(name, "ubChance") == 0 || strcmp(name, "bBaseEffect") == 0 || @@ -364,6 +412,20 @@ facilitytypeStartElementHandle(void *userData, const XML_Char *name, const XML_C pData->maxReadDepth++; } + else if ( pData->curElement == FACILITYTYPE_PRODUCTION && + ( strcmp( name, "szProductionName" ) == 0 || + strcmp( name, "szAdditionalRequirementTips" ) == 0 || + strcmp( name, "usItemToCreate" ) == 0 || + strcmp( name, "sMinutesRequired" ) == 0 || + strcmp( name, "sGridNo_Creation" ) == 0 || + strcmp( name, "requires_staff" ) == 0 || + strcmp( name, "sHourlyCost" ) == 0 || + strcmp( name, "usOptional_LoyaltyRequired" ) == 0 || + strcmp( name, "usOptional_ItemUsedUp" ) == 0 ) ) + { + pData->curElement = FACILITYTYPE_PRODUCTION_ELEMENT; + pData->maxReadDepth++; + } pData->szCharData[0] = '\0'; } @@ -477,6 +539,9 @@ facilitytypeEndElementHandle(void *userData, const XML_Char *name) gFacilityTypes[pData->curIndex].AssignmentData[cnt].Risk[cntB].ubRange = pData->curFacilityTypeData.AssignmentData[cnt].Risk[cntB].ubRange; } } + + // Set production-specific data + gFacilityTypes[pData->curIndex].ProductionData = pData->curFacilityTypeData.ProductionData; } else { @@ -625,6 +690,23 @@ facilitytypeEndElementHandle(void *userData, const XML_Char *name) } } + else if ( strcmp( name, "PRODUCTIONLINE" ) == 0 ) + { + pData->curElement = FACILITYTYPE_TYPE; + + // Make sure an production is selected for data dump + if ( pData->curProduction == -1 ) + { + CHAR16 sErrorString[256]; + swprintf( sErrorString, L"FacilityTypes.XML Error: Production data for facility type %d is missing a tag", pData->curIndex ); + SGP_THROW( sErrorString ); + } + else + { + // Set data from memory + pData->curFacilityTypeData.ProductionData.push_back( pData->curProductionData ); + } + } //////////////////////////////////////////////// // Specific Assignment Data @@ -1107,7 +1189,76 @@ facilitytypeEndElementHandle(void *userData, const XML_Char *name) pData->curElement = FACILITYTYPE_RISK; pData->curAssignmentData.Risk[pData->curRisk].ubRange = (UINT8) atol(pData->szCharData); } + + else if ( strcmp( name, "szProductionName" ) == 0 ) + { + pData->curElement = FACILITYTYPE_PRODUCTION; + MultiByteToWideChar( CP_UTF8, 0, pData->szCharData, -1, pData->curProductionData.szProductionName, sizeof( pData->curProductionData.szProductionName ) / sizeof( pData->curProductionData.szProductionName[0] ) ); + pData->curProductionData.szProductionName[sizeof( pData->curProductionData.szProductionName ) / sizeof( pData->curProductionData.szProductionName[0] ) - 1] = '\0'; + } + else if ( strcmp( name, "szAdditionalRequirementTips" ) == 0 ) + { + pData->curElement = FACILITYTYPE_PRODUCTION; + + MultiByteToWideChar( CP_UTF8, 0, pData->szCharData, -1, pData->curProductionData.szAdditionalRequirementTips, sizeof( pData->curProductionData.szAdditionalRequirementTips ) / sizeof( pData->curProductionData.szAdditionalRequirementTips[0] ) ); + pData->curProductionData.szAdditionalRequirementTips[sizeof( pData->curProductionData.szAdditionalRequirementTips ) / sizeof( pData->curProductionData.szAdditionalRequirementTips[0] ) - 1] = '\0'; + } + else if ( strcmp( name, "usItemToCreate" ) == 0 ) + { + pData->curElement = FACILITYTYPE_PRODUCTION; + pData->curProductionData.usItemToCreate = (UINT16)atol( pData->szCharData ); + } + else if ( strcmp( name, "sMinutesRequired" ) == 0 ) + { + pData->curElement = FACILITYTYPE_PRODUCTION; + pData->curProductionData.sMinutesRequired = max(1, (INT32)atol( pData->szCharData ) ); + } + else if ( strcmp( name, "sGridNo_Creation" ) == 0 ) + { + pData->curElement = FACILITYTYPE_PRODUCTION; + pData->curProductionData.sGridNo_Creation = (INT32)atol( pData->szCharData ); + } + else if ( strcmp( name, "requires_staff" ) == 0 ) + { + pData->curElement = FACILITYTYPE_PRODUCTION; + if ( (UINT32)atol( pData->szCharData ) ) + pData->curProductionData.usProductionFlags |= REQUIRES_STAFFING; + } + else if ( strcmp( name, "sHourlyCost" ) == 0 ) + { + pData->curElement = FACILITYTYPE_PRODUCTION; + pData->curProductionData.sHourlyCost = (INT32)atol( pData->szCharData ); + } + else if ( strcmp( name, "usOptional_LoyaltyRequired" ) == 0 ) + { + pData->curElement = FACILITYTYPE_PRODUCTION; + pData->curProductionData.usOptional_LoyaltyRequired = (UINT8)atol( pData->szCharData ); + } + else if ( strcmp( name, "usOptional_ItemUsedUp" ) == 0 ) + { + pData->curElement = FACILITYTYPE_PRODUCTION; + UINT16 requireditem = (UINT16)atol( pData->szCharData ); + + bool found = false; + for ( std::vector::size_type i = 0; i < pData->curProductionData.usOptional_PreProducts.size(); ++i ) + { + if ( pData->curProductionData.usOptional_PreProducts[i].item == requireditem ) + { + pData->curProductionData.usOptional_PreProducts[i].requiredforonecreation++; + found = true; + break; + } + } + + if ( !found ) + { + PRODUCTION_LINE_PREPRODUCT data; + data.item = requireditem; + data.requiredforonecreation = 1; + pData->curProductionData.usOptional_PreProducts.push_back( data ); + } + } pData->maxReadDepth--; } diff --git a/Utils/Text.h b/Utils/Text.h index a20cc07d..3091f35c 100644 --- a/Utils/Text.h +++ b/Utils/Text.h @@ -3091,6 +3091,8 @@ extern STR16 szChatTextEnemy[]; extern STR16 szMilitiaText[]; +extern STR16 szFactoryText[]; + #define TACTICAL_INVENTORY_DIALOG_NUM 16 #define TACTICAL_COVER_DIALOG_NUM 16 diff --git a/Utils/_ChineseText.cpp b/Utils/_ChineseText.cpp index b3cc47a1..e71a6780 100644 --- a/Utils/_ChineseText.cpp +++ b/Utils/_ChineseText.cpp @@ -4237,6 +4237,7 @@ STR16 pMapPopUpInventoryText[] = L"存货", L"离开", L"修理", //L"Repair", + L"Factories", // TODO.Translate }; // town strings @@ -5065,6 +5066,7 @@ STR16 pBookMarkStrings[] = L"安保公司", //L"Kerberus", L"民兵总览",//L"Militia Overview", L"R.I.S", + L"Factories", // TODO.Translate }; STR16 pBookmarkTitle[] = @@ -5191,6 +5193,7 @@ STR16 pWebPagesTitles[] = L"Recon情报服务 - 情报需求", //L"Recon Intelligence Services - Information Requests", L"Recon情报服务 - 情报验证", //L"Recon Intelligence Services - Information Verification", L"Recon情报服务 - 关于我们", //L"Recon Intelligence Services - About us", + L"Factory Overview", // TODO.Translate L"Bobby Ray - 最近的运货", L"百科全书", L"百科全书 - 数据", @@ -6995,6 +6998,7 @@ STR16 gzLaptopHelpText[] = L"Kerberus - 安保公司",//L"Kerberus - Experience In Security", L"民兵总览",//L"Militia Overview", L"Recon情报服务", //L"Recon Intelligence Services", + L"Controlled factories", // TODO.Translate }; @@ -11581,6 +11585,18 @@ STR16 szMilitiaText[] = L"取消", //L"Cancel", }; +STR16 szFactoryText[] = // TODO.Translate +{ + L"%s: Production of %s switched off as loyalty is too low.", + L"%s: Production of %s switched off due to insufficient funds.", + L"%s: Production of %s switched off as it requires a merc to staff the facility.", + L"%s: Production of %s switched off due to required items missing.", + L"Item to build", + + L"Preproducts", // 5 + L"h/item", +}; + // 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 364d1fa3..5d61840f 100644 --- a/Utils/_DutchText.cpp +++ b/Utils/_DutchText.cpp @@ -4239,6 +4239,7 @@ STR16 pMapPopUpInventoryText[] = L"Inventaris", L"OK", L"Repair", // TODO.Translate + L"Factories", // TODO.Translate }; // town strings @@ -5072,6 +5073,7 @@ STR16 pBookMarkStrings[] = L"Kerberus", L"Militia Overview", // TODO.Translate L"R.I.S.", + L"Factories", // TODO.Translate }; STR16 pBookmarkTitle[] = @@ -5198,6 +5200,7 @@ STR16 pWebPagesTitles[] = L"Recon Intelligence Services - Information Requests", // TODO.Translate L"Recon Intelligence Services - Information Verification", L"Recon Intelligence Services - About us", + L"Factory Overview", // TODO.Translate L"Bobby Ray's - Recent Shipments", L"Encyclopedia", L"Encyclopedia - Data", @@ -7011,6 +7014,7 @@ STR16 gzLaptopHelpText[] = L"Kerberus - Excellence In Security", L"Militia Overview", // TODO.Translate L"Recon Intelligence Services", // TODO.Translate + L"Controlled factories", // TODO.Translate }; @@ -11597,4 +11601,16 @@ STR16 szMilitiaText[] = L"Cancel", }; +STR16 szFactoryText[] = // TODO.Translate +{ + L"%s: Production of %s switched off as loyalty is too low.", + L"%s: Production of %s switched off due to insufficient funds.", + L"%s: Production of %s switched off as it requires a merc to staff the facility.", + L"%s: Production of %s switched off due to required items missing.", + L"Item to build", + + L"Preproducts", // 5 + L"h/item", +}; + #endif //DUTCH diff --git a/Utils/_EnglishText.cpp b/Utils/_EnglishText.cpp index 21444aef..8436cce7 100644 --- a/Utils/_EnglishText.cpp +++ b/Utils/_EnglishText.cpp @@ -4237,6 +4237,7 @@ STR16 pMapPopUpInventoryText[] = L"Inventory", L"Exit", L"Repair", + L"Factories", }; // town strings @@ -5065,6 +5066,7 @@ STR16 pBookMarkStrings[] = L"Kerberus", L"Militia Overview", L"R.I.S.", + L"Factories", }; STR16 pBookmarkTitle[] = @@ -5191,6 +5193,7 @@ STR16 pWebPagesTitles[] = L"Recon Intelligence Services - Information Requests", L"Recon Intelligence Services - Information Verification", L"Recon Intelligence Services - About us", + L"Factory Overview", L"Bobby Ray's - Recent Shipments", L"Encyclopedia", L"Encyclopedia - Data", @@ -6995,6 +6998,7 @@ STR16 gzLaptopHelpText[] = L"Kerberus - Experience In Security", L"Militia Overview", L"Recon Intelligence Services", + L"Controlled factories", }; @@ -11581,4 +11585,16 @@ STR16 szMilitiaText[] = L"Cancel", }; +STR16 szFactoryText[] = +{ + L"%s: Production of %s switched off as loyalty is too low.", + L"%s: Production of %s switched off due to insufficient funds.", + L"%s: Production of %s switched off as it requires a merc to staff the facility.", + L"%s: Production of %s switched off due to required items missing.", + L"Item to build", + + L"Preproducts", // 5 + L"h/item", +}; + #endif //ENGLISH diff --git a/Utils/_FrenchText.cpp b/Utils/_FrenchText.cpp index 71345c20..72b70b1f 100644 --- a/Utils/_FrenchText.cpp +++ b/Utils/_FrenchText.cpp @@ -4243,6 +4243,7 @@ STR16 pMapPopUpInventoryText[] = L"Inventaire", L"Quitter", L"Repair", // TODO.Translate + L"Factories", // TODO.Translate }; // town strings @@ -5077,6 +5078,7 @@ STR16 pBookMarkStrings[] = L"Kerberus", L"Militia Overview", // TODO.Translate L"R.I.S.", + L"Factories", // TODO.Translate }; STR16 pBookmarkTitle[] = @@ -5203,6 +5205,7 @@ STR16 pWebPagesTitles[] = L"Recon Intelligence Services - Information Requests", // TODO.Translate L"Recon Intelligence Services - Information Verification", L"Recon Intelligence Services - About us", + L"Factory Overview", // TODO.Translate L"Bobby Ray : Dernières commandes", L"Encyclopédie", L"Encyclopédie : Données", @@ -7008,6 +7011,7 @@ STR16 gzLaptopHelpText[] = L"Kerberus - Experience In Security", L"Militia Overview", // TODO.Translate L"Recon Intelligence Services", // TODO.Translate + L"Controlled factories", // TODO.Translate }; @@ -11579,4 +11583,16 @@ STR16 szMilitiaText[] = L"Cancel", }; +STR16 szFactoryText[] = // TODO.Translate +{ + L"%s: Production of %s switched off as loyalty is too low.", + L"%s: Production of %s switched off due to insufficient funds.", + L"%s: Production of %s switched off as it requires a merc to staff the facility.", + L"%s: Production of %s switched off due to required items missing.", + L"Item to build", + + L"Preproducts", // 5 + L"h/item", +}; + #endif //FRENCH diff --git a/Utils/_GermanText.cpp b/Utils/_GermanText.cpp index 759f977f..c0bf3cd4 100644 --- a/Utils/_GermanText.cpp +++ b/Utils/_GermanText.cpp @@ -4238,6 +4238,7 @@ STR16 pMapPopUpInventoryText[] = L"Inventar", L"Exit", L"Repair", // TODO.Translate + L"Factories", // TODO.Translate }; // town strings @@ -5021,6 +5022,7 @@ STR16 pBookMarkStrings[] = L"Kerberus", L"Militia Overview", // TODO.Translate L"R.I.S.", + L"Factories", // TODO.Translate }; STR16 pBookmarkTitle[] = @@ -5139,6 +5141,7 @@ STR16 pWebPagesTitles[] = L"Recon Intelligence Services - Information Requests", // TODO.Translate L"Recon Intelligence Services - Information Verification", L"Recon Intelligence Services - About us", + L"Fabriken - Übersicht", L"Bobby Rays - Letzte Lieferungen", L"Enzyklopädie", L"Enzyklopädie - Daten", @@ -6841,6 +6844,7 @@ STR16 gzLaptopHelpText[] = L"Kerberus - Experience In Security", L"Militia Overview", // TODO.Translate L"Recon Intelligence Services", // TODO.Translate + L"Controlled factories", // TODO.Translate }; STR16 gzHelpScreenText[] = @@ -11409,4 +11413,16 @@ STR16 szMilitiaText[] = L"Cancel", }; +STR16 szFactoryText[] = // TODO.Translate +{ + L"%s: Production of %s switched off as loyalty is too low.", + L"%s: Production of %s switched off due to insufficient funds.", + L"%s: Production of %s switched off as it requires a merc to staff the facility.", + L"%s: Production of %s switched off due to required items missing.", + L"Item to build", + + L"Preproducts", // 5 + L"h/item", +}; + #endif //GERMAN diff --git a/Utils/_ItalianText.cpp b/Utils/_ItalianText.cpp index 66c7dd96..495a6b00 100644 --- a/Utils/_ItalianText.cpp +++ b/Utils/_ItalianText.cpp @@ -4233,6 +4233,7 @@ STR16 pMapPopUpInventoryText[] = L"Inventario", L"Uscita", L"Repair", // TODO.Translate + L"Factories", // TODO.Translate }; // town strings @@ -5059,6 +5060,7 @@ STR16 pBookMarkStrings[] = L"Kerberus", L"Militia Overview", // TODO.Translate L"R.I.S.", + L"Factories", // TODO.Translate }; STR16 pBookmarkTitle[] = @@ -5185,6 +5187,7 @@ STR16 pWebPagesTitles[] = L"Recon Intelligence Services - Information Requests", // TODO.Translate L"Recon Intelligence Services - Information Verification", L"Recon Intelligence Services - About us", + L"Factory Overview", // TODO.Translate L"Bobby Ray's - Recent Shipments", L"Encyclopedia", L"Encyclopedia - Data", @@ -6995,6 +6998,7 @@ STR16 gzLaptopHelpText[] = L"Kerberus - Experience In Security", L"Militia Overview", // TODO.Translate L"Recon Intelligence Services", // TODO.Translate + L"Controlled factories", // TODO.Translate }; @@ -11588,4 +11592,16 @@ STR16 szMilitiaText[] = L"Cancel", }; +STR16 szFactoryText[] = // TODO.Translate +{ + L"%s: Production of %s switched off as loyalty is too low.", + L"%s: Production of %s switched off due to insufficient funds.", + L"%s: Production of %s switched off as it requires a merc to staff the facility.", + L"%s: Production of %s switched off due to required items missing.", + L"Item to build", + + L"Preproducts", // 5 + L"h/item", +}; + #endif //ITALIAN diff --git a/Utils/_PolishText.cpp b/Utils/_PolishText.cpp index cbbca7ef..bdb14ee1 100644 --- a/Utils/_PolishText.cpp +++ b/Utils/_PolishText.cpp @@ -4244,6 +4244,7 @@ STR16 pMapPopUpInventoryText[] = L"Inwentarz", L"Zamknij", L"Repair", // TODO.Translate + L"Factories", // TODO.Translate }; // town strings @@ -5074,6 +5075,7 @@ STR16 pBookMarkStrings[] = L"Kerberus", L"Militia Overview", // TODO.Translate L"R.I.S.", + L"Factories", // TODO.Translate }; STR16 pBookmarkTitle[] = @@ -5200,6 +5202,7 @@ STR16 pWebPagesTitles[] = L"Recon Intelligence Services - Information Requests", // TODO.Translate L"Recon Intelligence Services - Information Verification", L"Recon Intelligence Services - About us", + L"Factory Overview", // TODO.Translate L"Bobby Ray's - Ostatnie dostawy", L"Encyclopedia", L"Encyclopedia - Dane", @@ -7009,6 +7012,7 @@ STR16 gzLaptopHelpText[] = L"Kerberus - Experience In Security", L"Militia Overview", // TODO.Translate L"Recon Intelligence Services", // TODO.Translate + L"Controlled factories", // TODO.Translate }; @@ -11601,4 +11605,16 @@ STR16 szMilitiaText[] = L"Cancel", }; +STR16 szFactoryText[] = // TODO.Translate +{ + L"%s: Production of %s switched off as loyalty is too low.", + L"%s: Production of %s switched off due to insufficient funds.", + L"%s: Production of %s switched off as it requires a merc to staff the facility.", + L"%s: Production of %s switched off due to required items missing.", + L"Item to build", + + L"Preproducts", // 5 + L"h/item", +}; + #endif //POLISH diff --git a/Utils/_RussianText.cpp b/Utils/_RussianText.cpp index d2e01b69..fa191c3d 100644 --- a/Utils/_RussianText.cpp +++ b/Utils/_RussianText.cpp @@ -4237,6 +4237,7 @@ STR16 pMapPopUpInventoryText[] = L"Инвентарь", L"Выйти", L"Ремонт", + L"Factories", // TODO.Translate }; // town strings @@ -5065,6 +5066,7 @@ STR16 pBookMarkStrings[] = L"Цербер", L"Ополчение", L"R.I.S.", + L"Factories", // TODO.Translate }; STR16 pBookmarkTitle[] = @@ -5191,6 +5193,7 @@ STR16 pWebPagesTitles[] = L"Recon Intelligence Services - Information Requests", // TODO.Translate L"Recon Intelligence Services - Information Verification", L"Recon Intelligence Services - About us", + L"Factory Overview", // TODO.Translate L"Бобби Рэй - последние поступления", L"Энциклопедия", L"Энциклопедия - данные", @@ -6995,6 +6998,7 @@ STR16 gzLaptopHelpText[] = L"Цербер - Опыт в безопасности", L"Ополчение", L"Recon Intelligence Services", // TODO.Translate + L"Controlled factories", // TODO.Translate }; @@ -11581,4 +11585,16 @@ STR16 szMilitiaText[] = L"Cancel", }; +STR16 szFactoryText[] = // TODO.Translate +{ + L"%s: Production of %s switched off as loyalty is too low.", + L"%s: Production of %s switched off due to insufficient funds.", + L"%s: Production of %s switched off as it requires a merc to staff the facility.", + L"%s: Production of %s switched off due to required items missing.", + L"Item to build", + + L"Preproducts", // 5 + L"h/item", +}; + #endif //RUSSIAN