mirror of
https://github.com/1dot13/source.git
synced 2026-09-02 14:36:06 +02:00
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:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 )
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 )
|
||||
|
||||
@@ -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 )
|
||||
{
|
||||
|
||||
@@ -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--;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user