1 #include "Buffer.h"
2 #include "Font_Control.h"
3 #include "Handle_Items.h"
4 #include "Structure.h"
5 #include "TileDef.h"
6 #include "Types.h"
7 #include "SaveLoadMap.h"
8 #include "Overhead.h"
9 #include "FileMan.h"
10 #include "Tactical_Save.h"
11 #include "Debug.h"
12 #include "WorldMan.h"
13 #include "StrategicMap.h"
14 #include "Campaign_Types.h"
15 #include "Render_Fun.h"
16 #include "FOV.h"
17 #include "WorldDef.h"
18 #include "Exit_Grids.h"
19 #include "Message.h"
20 #include "GameSettings.h"
21 #include "Smell.h"
22 #include "MemMan.h"
23 
24 #include "ContentManager.h"
25 #include "GameInstance.h"
26 #include <memory>
27 
28 #define NUM_REVEALED_BYTES 3200
29 
30 extern BOOLEAN gfLoadingExitGrids;
31 
32 
33 bool ApplyMapChangesToMapTempFile::active_ = false;
34 
35 
36 //  There are 3200 bytes, and each bit represents the revelaed status.
37 //	3200 bytes * 8 bits = 25600 map elements
38 UINT8				*gpRevealedMap;
39 
40 
41 // Opens the map modification temp file (m_*) of the given sector for append, and marks it in the sector flag.
OpenMapModificationTempFile(INT16 const sSectorX,INT16 const sSectorY,INT8 const bSectorZ)42 static std::unique_ptr<AutoSGPFile> OpenMapModificationTempFile(INT16 const sSectorX, INT16 const sSectorY, INT8 const bSectorZ)
43 {
44 	SetSectorFlag(sSectorX, sSectorY, bSectorZ, SF_MAP_MODIFICATIONS_TEMP_FILE_EXISTS);
45 
46 	return std::make_unique<AutoSGPFile>(FileMan::openForAppend(GetMapTempFileName(SF_MAP_MODIFICATIONS_TEMP_FILE_EXISTS, sSectorX, sSectorY, bSectorZ)));
47 }
48 
49 // Writes map modification to the open temp file
SaveModifiedMapStructToMapTempFile(MODIFY_MAP const * const pMap,AutoSGPFile & hFile)50 static void SaveModifiedMapStructToMapTempFile(MODIFY_MAP const* const pMap, AutoSGPFile& hFile)
51 {
52 	FileWrite(hFile, pMap, sizeof(MODIFY_MAP));
53 }
54 
55 // Opens the map temp file, writes the modification, then close the file
SaveModifiedMapStructToMapTempFile(MODIFY_MAP const * const pMap,INT16 const sSectorX,INT16 const sSectorY,INT8 const bSectorZ)56 static void SaveModifiedMapStructToMapTempFile(MODIFY_MAP const* const pMap, INT16 const sSectorX, INT16 const sSectorY, INT8 const bSectorZ)
57 {
58 	std::unique_ptr<AutoSGPFile> hFile = OpenMapModificationTempFile(sSectorX, sSectorY, bSectorZ);
59 	SaveModifiedMapStructToMapTempFile(pMap, *hFile);
60 }
61 
62 
63 static void AddBloodOrSmellFromMapTempFileToMap(MODIFY_MAP* pMap);
64 static void AddObjectFromMapTempFileToMap(UINT32 uiMapIndex, UINT16 usIndex);
65 static void DamageStructsFromMapTempFile(MODIFY_MAP* pMap);
66 static bool ModifyWindowStatus(GridNo);
67 static void RemoveSavedStructFromMap(UINT32 uiMapIndex, UINT16 usIndex);
68 static void SetOpenableStructStatusFromMapTempFile(UINT32 uiMapIndex, BOOLEAN fOpened);
69 
70 
LoadAllMapChangesFromMapTempFileAndApplyThem()71 void LoadAllMapChangesFromMapTempFileAndApplyThem()
72 {
73 	UINT32     uiNumberOfElementsSavedBackToFile = 0; // added becuase if no files get saved back to disk, the flag needs to be erased
74 	UINT32     cnt;
75 	MODIFY_MAP *pMap;
76 
77 	ST::string const zMapName = GetMapTempFileName( SF_MAP_MODIFICATIONS_TEMP_FILE_EXISTS, gWorldSectorX, gWorldSectorY, gbWorldSectorZ );
78 
79 	//If the file doesnt exists, its no problem.
80 	if (!GCM->doesGameResExists(zMapName)) return;
81 
82 	UINT32                  uiNumberOfElements;
83 	SGP::Buffer<MODIFY_MAP> pTempArrayOfMaps;
84 	{
85 		AutoSGPFile hFile(GCM->openGameResForReading(zMapName));
86 
87 		//Get the size of the file
88 		uiNumberOfElements = FileGetSize(hFile) / sizeof(MODIFY_MAP);
89 
90 		//Read the map temp file into a buffer
91 		pTempArrayOfMaps.Allocate(uiNumberOfElements);
92 		FileRead(hFile, pTempArrayOfMaps, sizeof(*pTempArrayOfMaps) * uiNumberOfElements);
93 	}
94 
95 	//Delete the file
96 	FileDelete( zMapName );
97 	std::unique_ptr<AutoSGPFile> tempMapFile = OpenMapModificationTempFile(gWorldSectorX, gWorldSectorY, gbWorldSectorZ);
98 
99 	for( cnt=0; cnt< uiNumberOfElements; cnt++ )
100 	{
101 		pMap = &pTempArrayOfMaps[ cnt ];
102 
103 		//Switch on the type that should either be added or removed from the map
104 		switch( pMap->ubType )
105 		{
106 			//If we are adding to the map
107 			case SLM_LAND:
108 				break;
109 			case SLM_OBJECT:
110 			{
111 				UINT16 usIndex = GetTileIndexFromTypeSubIndex(pMap->usImageType, pMap->usSubImageIndex);
112 				AddObjectFromMapTempFileToMap( pMap->usGridNo, usIndex );
113 
114 				// Save this struct back to the temp file
115 				SaveModifiedMapStructToMapTempFile(pMap, *tempMapFile);
116 
117 				//Since the element is being saved back to the temp file, increment the #
118 				uiNumberOfElementsSavedBackToFile++;
119 				break;
120 			}
121 
122 			case SLM_STRUCT:
123 			{
124 				UINT16 const usIndex = GetTileIndexFromTypeSubIndex(pMap->usImageType, pMap->usSubImageIndex);
125 				if (!IndexExistsInStructLayer(pMap->usGridNo, usIndex))
126 				{
127 					AddStructToTail(pMap->usGridNo, usIndex);
128 				}
129 
130 				// Save this struct back to the temp file
131 				SaveModifiedMapStructToMapTempFile(pMap, *tempMapFile);
132 
133 				//Since the element is being saved back to the temp file, increment the #
134 				uiNumberOfElementsSavedBackToFile++;
135 				break;
136 			}
137 
138 			case SLM_SHADOW:
139 				break;
140 			case SLM_MERC:
141 				break;
142 			case SLM_ROOF:
143 				break;
144 			case SLM_ONROOF:
145 				break;
146 			case SLM_TOPMOST:
147 				break;
148 
149 
150 			//Remove objects out of the world
151 			case SLM_REMOVE_LAND:
152 				break;
153 			case SLM_REMOVE_OBJECT:
154 				break;
155 			case SLM_REMOVE_STRUCT:
156 
157 				// ATE: OK, dor doors, the usIndex can be varied, opened, closed, etc
158 				// we MUSTR delete ANY door type on this gridno
159 				// Since we can only have one door per gridno, we're safe to do so.....
160 				if ( pMap->usImageType >= FIRSTDOOR && pMap->usImageType <= FOURTHDOOR )
161 				{
162 					// Remove ANY door...
163 					RemoveAllStructsOfTypeRange( pMap->usGridNo, FIRSTDOOR, FOURTHDOOR );
164 				}
165 				else
166 				{
167 					UINT16 usIndex = GetTileIndexFromTypeSubIndex(pMap->usImageType, pMap->usSubImageIndex);
168 					RemoveSavedStructFromMap( pMap->usGridNo, usIndex );
169 				}
170 
171 				// Save this struct back to the temp file
172 				SaveModifiedMapStructToMapTempFile(pMap, *tempMapFile);
173 
174 				//Since the element is being saved back to the temp file, increment the #
175 				uiNumberOfElementsSavedBackToFile++;
176 				break;
177 			case SLM_REMOVE_SHADOW:
178 				break;
179 			case SLM_REMOVE_MERC:
180 				break;
181 			case SLM_REMOVE_ROOF:
182 				break;
183 			case SLM_REMOVE_ONROOF:
184 				break;
185 			case SLM_REMOVE_TOPMOST:
186 				break;
187 
188 
189 			case SLM_BLOOD_SMELL:
190 				AddBloodOrSmellFromMapTempFileToMap( pMap );
191 				break;
192 
193 			case SLM_DAMAGED_STRUCT:
194 				DamageStructsFromMapTempFile( pMap );
195 				break;
196 
197 			case SLM_EXIT_GRIDS:
198 				{
199 					EXITGRID ExitGrid;
200 					gfLoadingExitGrids = TRUE;
201 					ExitGrid.usGridNo = pMap->usSubImageIndex;
202 					ExitGrid.ubGotoSectorX = (UINT8) pMap->usImageType;
203 					ExitGrid.ubGotoSectorY = (UINT8) ( pMap->usImageType >> 8 ) ;
204 					ExitGrid.ubGotoSectorZ = pMap->ubExtra;
205 
206 					AddExitGridToWorld( pMap->usGridNo, &ExitGrid );
207 					gfLoadingExitGrids = FALSE;
208 
209 					// Save this struct back to the temp file
210 					SaveModifiedMapStructToMapTempFile(pMap, *tempMapFile);
211 
212 					//Since the element is being saved back to the temp file, increment the #
213 					uiNumberOfElementsSavedBackToFile++;
214 				}
215 				break;
216 
217 			case SLM_OPENABLE_STRUCT:
218 				SetOpenableStructStatusFromMapTempFile( pMap->usGridNo, (BOOLEAN)pMap->usImageType );
219 				break;
220 
221 			case SLM_WINDOW_HIT:
222 				if ( ModifyWindowStatus( pMap->usGridNo ) )
223 				{
224 					// Save this struct back to the temp file
225 					SaveModifiedMapStructToMapTempFile(pMap, *tempMapFile);
226 
227 					//Since the element is being saved back to the temp file, increment the #
228 					uiNumberOfElementsSavedBackToFile++;
229 				}
230 				break;
231 
232 			default:
233 				SLOGA("Map Type not in switch when loading map changes from temp file");
234 				break;
235 		}
236 
237 	}
238 
239 	//if no elements are saved back to the file, remove the flag indicating that there is a temp file
240 	if( uiNumberOfElementsSavedBackToFile == 0 )
241 	{
242 		ReSetSectorFlag( gWorldSectorX, gWorldSectorY, gbWorldSectorZ, SF_MAP_MODIFICATIONS_TEMP_FILE_EXISTS );
243 	}
244 }
245 
246 
AddToMapTempFile(UINT32 const uiMapIndex,UINT16 const usIndex,UINT8 const type)247 static void AddToMapTempFile(UINT32 const uiMapIndex, UINT16 const usIndex, UINT8 const type)
248 {
249 	if (!ApplyMapChangesToMapTempFile::IsActive())    return;
250 	if (gTacticalStatus.uiFlags & LOADING_SAVED_GAME) return;
251 
252 	UINT32 const uiType     = GetTileType(usIndex);
253 	UINT16 const usSubIndex = GetSubIndexFromTileIndex(usIndex);
254 
255 	MODIFY_MAP m;
256 	m = MODIFY_MAP{};
257 	m.usGridNo        = uiMapIndex;
258 	m.usImageType     = uiType;
259 	m.usSubImageIndex = usSubIndex;
260 	m.ubType          = type;
261 	SaveModifiedMapStructToMapTempFile(&m, gWorldSectorX, gWorldSectorY, gbWorldSectorZ);
262 }
263 
264 
AddStructToMapTempFile(UINT32 const uiMapIndex,UINT16 const usIndex)265 void AddStructToMapTempFile(UINT32 const uiMapIndex, UINT16 const usIndex)
266 {
267 	AddToMapTempFile(uiMapIndex, usIndex, SLM_STRUCT);
268 }
269 
270 
AddObjectToMapTempFile(UINT32 const uiMapIndex,UINT16 const usIndex)271 void AddObjectToMapTempFile(UINT32 const uiMapIndex, UINT16 const usIndex)
272 {
273 	AddToMapTempFile(uiMapIndex, usIndex, SLM_OBJECT);
274 }
275 
276 
AddObjectFromMapTempFileToMap(UINT32 uiMapIndex,UINT16 usIndex)277 static void AddObjectFromMapTempFileToMap(UINT32 uiMapIndex, UINT16 usIndex)
278 {
279 	AddObjectToHead( uiMapIndex, usIndex );
280 }
281 
282 
AddRemoveObjectToMapTempFile(UINT32 const uiMapIndex,UINT16 const usIndex)283 void AddRemoveObjectToMapTempFile(UINT32 const uiMapIndex, UINT16 const usIndex)
284 {
285 	AddToMapTempFile(uiMapIndex, usIndex, SLM_REMOVE_OBJECT);
286 }
287 
288 
RemoveStructFromMapTempFile(UINT32 const uiMapIndex,UINT16 const usIndex)289 void RemoveStructFromMapTempFile(UINT32 const uiMapIndex, UINT16 const usIndex)
290 {
291 	AddToMapTempFile(uiMapIndex, usIndex, SLM_REMOVE_STRUCT);
292 }
293 
294 
RemoveSavedStructFromMap(UINT32 uiMapIndex,UINT16 usIndex)295 static void RemoveSavedStructFromMap(UINT32 uiMapIndex, UINT16 usIndex)
296 {
297 	RemoveStruct( uiMapIndex, usIndex );
298 }
299 
300 
301 static void AddOpenableStructStatusToMapTempFile(UINT32 uiMapIndex, BOOLEAN fOpened, AutoSGPFile& hFile);
302 static void SetSectorsRevealedBit(UINT16 usMapIndex);
303 
304 
SaveBloodSmellAndRevealedStatesFromMapToTempFile()305 void SaveBloodSmellAndRevealedStatesFromMapToTempFile()
306 {
307 	MODIFY_MAP Map;
308 	UINT16	cnt;
309 	STRUCTURE * pStructure;
310 
311 	gpRevealedMap = new UINT8[NUM_REVEALED_BYTES]{};
312 
313 	std::unique_ptr<AutoSGPFile> tempFile = OpenMapModificationTempFile(gWorldSectorX, gWorldSectorY, gbWorldSectorZ);
314 
315 	//Loop though all the map elements
316 	for ( cnt = 0; cnt < WORLD_MAX; cnt++ )
317 	{
318 		//if there is either blood or a smell on the tile, save it
319 		if( gpWorldLevelData[cnt].ubBloodInfo || gpWorldLevelData[cnt].ubSmellInfo )
320 		{
321 			Map = MODIFY_MAP{};
322 
323 
324 			// Save the BloodInfo in the bottom byte and the smell info in the upper byte
325 			Map.usGridNo	= cnt;
326 //			Map.usIndex			= gpWorldLevelData[cnt].ubBloodInfo | ( gpWorldLevelData[cnt].ubSmellInfo << 8 );
327 			Map.usImageType = gpWorldLevelData[cnt].ubBloodInfo;
328 			Map.usSubImageIndex = gpWorldLevelData[cnt].ubSmellInfo;
329 
330 
331 			Map.ubType			= SLM_BLOOD_SMELL;
332 
333 			//Save the change to the map file
334 			SaveModifiedMapStructToMapTempFile(&Map, *tempFile);
335 		}
336 
337 
338 		//if the element has been revealed
339 		if( gpWorldLevelData[cnt].uiFlags & MAPELEMENT_REVEALED )
340 		{
341 			SetSectorsRevealedBit( cnt );
342 		}
343 
344 		//if there is a structure that is damaged
345 		if( gpWorldLevelData[cnt].uiFlags & MAPELEMENT_STRUCTURE_DAMAGED )
346 		{
347 			//loop through all the structures and add all that are damaged
348 			FOR_EACH_STRUCTURE(pCurrent, cnt, STRUCTURE_BASE_TILE)
349 			{
350 				//if the structure has been damaged
351 				if( pCurrent->ubHitPoints < pCurrent->pDBStructureRef->pDBStructure->ubHitPoints )
352 				{
353 					UINT8	ubBitToSet = 0x80;
354 					UINT8	ubLevel=0;
355 
356 					if( pCurrent->sCubeOffset != 0 )
357 						ubLevel |= ubBitToSet;
358 
359 					Map = MODIFY_MAP{};
360 
361 					// Save the Damaged value
362 					Map.usGridNo	= cnt;
363 //					Map.usIndex			= StructureFlagToType( pCurrent->fFlags ) | ( pCurrent->ubHitPoints << 8 );
364 					Map.usImageType = StructureFlagToType( pCurrent->fFlags );
365 					Map.usSubImageIndex = pCurrent->ubHitPoints;
366 
367 
368 					Map.ubType			= SLM_DAMAGED_STRUCT;
369 					Map.ubExtra			= pCurrent->ubWallOrientation | ubLevel;
370 
371 					//Save the change to the map file
372 					SaveModifiedMapStructToMapTempFile(&Map, *tempFile);
373 				}
374 			}
375 		}
376 
377 		pStructure = FindStructure( cnt, STRUCTURE_OPENABLE );
378 
379 		//if this structure
380 		if( pStructure )
381 		{
382 			// if the current structure has an openable structure in it, and it is NOT a door
383 			if( !( pStructure->fFlags & STRUCTURE_ANYDOOR ) )
384 			{
385 				BOOLEAN			fStatusOnTheMap;
386 
387 				fStatusOnTheMap = ( ( pStructure->fFlags & STRUCTURE_OPEN ) != 0 );
388 
389 				AddOpenableStructStatusToMapTempFile(cnt, fStatusOnTheMap, *tempFile);
390 			}
391 		}
392 	}
393 }
394 
395 
396 // The BloodInfo is saved in the bottom byte and the smell info in the upper byte
AddBloodOrSmellFromMapTempFileToMap(MODIFY_MAP * pMap)397 static void AddBloodOrSmellFromMapTempFileToMap(MODIFY_MAP* pMap)
398 {
399 	gpWorldLevelData[ pMap->usGridNo ].ubBloodInfo = (UINT8)pMap->usImageType;
400 
401 	//if the blood and gore option IS set, add blood
402 	if( gGameSettings.fOptions[ TOPTION_BLOOD_N_GORE ] )
403 	{
404 		// Update graphics for both levels...
405 		gpWorldLevelData[ pMap->usGridNo ].uiFlags |= MAPELEMENT_REEVALUATEBLOOD;
406 		UpdateBloodGraphics( pMap->usGridNo, 0 );
407 		gpWorldLevelData[ pMap->usGridNo ].uiFlags |= MAPELEMENT_REEVALUATEBLOOD;
408 		UpdateBloodGraphics( pMap->usGridNo, 1 );
409 	}
410 
411 	gpWorldLevelData[ pMap->usGridNo ].ubSmellInfo = (UINT8)pMap->usSubImageIndex;
412 }
413 
414 
SaveRevealedStatusArrayToRevealedTempFile(INT16 const sSectorX,INT16 const sSectorY,INT8 const bSectorZ)415 void SaveRevealedStatusArrayToRevealedTempFile(INT16 const sSectorX, INT16 const sSectorY, INT8 const bSectorZ)
416 {
417 	Assert( gpRevealedMap != NULL );
418 
419 	AutoSGPFile hFile(FileMan::openForWriting(GetMapTempFileName( SF_REVEALED_STATUS_TEMP_FILE_EXISTS, sSectorX, sSectorY, bSectorZ )));
420 
421 	//Write the revealed array to the Revealed temp file
422 	FileWrite(hFile, gpRevealedMap, NUM_REVEALED_BYTES);
423 
424 	SetSectorFlag( sSectorX, sSectorY, bSectorZ, SF_REVEALED_STATUS_TEMP_FILE_EXISTS );
425 
426 	delete[] gpRevealedMap;
427 	gpRevealedMap = NULL;
428 }
429 
430 
431 static void SetMapRevealedStatus(void);
432 
433 
LoadRevealedStatusArrayFromRevealedTempFile()434 void LoadRevealedStatusArrayFromRevealedTempFile()
435 {
436 	ST::string const zMapName = GetMapTempFileName( SF_REVEALED_STATUS_TEMP_FILE_EXISTS, gWorldSectorX, gWorldSectorY, gbWorldSectorZ );
437 
438 	//If the file doesnt exists, its no problem.
439 	if (!GCM->doesGameResExists(zMapName)) return;
440 
441 	{
442 		AutoSGPFile hFile(GCM->openGameResForReading(zMapName));
443 
444 		Assert( gpRevealedMap == NULL );
445 		gpRevealedMap = new UINT8[NUM_REVEALED_BYTES]{};
446 
447 		// Load the Reveal map array structure
448 		FileRead(hFile, gpRevealedMap, NUM_REVEALED_BYTES);
449 	}
450 
451 	//Loop through and set the bits in the map that are revealed
452 	SetMapRevealedStatus();
453 
454 	delete[] gpRevealedMap;
455 	gpRevealedMap = NULL;
456 }
457 
458 
SetSectorsRevealedBit(UINT16 usMapIndex)459 static void SetSectorsRevealedBit(UINT16 usMapIndex)
460 {
461 	UINT16	usByteNumber;
462 	UINT8		ubBitNumber;
463 
464 	usByteNumber = usMapIndex / 8;
465 	ubBitNumber  = usMapIndex % 8;
466 
467 	gpRevealedMap[ usByteNumber ] |= 1 << ubBitNumber;
468 }
469 
470 
SetMapRevealedStatus(void)471 static void SetMapRevealedStatus(void)
472 {
473 	UINT16	usByteCnt;
474 	UINT8		ubBitCnt;
475 	UINT16	usMapIndex;
476 
477 	AssertMsg(gpRevealedMap != NULL, "gpRevealedMap is NULL.  DF 1");
478 
479 	ClearSlantRoofs( );
480 
481 	//Loop through all bytes in the array
482 	for( usByteCnt=0; usByteCnt< 3200; usByteCnt++)
483 	{
484 		//loop through all the bits in the byte
485 		for( ubBitCnt=0; ubBitCnt<8; ubBitCnt++)
486 		{
487 			usMapIndex = ( usByteCnt * 8 ) + ubBitCnt;
488 
489 			if( gpRevealedMap[ usByteCnt ] & ( 1 << ubBitCnt ) )
490 			{
491 				gpWorldLevelData[ usMapIndex ].uiFlags |= MAPELEMENT_REVEALED;
492 				SetGridNoRevealedFlag( usMapIndex );
493 			}
494 			else
495 			{
496 				gpWorldLevelData[ usMapIndex ].uiFlags &= (~MAPELEMENT_REVEALED );
497 			}
498 		}
499 	}
500 
501 	ExamineSlantRoofFOVSlots( );
502 
503 }
504 
505 
DamageStructsFromMapTempFile(MODIFY_MAP * pMap)506 static void DamageStructsFromMapTempFile(MODIFY_MAP* pMap)
507 {
508 	STRUCTURE *pCurrent=NULL;
509 	INT8			bLevel;
510 	UINT8			ubWallOrientation;
511 	UINT8			ubBitToSet = 0x80;
512 	UINT8			ubType=0;
513 
514 
515 	//Find the base structure
516 	pCurrent = FindStructure( (INT16)pMap->usGridNo, STRUCTURE_BASE_TILE );
517 
518 	if( pCurrent == NULL )
519 		return;
520 
521 	bLevel = pMap->ubExtra & ubBitToSet;
522 	ubWallOrientation = pMap->ubExtra & ~ubBitToSet;
523 	ubType = (UINT8) pMap->usImageType;
524 
525 
526 	//Check to see if the desired strucure node is in this tile
527 	pCurrent = FindStructureBySavedInfo( pMap->usGridNo, ubType, ubWallOrientation, bLevel );
528 
529 	if( pCurrent != NULL )
530 	{
531 		//Assign the hitpoints
532 		pCurrent->ubHitPoints = (UINT8)( pMap->usSubImageIndex );
533 
534 		gpWorldLevelData[ pCurrent->sGridNo ].uiFlags |= MAPELEMENT_STRUCTURE_DAMAGED;
535 	}
536 }
537 
538 
AddStructToUnLoadedMapTempFile(UINT32 uiMapIndex,UINT16 usIndex,INT16 sSectorX,INT16 sSectorY,UINT8 ubSectorZ)539 void AddStructToUnLoadedMapTempFile( UINT32 uiMapIndex, UINT16 usIndex, INT16 sSectorX, INT16 sSectorY, UINT8 ubSectorZ  )
540 {
541 	MODIFY_MAP Map;
542 
543 	if( gTacticalStatus.uiFlags & LOADING_SAVED_GAME )
544 		return;
545 
546 	const UINT32 uiType     = GetTileType(usIndex);
547 	const UINT16 usSubIndex = GetSubIndexFromTileIndex(usIndex);
548 
549 	Map = MODIFY_MAP{};
550 
551 	Map.usGridNo = (UINT16)uiMapIndex;
552 //	Map.usIndex		= usIndex;
553 	Map.usImageType = (UINT16)uiType;
554 	Map.usSubImageIndex = usSubIndex;
555 
556 
557 	Map.ubType		= SLM_STRUCT;
558 
559 	SaveModifiedMapStructToMapTempFile( &Map, sSectorX, sSectorY, ubSectorZ );
560 }
561 
562 
RemoveStructFromUnLoadedMapTempFile(UINT32 uiMapIndex,UINT16 usIndex,INT16 sSectorX,INT16 sSectorY,UINT8 ubSectorZ)563 void RemoveStructFromUnLoadedMapTempFile( UINT32 uiMapIndex, UINT16 usIndex, INT16 sSectorX, INT16 sSectorY, UINT8 ubSectorZ  )
564 {
565 	MODIFY_MAP Map;
566 
567 	if( gTacticalStatus.uiFlags & LOADING_SAVED_GAME )
568 		return;
569 
570 	const UINT32 uiType     = GetTileType(usIndex);
571 	const UINT16 usSubIndex = GetSubIndexFromTileIndex(usIndex);
572 
573 	Map = MODIFY_MAP{};
574 
575 	Map.usGridNo	= (UINT16)uiMapIndex;
576 //	Map.usIndex			= usIndex;
577 	Map.usImageType = (UINT16)uiType;
578 	Map.usSubImageIndex = usSubIndex;
579 
580 	Map.ubType			= SLM_REMOVE_STRUCT;
581 
582 	SaveModifiedMapStructToMapTempFile( &Map, sSectorX, sSectorY, ubSectorZ );
583 }
584 
585 
AddExitGridToMapTempFile(UINT16 usGridNo,EXITGRID * pExitGrid,INT16 sSectorX,INT16 sSectorY,UINT8 ubSectorZ)586 void AddExitGridToMapTempFile( UINT16 usGridNo, EXITGRID *pExitGrid, INT16 sSectorX, INT16 sSectorY, UINT8 ubSectorZ )
587 {
588 	MODIFY_MAP Map;
589 
590 	if (!ApplyMapChangesToMapTempFile::IsActive())
591 	{
592 		SLOGD("Called AddExitGridToMapTempFile() without holding ApplyMapChangesToMapTempFile");
593 		return;
594 	}
595 
596 	if( gTacticalStatus.uiFlags & LOADING_SAVED_GAME )
597 		return;
598 
599 	Map = MODIFY_MAP{};
600 
601 	Map.usGridNo = usGridNo;
602 //	Map.usIndex		= pExitGrid->ubGotoSectorX;
603 
604 	Map.usImageType = pExitGrid->ubGotoSectorX | ( pExitGrid->ubGotoSectorY << 8 );
605 	Map.usSubImageIndex = pExitGrid->usGridNo;
606 
607 	Map.ubExtra		= pExitGrid->ubGotoSectorZ;
608 	Map.ubType		= SLM_EXIT_GRIDS;
609 
610 	SaveModifiedMapStructToMapTempFile( &Map, sSectorX, sSectorY, ubSectorZ );
611 }
612 
RemoveGraphicFromTempFile(UINT32 uiMapIndex,UINT16 usIndex,INT16 sSectorX,INT16 sSectorY,UINT8 ubSectorZ)613 BOOLEAN RemoveGraphicFromTempFile( UINT32 uiMapIndex, UINT16 usIndex, INT16 sSectorX, INT16 sSectorY, UINT8 ubSectorZ )
614 try
615 {
616 	MODIFY_MAP *pMap;
617 	BOOLEAN	fRetVal=FALSE;
618 	UINT32	cnt;
619 
620 	ST::string const zMapName = GetMapTempFileName( SF_MAP_MODIFICATIONS_TEMP_FILE_EXISTS, sSectorX, sSectorY, ubSectorZ );
621 
622 	UINT32                  uiNumberOfElements;
623 	SGP::Buffer<MODIFY_MAP> pTempArrayOfMaps;
624 	{
625 		AutoSGPFile hFile(GCM->openGameResForReading(zMapName));
626 
627 		//Get the number of elements in the file
628 		uiNumberOfElements = FileGetSize(hFile) / sizeof(MODIFY_MAP);
629 
630 		//Read the map temp file into a buffer
631 		pTempArrayOfMaps.Allocate(uiNumberOfElements);
632 		FileRead(hFile, pTempArrayOfMaps, sizeof(*pTempArrayOfMaps) * uiNumberOfElements);
633 	}
634 
635 	//Delete the file
636 	FileDelete( zMapName );
637 
638 	//Get the image type and subindex
639 	const UINT32 uiType     = GetTileType(usIndex);
640 	const UINT16 usSubIndex = GetSubIndexFromTileIndex(usIndex);
641 
642 	for( cnt=0; cnt< uiNumberOfElements; cnt++ )
643 	{
644 		pMap = &pTempArrayOfMaps[ cnt ];
645 
646 		//if this is the peice we are looking for
647 		if( pMap->usGridNo == uiMapIndex && pMap->usImageType == uiType && pMap->usSubImageIndex == usSubIndex )
648 		{
649 			//Do nothin
650 			fRetVal = TRUE;
651 		}
652 		else
653 		{
654 			//save the struct back to the temp file
655 			SaveModifiedMapStructToMapTempFile( pMap, sSectorX, sSectorY, ubSectorZ );
656 		}
657 	}
658 
659 	return( fRetVal );
660 }
661 catch (...) { return FALSE; }
662 
663 // Appends the status of openable struct status to the map modification temp file (m_*)
AddOpenableStructStatusToMapTempFile(UINT32 uiMapIndex,BOOLEAN fOpened,AutoSGPFile & hFile)664 static void AddOpenableStructStatusToMapTempFile(UINT32 uiMapIndex, BOOLEAN fOpened, AutoSGPFile& hFile)
665 {
666 	MODIFY_MAP Map;
667 
668 	Map = MODIFY_MAP{};
669 
670 	Map.usGridNo = (UINT16)uiMapIndex;
671 	Map.usImageType = fOpened;
672 
673 	Map.ubType = SLM_OPENABLE_STRUCT;
674 
675 	SaveModifiedMapStructToMapTempFile(&Map, hFile);
676 }
677 
AddWindowHitToMapTempFile(UINT32 uiMapIndex)678 void AddWindowHitToMapTempFile( UINT32 uiMapIndex )
679 {
680 	MODIFY_MAP Map;
681 
682 	Map = MODIFY_MAP{};
683 
684 	Map.usGridNo = (UINT16)uiMapIndex;
685 	Map.ubType = SLM_WINDOW_HIT;
686 
687 	SaveModifiedMapStructToMapTempFile( &Map, gWorldSectorX, gWorldSectorY, gbWorldSectorZ );
688 }
689 
690 
ModifyWindowStatus(GridNo const grid_no)691 static bool ModifyWindowStatus(GridNo const grid_no)
692 {
693 	STRUCTURE* const s = FindStructure(grid_no, STRUCTURE_WALLNWINDOW);
694 	if (!s) return false; // Forget it, window could be destroyed
695 	SwapStructureForPartner(s);
696 	return true;
697 }
698 
699 
SetOpenableStructStatusFromMapTempFile(UINT32 uiMapIndex,BOOLEAN fOpened)700 static void SetOpenableStructStatusFromMapTempFile(UINT32 uiMapIndex, BOOLEAN fOpened)
701 {
702 	STRUCTURE *pStructure;
703 	STRUCTURE *pBase;
704 	BOOLEAN   fStatusOnTheMap;
705 	INT16     sBaseGridNo = (INT16)uiMapIndex;
706 
707 	pStructure = FindStructure( (UINT16)uiMapIndex, STRUCTURE_OPENABLE );
708 
709 	if( pStructure == NULL )
710 	{
711 		SLOGD("SetOpenableStructStatusFromMapTempFile( %d, %d ) failed to find the openable struct.", uiMapIndex, fOpened );
712 		return;
713 	}
714 
715 	fStatusOnTheMap = ( ( pStructure->fFlags & STRUCTURE_OPEN ) != 0 );
716 
717 	if( fStatusOnTheMap != fOpened )
718 	{
719 		// Adjust the item's gridno to the base of struct.....
720 		pBase = FindBaseStructure( pStructure );
721 
722 		// Get LEVELNODE for struct and remove!
723 		if (pBase)
724 		{
725 			sBaseGridNo = pBase->sGridNo;
726 		}
727 
728 		if (!SwapStructureForPartner(pStructure))
729 		{
730 			//an error occured
731 		}
732 
733 		// Adjust visiblity of any item pools here....
734 		// ATE: Nasty bug here - use base gridno for structure for items!
735 		// since items always drop to base gridno in AddItemToPool
736 		if (fOpened)
737 		{
738 			// We are open, make un-hidden if so....
739 			SetItemsVisibilityOn(sBaseGridNo, 0, ANY_VISIBILITY_VALUE, FALSE);
740 		}
741 		else
742 		{
743 			// Make sure items are hidden...
744 			SetItemsVisibilityHidden(sBaseGridNo, 0);
745 		}
746 	}
747 }
748 
749 
ChangeStatusOfOpenableStructInUnloadedSector(UINT16 const usSectorX,UINT16 const usSectorY,INT8 const bSectorZ,UINT16 const usGridNo,BOOLEAN const fChangeToOpen)750 void ChangeStatusOfOpenableStructInUnloadedSector(UINT16 const usSectorX, UINT16 const usSectorY, INT8 const bSectorZ, UINT16 const usGridNo, BOOLEAN const fChangeToOpen)
751 {
752 	ST::string const map_name = GetMapTempFileName(SF_MAP_MODIFICATIONS_TEMP_FILE_EXISTS, usSectorX, usSectorY, bSectorZ);
753 
754 	// If the file doesn't exists, it's no problem.
755 	if (!GCM->doesGameResExists(map_name)) return;
756 
757 	UINT32                  uiNumberOfElements;
758 	SGP::Buffer<MODIFY_MAP> mm;
759 	{
760 		// Read the map temp file into a buffer
761 		AutoSGPFile src(GCM->openGameResForReading(map_name));
762 
763 		uiNumberOfElements = FileGetSize(src) / sizeof(MODIFY_MAP);
764 
765 		mm.Allocate(uiNumberOfElements);
766 		FileRead(src, mm, sizeof(*mm) * uiNumberOfElements);
767 	}
768 
769 	for (UINT32 i = 0; i < uiNumberOfElements; ++i)
770 	{
771 		MODIFY_MAP* const m = &mm[i];
772 		if (m->ubType != SLM_OPENABLE_STRUCT || m->usGridNo != usGridNo) continue;
773 		// This element is of the same type and on the same gridno
774 
775 		// Change to the desired settings
776 		m->usImageType = fChangeToOpen;
777 		break;
778 	}
779 
780 	AutoSGPFile dst(FileMan::openForWriting(map_name));
781 	FileWrite(dst, mm, sizeof(*mm) * uiNumberOfElements);
782 }
783