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