Improve loading speed of stash (by Moa)

- improved processing of sector stash (opening/closing)
- improved loading speed of save games
- improved processing of items droped by militia (most noteable after autoresolve)
- and some other code related changes
see: http://www.ja-galaxy-forum.com/board/ubbthreads.php/topics/325332/FIX_improve_loading_speed_of_s.html#Post325332

Notes:
removed some functions, still in code so but renamed to *_OLD() because they are from Sirtech and should be kept as I have read in "§18) If possible, we don't just delete the old code, but comment it out (or #ifdef it out) for reference. We delete it only if it's really necessary."

git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@6434 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
Wanne
2013-09-23 06:59:29 +00:00
parent 78b4e784b6
commit 5df38d5042
10 changed files with 494 additions and 28 deletions
+1 -1
View File
@@ -470,7 +470,7 @@ typedef struct SECTORINFO
// Replacing these variables with the ones above. They really are unused.
//UINT16 usUNUSEDMilitiaLevels; // unused (ARM)
//UINT8 ubUNUSEDNumberOfJoeBlowCivilians; // unused (ARM)
UINT32 uiTimeCurrentSectorWasLastLoaded; //Specifies the last time the player was in the sector
UINT32 uiTimeCurrentSectorWasLastLoaded; //in game minutes, Specifies the last time the player was in the sector.
UINT8 ubUNUSEDNumberOfEnemiesThoughtToBeHere; // using bLastKnownEnemies instead
UINT32 uiTimeLastPlayerLiberated; //in game seconds (used to prevent the queen from attacking for awhile)
+1 -1
View File
@@ -307,7 +307,7 @@ void RenderMapScreenInterfaceBottom( BOOLEAN fForceMapscreenFullRender )
// HEADROCK Changed this line to accept outside influence through the new boolean:
//if ( fForceMapscreenFullRender == TRUE || fMapScreenBottomDirty == TRUE)
// HEADROCK HAM 3.6: OK, let's always render this panel, as long as the team inventory screen isn't open.
if ( fMapScreenBottomDirty || !fShowInventoryFlag )
if ( fMapScreenBottomDirty || (!fShowInventoryFlag && fForceMapscreenFullRender))
{
// get and blt panel
GetVideoObject(&hHandle, guiMAPBOTTOMPANEL );
+432 -10
View File
@@ -31,6 +31,7 @@
#include "interface panels.h"
#include "wordwrap.h"
#include "Soldier macros.h"
#include "rt time defines.h"
#endif
#include "ShopKeeper Interface.h"
@@ -798,11 +799,17 @@ void CreateDestroyMapInventoryPoolButtons( BOOLEAN fExitFromMapScreen )
// Flugente: certain features need to alter an item's temperature value depending on the time passed
// if we do these functions here and adjust for the time passed since this sector was loaded last, it will seem to the player
// as if these checks are always performed in any sector
SectorInventoryCooldownFunctions(sSelMapX, sSelMapY, ( INT16 )( iCurrentMapSectorZ ));
//Moa: removed this function and replaced by HandleSectorCooldownFunctions() below
//SectorInventoryCooldownFunctions(sSelMapX, sSelMapY, ( INT16 )( iCurrentMapSectorZ ));
// build stash
BuildStashForSelectedSector( sSelMapX, sSelMapY, ( INT16 )( iCurrentMapSectorZ ) );
//Moa: added the handling function instead of SectorInventoryCooldown, which has loaded the items from the tempfile (loading also done in BuildStashForSelectedSector)
HandleSectorCooldownFunctions( sSelMapX, sSelMapY, (INT8)iCurrentMapSectorZ, (WORLDITEM*) &(*pInventoryPoolList.begin()) , pInventoryPoolList.size(), TRUE );
//SetLastTimePlayerWasInSector( sSelMapX, sSelMapY, (INT8)iCurrentMapSectorZ );
//SaveWorldItemsToTempItemFile( sSelMapX, sSelMapY, (INT8)iCurrentMapSectorZ, pInventoryPoolList.size(), (WORLDITEM*) &(*pInventoryPoolList.begin()) );
// HEADROCK HAM 5: Reset all BigItem image numbers, just in case.
ResetAllMapInventoryBigItemGraphics();
@@ -852,6 +859,9 @@ void CreateDestroyMapInventoryPoolButtons( BOOLEAN fExitFromMapScreen )
// clear up unseen list
ClearUpTempUnSeenList( );
// undo item decay (will be saved once and only when entering sector)
HandleSectorCooldownFunctions( sSelMapX, sSelMapY, (INT8)iCurrentMapSectorZ, (WORLDITEM*) &(*pInventoryPoolList.begin()) , pInventoryPoolList.size(), TRUE , TRUE);
// now save results
SaveSeenAndUnseenItems( );
@@ -912,7 +922,98 @@ void ClearUpTempUnSeenList( void )
return;
}
//////////////////////////////////////
//@brief Saves pSaveList and pInventoryPoolList either into file or into memmory.
// Takes any existing items from pInventoryPoolList and all items from pSaveList to save same into
// file if map is not loaded or memmory if the map is loaded. Make sure to remove all filters before
// calling this function!
//
// Globals which get modified:
// WORLDITEM* pSaveList ...If successfull pSaveList gets cleared
// UINT32 uiNumberOfUnSeenItems ...and uiNumberOfUnSeenItems set to 0.
//
// Globals used to save the list:
// INT16 gWorldSectorX,gWorldSectorY
// INT8 gWorldSectorZ ...Current loaded sector.
// INT32 sSelMapX, sSelMapY
// INT32 iCurrentMapSectorZ ...Current selected sector.
// std::vector<WORLDITEM> pInventoryPoolList ...The stash of unfiltered Items.
// Notes:
// The original function had set the visible and exist flag for every worlditem which had existing objects,
// also it has set the WORLD_ITEM_GRIDNO_NOT_SET_USE_ENTRY_POINT using TileIsOutOfBounds() but this is not
// possible since we dont know the boundaries of a unloaded sector, occationally some data got lost. For
// loaded maps this check was not performed...
// In case this function should mimic the old behavier activate the preprocessor instruction(s), in this case
// those checks ARE performed for loaded maps.
//@auth SirTech
//@auth (merged into single loop by Moa)
//////////////////////////////////////
void SaveSeenAndUnseenItems( void )
{
std::vector<WORLDITEM> worldItemsSaveList; //exists() on front and exists() && visible != 0 on back.
UINT32 iExistingItems = 0; //fExists
//build save list and add flag WORLD_ITEM_GRIDNO_NOT_SET_USE_ENTRY_POINT if required.
worldItemsSaveList.reserve( pInventoryPoolList.size() + uiNumberOfUnSeenItems );
if ( worldItemsSaveList.capacity() == 0 ) //nothing to do anyways so get out of here
return;
//make list of seen items
for ( UINT32 i = 0; i < pInventoryPoolList.size(); i++ )
{
#if 0
if ( pInventoryPoolList[ i ].object.exists() )
{
pInventoryPoolList[ i ].fExists = TRUE;
pInventoryPoolList[ i ].bVisible = TRUE;
//Check
if(TileIsOutOfBounds( pInventoryPoolList[ i ].sGridNo) && !( pInventoryPoolList[ i ].usFlags & WORLD_ITEM_GRIDNO_NOT_SET_USE_ENTRY_POINT ) )
{
pInventoryPoolList[ i ].usFlags |= WORLD_ITEM_GRIDNO_NOT_SET_USE_ENTRY_POINT;
// Display warning.....
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_BETAVERSION, L"Error: Trying to add item ( %d: %s ) to invalid gridno in unloaded sector. Please Report.", pInventoryPoolList[ i ].object.usItem, ItemNames[ pInventoryPoolList[ i ].object.usItem] );
}
#else
if ( pInventoryPoolList[i].fExists )
{
#endif
worldItemsSaveList.push_back(pInventoryPoolList[i]);
iExistingItems++;
}
}
//check whether memmory (loaded map) or file is used to save the items
if( ( gWorldSectorX == sSelMapX ) && ( gWorldSectorY == sSelMapY ) && ( gbWorldSectorZ == ( INT8 ) ( iCurrentMapSectorZ ) ) )
{
//handle in existing function
ReBuildWorldItemStashForLoadedSector( iExistingItems, uiNumberOfUnSeenItems, &(*worldItemsSaveList.begin()), pSaveList );
}
else
{
//copy remaining unseen items into savelist
if ( uiNumberOfUnSeenItems > 0 && pSaveList != NULL)
worldItemsSaveList.insert( worldItemsSaveList.end(), pSaveList, pSaveList + uiNumberOfUnSeenItems );
//save the items to file (skipping all checks of AddWorldItemsToUnLoadedSector(), allready done here!, also we do not delete the file before we overwrite)
if ( !SaveWorldItemsToTempItemFile( sSelMapX, sSelMapY, ( INT8 ) iCurrentMapSectorZ, uiNumberOfUnSeenItems + iExistingItems, &(*worldItemsSaveList.begin()) ) )
{
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_BETAVERSION, L"Error: Could not save %d seen and %d unseen items to disc! Please Report.", iExistingItems, uiNumberOfUnSeenItems );
return;
}
}
uiNumberOfUnSeenItems = 0;
if( pSaveList != NULL )
{
delete[] ( pSaveList );
pSaveList = NULL;
}
}
//original Sirtech function, modified once in rev1325
void SaveSeenAndUnseenItems_OLD( void )
{
WORLDITEM *pSeenItemsList = NULL;
UINT32 iCounter = 0;
@@ -1466,7 +1567,7 @@ void MapInvenPoolSlots(MOUSE_REGION * pRegion, INT32 iReason )
BeginInventoryPoolPtr( &( pInventoryPoolList[ ( iCurrentInventoryPoolPage * MAP_INVENTORY_POOL_SLOT_COUNT ) + iCounter ].object ) );
}
else
{
{//we have an item on cursor
// if in battle inform player they will have to do this in tactical
// if( ( gTacticalStatus.fEnemyInSector ) ||( ( sSelMapX == gWorldSectorX ) && ( sSelMapY == gWorldSectorY ) && ( iCurrentMapSectorZ == gbWorldSectorZ ) && ( gTacticalStatus.uiFlags & INCOMBAT ) ) )
@@ -1814,8 +1915,8 @@ void DestroyMapInventoryButtons( void )
return;
}
void BuildStashForSelectedSector( INT16 sMapX, INT16 sMapY, INT16 sMapZ )
INT32 GetSizeOfStashInSector_OLD( INT16 sMapX, INT16 sMapY, INT16 sMapZ, BOOLEAN fCountStacksAsOne );
void BuildStashForSelectedSector_OLD( INT16 sMapX, INT16 sMapY, INT16 sMapZ )
{
INT32 iSize = 0;
UINT32 uiItemCount = 0;
@@ -1829,7 +1930,7 @@ void BuildStashForSelectedSector( INT16 sMapX, INT16 sMapY, INT16 sMapZ )
// #endif
// get size of the current stash in sector (count stacks as one item)
iSize = GetSizeOfStashInSector( sMapX, sMapY, sMapZ, TRUE );
iSize = GetSizeOfStashInSector_OLD( sMapX, sMapY, sMapZ, TRUE );
// round off .. we want at least 1 free page of space...
iSize = ((iSize / MAP_INVENTORY_POOL_SLOT_COUNT) + 1) * MAP_INVENTORY_POOL_SLOT_COUNT;
@@ -1982,6 +2083,219 @@ void BuildStashForSelectedSector( INT16 sMapX, INT16 sMapY, INT16 sMapZ )
SortSectorInventory( pInventoryPoolList, uiTotalNumberOfSeenItems );
}
////////////////////////////
// @brief: Creates filtered and unfiltered lists for stash and stores them in global variables.
//
// If loaded sector matches the parameter sector globals are used to build the stash, otherwise the items are read from temp file (if any)
// Globals used to build the stash
// INT32 MAP_INVENTORY_POOL_SLOT_COUNT ...Number of Slots per page.
// INT16 gWorldSectorX,gWorldSectorY
// INT8 gWorldSectorZ ...Current loaded sector.
// UINT32 guiNumWorldItems ...Number of itemsstacks in the loaded sector.
// WORLDITEM * gWorldItems ...Global dynamic array of itemstacks in the loaded sector.
//
// Globals used to save the lists:
// INT32 iLastInventoryPoolPage ...page index where still one item is displayed (0..)
// std::vector<WORLDITEM> pInventoryPoolList ...Stores unfiltered items and itemstacks of the sector (only items that return TRUE for @see IsMapScreenWorldItemVisibleInMapInventory() ) vector.size() is 1 + a multiple of MAP_INVENTORY_POOL_SLOT_COUNT.
// UINT32 uiNumberOfUnSeenItems ...Number of filtered items in that sector (only items that exist and return TRUE for @see IsMapScreenWorldItemInvisibleInMapInventory() ).
// WORLDITEM *pUnSeenItems ...Stores filtered items in that sector
//
// @calls CheckGridNoOfItemsInMapScreenMapInventory(), SortSectorInventory()
// @Todo: remove CheckGridNoOfItemsInMapScreenMapInventory() by identifying the root cause of the missing flag
//@auth SirTech, ChrisL
//@auth (merged into single loop by Moa)
////////////////////////////
void BuildStashForSelectedSector( INT16 sMapX, INT16 sMapY, INT16 sMapZ )
{
UINT32 fNumTotal = 0, fNumShown = 0, fNumFiltered = 0, fNumFlagsSet = 0; //itemstack count
std::vector<WORLDITEM> fFilteredItems; //store filtered items to be converted later to an array.
std::vector<WORLDITEM> fWorldItems; //store everything here what we can get (WORLDITEM.fExists == TRUE)
// pInventoryPoolList //store unfiltered items directly into the global
// if map is allready loaded use gWorldItems[] and guiNumWorldItems to build lists
if( ( sMapX == gWorldSectorX )&&( gWorldSectorY == sMapY ) &&(gbWorldSectorZ == sMapZ ) )
{
// approximate capacitiy
fFilteredItems.reserve( 50 ); //since we are building the stash from blank, there is probably no filter set and only few items get into fFilteredItems
fWorldItems.reserve(guiNumWorldItems);
// start with empty list (global)
pInventoryPoolList.clear( );
pInventoryPoolList.reserve( MAP_INVENTORY_POOL_SLOT_COUNT * ( 1 + (guiNumWorldItems/MAP_INVENTORY_POOL_SLOT_COUNT) ) );
// sector loaded, just copy from list
for( UINT32 i = 0; i < guiNumWorldItems; i++ )
{
if( IsMapScreenWorldItemVisibleInMapInventory( &gWorldItems[ i ] ) )
{
if( ( gWorldItems[i].object.exists() == true ) && ( TileIsOutOfBounds(gWorldItems[ i ].sGridNo) ) && !( gWorldItems[ i ].usFlags & WORLD_ITEM_GRIDNO_NOT_SET_USE_ENTRY_POINT ) )
{
//set the flag
#ifndef _DEBUG
pInventoryPoolList[ i ].usFlags |= WORLD_ITEM_GRIDNO_NOT_SET_USE_ENTRY_POINT;
#endif
fNumFlagsSet++;
}
// unfiltered? add to visible and total list
pInventoryPoolList.push_back( gWorldItems[ i ] );
fWorldItems.push_back( gWorldItems[ i ] );
fNumShown++;
}
else if ( IsMapScreenWorldItemInvisibleInMapInventory( &gWorldItems[ i ] ) )
{
if( ( gWorldItems[i].object.exists() == true ) && ( TileIsOutOfBounds(gWorldItems[ i ].sGridNo) ) && !( gWorldItems[ i ].usFlags & WORLD_ITEM_GRIDNO_NOT_SET_USE_ENTRY_POINT ) )
{
//set the flag
#ifndef _DEBUG
gWorldItems[ i ].usFlags |= WORLD_ITEM_GRIDNO_NOT_SET_USE_ENTRY_POINT;
#endif
fNumFlagsSet++;
}
// filtered? add to invisible and total list
fFilteredItems.push_back( gWorldItems[ i ] );
fWorldItems.push_back( gWorldItems[ i ] );
}
else if ( gWorldItems[ i ].fExists )
{
// dont skip it, we reuse this loop to create a complete list of all items
fWorldItems.push_back( gWorldItems[ i ] );
#ifdef _DEBUG
//ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_BETAVERSION, L"The %d item in the list is hidden or does not exist.", i );
#endif
}
}
// update countings
fNumTotal = fWorldItems.size();
fNumFiltered = fFilteredItems.size();
fNumShown = pInventoryPoolList.size();
// double check if counting was correct
#ifdef JA2BETAVERSION
AssertGE( guiNumWorldItems, fNumTotal );
AssertGE( fNumTotal, fNumFiltered + fNumShown );
#endif
}
else
{ // if map not loaded, use tempfile to build lists
BOOLEAN error;
// get total number of itemstacks from temp file...
error = GetNumberOfWorldItemsFromTempItemFile( sMapX, sMapY, ( INT8 )( sMapZ ), &( fNumTotal ), FALSE );
Assert( error );
// ...and use this number to allocate space
fFilteredItems.reserve( 50 ); //since we are building the stash from blank, there is probably no filter set and only few items get into fFilteredItems, was 8 changed to 50 because of bobby ray
//initialize at least one element to avoid null dereference of iterator
fWorldItems.resize(fNumTotal+1);
// start with empty list (global)
pInventoryPoolList.reserve( MAP_INVENTORY_POOL_SLOT_COUNT * ( 1 + (fNumTotal/MAP_INVENTORY_POOL_SLOT_COUNT) ) );
pInventoryPoolList.clear( );
// load items into fWorldItems vector
if ( !LoadWorldItemsFromTempItemFile( sMapX, sMapY, (INT8) sMapZ, &(*fWorldItems.begin()) ) )
{
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("LoadWorldItemsFromTempItemFile: failed in BuildStashForSelectedSector()" ) );
return;
}
// was temporay used to get #items in file, now count what actually is added
fNumTotal = 0;
// now run through list and copy reference
for(UINT32 i = 0; i < fWorldItems.size(); i++ )
{
// TEST!! If the item exists, and is NOT VALID, report it
if( fWorldItems[i].fExists && fWorldItems[ i ].object.usItem > MAXITEMS )
{
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_BETAVERSION, L"The %d item in the list is NOT valid (ID%d). Please send save. DF 1.", i, fWorldItems[i].object.usItem );
}
if( IsMapScreenWorldItemVisibleInMapInventory( &fWorldItems[ i ] ) )
{
if( ( fWorldItems[i].object.exists() == true ) && ( TileIsOutOfBounds(fWorldItems[ i ].sGridNo) ) && !( fWorldItems[ i ].usFlags & WORLD_ITEM_GRIDNO_NOT_SET_USE_ENTRY_POINT ) )
{
//set the flag
#ifndef _DEBUG
fWorldItems[ i ].usFlags |= WORLD_ITEM_GRIDNO_NOT_SET_USE_ENTRY_POINT;
#endif
fNumFlagsSet++;
}
// unfiltered? add to visible
pInventoryPoolList.push_back( fWorldItems[i] );
fNumTotal++;
}
else if ( IsMapScreenWorldItemInvisibleInMapInventory( &fWorldItems[ i ] ) )
{
if( ( fWorldItems[i].object.exists() == true ) && ( TileIsOutOfBounds(fWorldItems[ i ].sGridNo) ) && !( fWorldItems[ i ].usFlags & WORLD_ITEM_GRIDNO_NOT_SET_USE_ENTRY_POINT ) )
{
//set the flag
#ifndef _DEBUG
fWorldItems[ i ].usFlags |= WORLD_ITEM_GRIDNO_NOT_SET_USE_ENTRY_POINT;
#endif
fNumFlagsSet++;
}
// filtered? add to invisible and total list
fFilteredItems.push_back( fWorldItems[ i ] );
fNumTotal++;
}
else if ( fWorldItems[ i ].fExists )
{
// dont skip it, we reuse this loop to create a complete list of existing items
fNumTotal++;
#ifdef _DEBUG
//ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_BETAVERSION, L"The %d item in the list does not exist.", i );
#endif
}
}
// update countings
//fNumTotal = fWorldItems.size();
fNumFiltered = fFilteredItems.size();
fNumShown = pInventoryPoolList.size();
// double check if counting was correct
#ifdef JA2BETAVERSION
AssertGE( fNumTotal, fNumFiltered + fNumShown );
AssertGE( fWorldItems.size(), fNumTotal );
#endif
}// done with lists...
// ... set globals: set index for last page ...
iLastInventoryPoolPage = (INT32)(fNumShown / MAP_INVENTORY_POOL_SLOT_COUNT);
uiNumberOfUnSeenItems = fNumFiltered;
// to copy fFilteredItems (vector) to global (array)
if (uiNumberOfUnSeenItems > 0)
{
pUnSeenItems = new WORLDITEM[uiNumberOfUnSeenItems];//gets passed to pSaveList in ClearUpTempUnSeenList() and deleted by SaveSeenAndUnseenItems()
std::copy(fFilteredItems.begin(), fFilteredItems.end(), pUnSeenItems );
}
//resize globallist to a multiple of MAP_INVENTORY_POOL_SLOT_COUNT + one element (some other code does expect that)
pInventoryPoolList.resize(MAP_INVENTORY_POOL_SLOT_COUNT * (iLastInventoryPoolPage+1) );
// Report corrected flags / missing flags
if( fNumFlagsSet > 0 )
{
#ifndef _DEBUG
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_BETAVERSION, L"Item with invalid gridno doesnt have flag set:# %d, this was corrected.", fNumFlagsSet );
#else
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_BETAVERSION, L"Item with invalid gridno doesnt have flag set:# %d, this was not corrected! Figure out why.", fNumFlagsSet );
#endif
}
//Sort the sector inventory
SortSectorInventory( pInventoryPoolList, fNumShown );
}
void ReBuildWorldItemStashForLoadedSector( INT32 iNumberSeenItems, INT32 iNumberUnSeenItems, WORLDITEM *pSeenItemsList, WORLDITEM *pUnSeenItemsList )
{
INT32 iTotalNumberOfItems = 0;
@@ -2048,8 +2362,8 @@ void DestroyStash( void )
pInventoryPoolList.clear();
}
INT32 GetSizeOfStashInSector( INT16 sMapX, INT16 sMapY, INT16 sMapZ, BOOLEAN fCountStacksAsOne )
//Moa: merged into BuildStashForSelectedSector
INT32 GetSizeOfStashInSector_OLD( INT16 sMapX, INT16 sMapY, INT16 sMapZ, BOOLEAN fCountStacksAsOne )
{
// get # of items in sector that are visible to the player
UINT32 uiTotalNumberOfItems = 0, uiTotalNumberOfRealItems = 0;
@@ -5223,8 +5537,9 @@ void HandleSetFilterButtons()
}
}
//Moa:moved code to CreateDestroyMapInventoryPoolButtons() and EnterSector() to decrease loading time
// Flugente: handle various cooldown functions in a sector
void SectorInventoryCooldownFunctions( INT16 sMapX, INT16 sMapY, INT16 sMapZ )
/*void SectorInventoryCooldownFunctions( INT16 sMapX, INT16 sMapY, INT16 sMapZ )
{
UINT32 uiTotalNumberOfRealItems = 0;
WORLDITEM * pTotalSectorList = NULL;
@@ -5270,12 +5585,114 @@ void SectorInventoryCooldownFunctions( INT16 sMapX, INT16 sMapY, INT16 sMapZ )
//Save the Items to the the file
SaveWorldItemsToTempItemFile( sMapX, sMapY, (INT8)sMapZ, uiTotalNumberOfRealItems, pTotalSectorList );
}*/
// @brief modifies data of items including, but not limited to: bDirtLevel, bTemperature (food/weapon overheat)
// Uses various external parameters set in ini file(s) labeled under [Tactical Weapon Overheating Settings], [Tactical Food Settings], [Strategic Gameplay Settings](advanced repair/dirt system)
// to calculate a delta decay and adds it to the itemStack.data
// It is assumed that the itemStack consists of the same usItem.
// Items can not have negative dirt and temperature (0 is used instead).
// @param itemstack: A single item or a itemsstack which will be decayed (dirt, temperature) depending on ini settings.
// @param seconds: Time passed in seconds for which the delta decay is calculated and added to the items in itemstack. Can handle up to +-2147483647/(60*60*24*365) ~ 68 years. This means you can pass in positive seconds to decay the items and negative seconds to undecay them.
// @param naturalDirt: Dirt of the sector, if omitted default = 100 is used.
// @param isUnderground: flag to reduce food decay in underground sectors to 80%, if omitted default = FALSE is used.
// @auth origninal code by flugente
// @auth Moa
void HandleItemCooldownFunctions( OBJECTTYPE* itemStack, INT32 deltaSeconds, UINT16 naturalDirt, BOOLEAN isUnderground )
{
INT32 tickspassed = deltaSeconds / NUM_SEC_PER_TACTICAL_TURN;//1 tick is 5 seconds
if ( tickspassed == 0 || !itemStack->exists() ||
!( gGameExternalOptions.fWeaponOverheating || gGameExternalOptions.fDirtSystem || gGameOptions.fFoodSystem ) )
return;
//original code by flugente, renamed variables to fit here, removed "min (OVERHEATING_MAX_TEMPERATURE, newValue)" for dirt to allow to go beyond maximum and deduct later the same amount if neccessary.
// ... if we use overheating and item is a gun, a launcher or a barrel ...
if ( gGameExternalOptions.fWeaponOverheating && ( Item[itemStack->usItem].usItemClass & (IC_GUN|IC_LAUNCHER) || Item[itemStack->usItem].barrel == TRUE ) )
{
for(INT16 i = 0; i < itemStack->ubNumberOfObjects; ++i) // ... there might be multiple items here (item stack), so for each one ...
{
FLOAT guntemperature = (*itemStack)[i]->data.bTemperature; // ... get temperature ...
FLOAT cooldownfactor = GetItemCooldownFactor(itemStack); // ... get item cooldown factor provided of attachments ...
if ( Item[itemStack->usItem].barrel == TRUE ) // ... a barrel lying around cools down a bit faster ...
cooldownfactor *= gGameExternalOptions.iCooldownModificatorLonelyBarrel;
FLOAT newguntemperature = max(0.0f, guntemperature - tickspassed * cooldownfactor ); // ... calculate new temperature ...
#if 0//def JA2TESTVERSION
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"World: Item temperature lowered from %4.2f to %4.2f", guntemperature, newguntemperature );
#endif
(*itemStack)[i]->data.bTemperature = newguntemperature; // ... set new temperature
// for every objects, we also have to check wether there are weapon attachments (eg. underbarrel weapons), and cool them down too
attachmentList::iterator iterend = (*itemStack)[i]->attachments.end();
for (attachmentList::iterator iter = (*itemStack)[i]->attachments.begin(); iter != iterend; ++iter)
{
if ( iter->exists() && Item[ iter->usItem ].usItemClass & (IC_GUN|IC_LAUNCHER) )
{
FLOAT temperature = (*iter)[i]->data.bTemperature; // ... get temperature of item ...
FLOAT cooldownfactor = GetItemCooldownFactor( &(*iter) ); // ... get cooldown factor ...
FLOAT newtemperature = max(0.0f, temperature - tickspassed * cooldownfactor ); // ... calculate new temperature ...
(*iter)[i]->data.bTemperature = newtemperature; // ... set new temperature
#if 0//def JA2TESTVERSION
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"World: Item temperature lowered from %4.2f to %4.2f", temperature, newtemperature );
#endif
// we assume that there can exist only 1 underbarrel weapon per gun
break;
}
}
}
}//end overheating
// ... if it is a weapon or armor and dirt system is active ...
if ( gGameExternalOptions.fDirtSystem && ( (Item[ itemStack->usItem ].usItemClass & IC_WEAPON) || (Item[ itemStack->usItem ].usItemClass & IC_ARMOUR) ) )
{
FLOAT dirtincreasefactor = GetItemDirtIncreaseFactor( itemStack, FALSE ); // ... get dirt increase factor ...
// the current sector determines how much dirt increases
dirtincreasefactor *= (naturalDirt)/100;
dirtincreasefactor /= gGameExternalOptions.usSectorDirtDivider;
if ( dirtincreasefactor > 0.0f ) // ... item can get dirtier ...
{
for( INT16 i = 0; i < itemStack->ubNumberOfObjects; ++i ) // ... there might be multiple items here (item stack), so for each one ...
{
(*itemStack)[i]->data.bDirtLevel = max(0.0f, (*itemStack)[i]->data.bDirtLevel + tickspassed * dirtincreasefactor ); // set new dirt value
}
}
}//end dirt stuff
// ... if it is food and the food system is active ...
if ( gGameOptions.fFoodSystem && Item[ itemStack->usItem ].foodtype > 0 )
{
if ( Food[ Item[ itemStack->usItem ].foodtype ].usDecayRate > 0.0f ) // ... if the food can decay...
{
// if in undergound sector the food will decay less
FLOAT sectorModifier = gGameExternalOptions.sFoodDecayModificator * ( isUnderground? 0.8f : 1.0f );
for( INT16 i = 0; i < itemStack->ubNumberOfObjects; ++i ) // ... there might be multiple items here (item stack), so for each one ...
{
(*itemStack)[i]->data.bTemperature = max( 0.0f, (*itemStack)[i]->data.bTemperature - tickspassed * sectorModifier * Food[ Item[ itemStack->usItem ].foodtype ].usDecayRate ); // set new temperature
}
}
}//end food
}
// Flugente: handle various cooldwon functions over an array of items in a specific sector.
// Flugente: handle various cooldown functions over an array of items in a specific sector.
// if fWithMinutes = true, adjust cooldown for time since sector was last entered
// otherwise its used for a turn-precise cooldown
void HandleSectorCooldownFunctions( INT16 sMapX, INT16 sMapY, INT8 sMapZ, WORLDITEM* pWorldItem, UINT32 size, BOOLEAN fWithMinutes )
//Moa: code inside pWorldItem loop moved to HandleItemCooldownFunctions, added optional fUndo flag to undecay items (default = FALSE)
void HandleSectorCooldownFunctions( INT16 sMapX, INT16 sMapY, INT8 sMapZ, WORLDITEM* pWorldItem, UINT32 size, BOOLEAN fWithMinutes, BOOLEAN fUndo )
{
// if not using overheating or food system, no point in all this
if ( !gGameExternalOptions.fWeaponOverheating && !gGameExternalOptions.fDirtSystem && !gGameOptions.fFoodSystem )
@@ -5318,6 +5735,10 @@ void HandleSectorCooldownFunctions( INT16 sMapX, INT16 sMapY, INT8 sMapZ, WORLDI
for( UINT32 uiCount = 0; uiCount < size; ++uiCount ) // ... for all items in the world ...
{
HandleItemCooldownFunctions( &(pWorldItem[ uiCount ].object), tickspassed * ( fUndo ? -NUM_SEC_PER_TACTICAL_TURN : NUM_SEC_PER_TACTICAL_TURN ), sectormod, (sMapZ > 0) );
//moved to HandleItemCooldownFunctions to reuse those calculations (see SOLDIERTYPE::SoldierInventoryCoolDown())
/*
if( pWorldItem[ uiCount ].fExists ) // ... if item exists ...
{
OBJECTTYPE* pObj = &(pWorldItem[ uiCount ].object); // ... get pointer for this item ...
@@ -5399,5 +5820,6 @@ void HandleSectorCooldownFunctions( INT16 sMapX, INT16 sMapY, INT8 sMapZ, WORLDI
}
}
}
*/
}
}
@@ -39,8 +39,6 @@ void CreateDestroyMapInventoryPoolButtons( BOOLEAN fExitFromMapScreen );
// bail out of sector inventory mode if it is on
void CancelSectorInventoryDisplayIfOn( BOOLEAN fExitFromMapScreen );
INT32 GetSizeOfStashInSector( INT16 sMapX, INT16 sMapY, INT16 sMapZ, BOOLEAN fCountStacksAsOne );
// get total number of items in sector
INT32 GetTotalNumberOfItems( void );
@@ -81,9 +79,10 @@ BOOLEAN SwitchToInventoryPoolQ(UINT8 newidx);
#endif
// Flugente: handle various cooldown functions in a sector
void SectorInventoryCooldownFunctions( INT16 sMapX, INT16 sMapY, INT16 sMapZ );
//void SectorInventoryCooldownFunctions( INT16 sMapX, INT16 sMapY, INT16 sMapZ );
// Flugente: handle various cooldown functions over an array of items in a specific sector.
// if fWithMinutes = true, adjust cooldown for time since sector was last entered
// otherwise its used for a turn-precise cooldown
void HandleSectorCooldownFunctions( INT16 sMapX, INT16 sMapY, INT8 sMapZ, WORLDITEM* pWorldItem, UINT32 size, BOOLEAN fWithMinutes );
void HandleSectorCooldownFunctions( INT16 sMapX, INT16 sMapY, INT8 sMapZ, WORLDITEM* pWorldItem, UINT32 size, BOOLEAN fWithMinutes, BOOLEAN fUndo = FALSE);
void HandleItemCooldownFunctions( OBJECTTYPE* itemStack, INT32 deltaSeconds, UINT16 naturalDirt = 100, BOOLEAN isUnderground = FALSE);
+1 -1
View File
@@ -21,7 +21,7 @@
#include "assignments.h"
#endif
#define NUM_SEC_PER_STRATEGIC_TURN ( NUM_SEC_IN_MIN * 15 ) // Every fifteen minutes
UINT32 guiLastStrategicTime = 0;
+15 -1
View File
@@ -2885,6 +2885,10 @@ SOLDIERTYPE *pSoldier=NULL;
#endif
}
extern void SetLastTimePlayerWasInSector();
//Moa: 09/14/2013 this function modifies uiTimeCurrentSectorWasLastLoaded and the various decay of items in that sector as well
// @calls HandleSectorCooldownFunctions
// @calls SetLastTimePlayerWasInSector
BOOLEAN EnterSector( INT16 sSectorX, INT16 sSectorY , INT8 bSectorZ )
{
INT32 i;
@@ -3017,7 +3021,17 @@ BOOLEAN EnterSector( INT16 sSectorX, INT16 sSectorY , INT8 bSectorZ )
// Flugente: certain features need to alter an item's temperature value depending on the time passed
// if we do these functions here and adjust for the time passed since this sector was loaded last, it will seem to the player
// as if these checks are always performed in any sector
SectorInventoryCooldownFunctions(sSectorX, sSectorY, bSectorZ);
//Moa: removed this function and replaced by the handling function.
//SectorInventoryCooldownFunctions(sSectorX, sSectorY, bSectorZ);
//moved from SectorInventoryCooldownFunctions. Invisible items are handled as well.
//Since we have allready loaded the items previously we can use the globals here.
HandleSectorCooldownFunctions( sSectorX, sSectorY, (INT8)bSectorZ, gWorldItems, guiNumWorldItems, TRUE );
//Update LastTimePlayerWasInSector
SetLastTimePlayerWasInSector();
//Save to tempfile
SaveWorldItemsToTempItemFile( sSectorX, sSectorY, (INT8)bSectorZ, guiNumWorldItems, gWorldItems );
return TRUE; //because the map was loaded.
}
+12
View File
@@ -13807,6 +13807,7 @@ BOOLEAN SOLDIERTYPE::SoldierCarriesTwoHandedWeapon( void )
return( FALSE );
}
extern void HandleItemCooldownFunctions( OBJECTTYPE* itemStack, INT32 deltaSeconds, UINT16 naturalDirt = 100, BOOLEAN isUnderground = TRUE );
// Flugente: Cool down/decay all items in inventory
void SOLDIERTYPE::SoldierInventoryCoolDown(void)
{
@@ -13865,6 +13866,16 @@ void SOLDIERTYPE::SoldierInventoryCoolDown(void)
if ( !gGameExternalOptions.fWeaponOverheating && !gGameExternalOptions.fDirtSystem && !gGameOptions.fFoodSystem )
return;
#if TRUE //start reusing existing code from HandleItemCooldownFunctions, set to FALSE if original code should be used
INT8 numStacks = (INT8)this->inv.size(); // remember inventorysize, so we don't call size() repeatedly
extern UINT32 guiLastTacticalRealTime, guiLastStrategicTime;
UINT32 secondsPassed = 5;//GetJA2Clock() > guiLastTacticalRealTime? (GetJA2Clock() - guiLastTacticalRealTime)/1000 : 0;
for ( INT8 bLoop = 0; bLoop < numStacks; ++bLoop) // ... for all items in our inventory ...
{
HandleItemCooldownFunctions( &(this->inv[bLoop]), secondsPassed );
}
#else //start using original redundant code
// one hour has 60 minutes, with 12 5-second-intervals (cooldown values are based on 5-second values)
FLOAT fooddecaymod = gGameExternalOptions.sFoodDecayModificator;
@@ -13966,6 +13977,7 @@ void SOLDIERTYPE::SoldierInventoryCoolDown(void)
}
}
}
#endif //end using original code
}
// Flugente: determine if we can rest our weapon on something. This can only happen when STANDING/CROUCHED. As a result, we get superior handling modifiers (we apply the PRONE modfiers)
+17 -9
View File
@@ -820,7 +820,12 @@ BOOLEAN AddItemsToUnLoadedSector( INT16 sMapX, INT16 sMapY, INT8 bMapZ, INT32 sG
WORLDITEM *pWorldItems;
UINT32 cnt;
UINT32 uiLoop1=0;
if ( uiNumberOfItemsToAdd == 0 && fReplaceEntireFile == FALSE )
{
//Moa: nothing to do, so get out of here!
return( TRUE );
}
if( !GetNumberOfWorldItemsFromTempItemFile( sMapX, sMapY, bMapZ, &uiNumberOfItems, TRUE ) )
{
@@ -3364,26 +3369,28 @@ void SetNumberOfVisibleWorldItemsInSectorStructureForSector( INT16 sMapX, INT16
}
}
//Moa 09/19/13: changed loop upperbound from uiTotalNumberOfRealItems to uiTotalNumberOfItems,
// this effectivly removes one entire loop in GetNumberOfActiveWorldItemsFromTempFile and 2 file reads.
// also changed type of iCounter from INT32 to UINT32 and for in if-clauses from true to TRUE to get rid of unneccessary casts.
void SynchronizeItemTempFileVisbleItemsToSectorInfoVisbleItems( INT16 sMapX, INT16 sMapY, INT8 bMapZ, BOOLEAN fLoadingGame )
{
UINT32 uiTotalNumberOfItems = 0, uiTotalNumberOfRealItems = 0;
UINT32 uiTotalNumberOfItems = 0;//, uiTotalNumberOfRealItems = 0;
WORLDITEM * pTotalSectorList = NULL;
UINT32 uiItemCount = 0;
INT32 iCounter = 0;
UINT32 iCounter = 0;
BOOLEAN fReturn;
/*
// get total number, visable and invisible
fReturn = GetNumberOfActiveWorldItemsFromTempFile( sMapX, sMapY, bMapZ, &( uiTotalNumberOfRealItems ) );
if (fReturn == false)
if (fReturn == TRUE)
{
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("GetNumberOfActiveWorldItemsFromTempFile failed" ) );
Assert( fReturn );
}
}*/
fReturn = GetNumberOfWorldItemsFromTempItemFile( sMapX, sMapY, bMapZ, &( uiTotalNumberOfItems ), FALSE );
if (fReturn == false)
if (fReturn == TRUE)
{
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("GetNumberOfWorldItemsFromTempItemFile failed" ) );
Assert( fReturn );
@@ -3399,7 +3406,8 @@ void SynchronizeItemTempFileVisbleItemsToSectorInfoVisbleItems( INT16 sMapX, INT
}
// now run through list and
for( iCounter = 0; ( UINT32 )( iCounter )< uiTotalNumberOfRealItems; iCounter++ )
//for( iCounter = 0; ( UINT32 )( iCounter )< uiTotalNumberOfRealItems; iCounter++ )
for( iCounter = 0; iCounter < uiTotalNumberOfItems; iCounter++ )
{
// if visible to player, then state fact
if( IsMapScreenWorldItemVisibleInMapInventory( &pTotalSectorList[ iCounter ] ) )
+7 -1
View File
@@ -11,8 +11,14 @@
#define RT_FIRST_AID_GAIN_MODIFIER 12
#define NUM_REAL_SEC_PER_TACTICAL_TURN 5000
#ifndef NUM_SEC_IN_MIN
#define NUM_SEC_IN_MIN 60
#endif
#define NUM_REAL_SEC_PER_TACTICAL_TURN 5000
#define NUM_SEC_PER_STRATEGIC_TURN ( NUM_SEC_IN_MIN * 15 ) // Every fifteen minutes
#define NUM_SEC_PER_TACTICAL_TURN 5
#define RT_COMPRESSION_TACTICAL_TURN_MODIFIER 10
+5
View File
@@ -1875,6 +1875,11 @@ void DebugStructurePage1( void )
{
gprintf( 0, LINE_HEIGHT * 1, L"DDoorRt with orientation %s", WallOrientationString[pStructure->ubWallOrientation] );
}
else if (pStructure->fFlags & STRUCTURE_PERSON)
{
if (pStructure->pDBStructureRef != NULL && pStructure->pDBStructureRef->pDBStructure != NULL)
gprintf( 0, LINE_HEIGHT * 1, L"PersonStructure with StructureNumber %d", pStructure->pDBStructureRef->pDBStructure->usStructureNumber );
}
else
{
gprintf( 0, LINE_HEIGHT * 1, L"UNKNOWN STRUCTURE! (%x)", pStructure->fFlags );