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
This commit is contained in:
Flugente
2020-05-17 20:52:27 +00:00
parent 4dc40912e4
commit ea1892c788
31 changed files with 1446 additions and 12 deletions
+30
View File
@@ -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<PRODUCTION_LINE_PREPRODUCT> 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<PRODUCTION_LINE> ProductionData;
} FACILITYTYPE;
// HEADROCK HAM 3.5: Maximum number of different facility types
+334
View File
@@ -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<WORLDITEM> 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<WORLDITEM> 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<PRODUCTION_LINE>::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<FACTORY_PREPRODUCT_AVAILABLE> productionstoragedata;
for ( std::vector<PRODUCTION_LINE_PREPRODUCT>::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<FACTORY_PREPRODUCT_AVAILABLE>::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<FACTORY_PREPRODUCT_AVAILABLE>::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
+35
View File
@@ -13408,6 +13408,41 @@ void LuaGetIntelAndQuestMapData( INT32 aLevel )
LuaFunction( _LS.L, "GetIntelAndQuestMapData" ).Param<int>( 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<int>( sSectorX ).Param<int>( sSectorY ).Param<int>( bSectorZ ).Param<int>( usFacilityType ).Param<int>( usProductionNumber ).Param<int>( 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<int>( sSectorX ).Param<int>( sSectorY ).Param<int>( bSectorZ ).Param<int>( usFacilityType ).Param<int>( 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 )
+2
View File
@@ -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
+54 -1
View File
@@ -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<PRODUCTION_LINE>::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 )
+23 -6
View File
@@ -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<PRODUCTION_LINE>::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 )
{
+154 -3
View File
@@ -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 <ubAssignmentType> 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<PRODUCTION_LINE_PREPRODUCT>::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--;
}