From 83aa3aba799c71079bf8b7d744b192f9a203252c Mon Sep 17 00:00:00 2001 From: Rui Date: Sat, 18 Jun 2022 16:02:56 +0100 Subject: [PATCH 01/40] Added feature to allow the player to save the game from the menu (work in progress) --- SOURCES/Assets/Text/de_ctxt.csv | 2 + SOURCES/Assets/Text/en_ctxt.csv | 2 + SOURCES/Assets/Text/fr_ctxt.csv | 2 + SOURCES/Assets/Text/it_ctxt.csv | 2 + SOURCES/Assets/Text/sp_ctxt.csv | 2 + SOURCES/GAMEMENU.C | 98 ++++++++++++++++++++++++++++++--- 6 files changed, 99 insertions(+), 9 deletions(-) diff --git a/SOURCES/Assets/Text/de_ctxt.csv b/SOURCES/Assets/Text/de_ctxt.csv index 0f5ae1b..1bf71b1 100644 --- a/SOURCES/Assets/Text/de_ctxt.csv +++ b/SOURCES/Assets/Text/de_ctxt.csv @@ -1,2 +1,4 @@ 234,Kollisionsschaden aktiv 34,Kollisionsschaden inaktiv +950,Create new save +951,Replace existing save diff --git a/SOURCES/Assets/Text/en_ctxt.csv b/SOURCES/Assets/Text/en_ctxt.csv index b761e00..d18fc2d 100644 --- a/SOURCES/Assets/Text/en_ctxt.csv +++ b/SOURCES/Assets/Text/en_ctxt.csv @@ -1,2 +1,4 @@ 234,Collision Damage On 34,Collision Damage Off +950,Create new save +951,Replace existing save diff --git a/SOURCES/Assets/Text/fr_ctxt.csv b/SOURCES/Assets/Text/fr_ctxt.csv index ffdfd0c..aaf68b8 100644 --- a/SOURCES/Assets/Text/fr_ctxt.csv +++ b/SOURCES/Assets/Text/fr_ctxt.csv @@ -1,2 +1,4 @@ 234,D‚gƒts de collision activ‚s 34,D‚gƒts de collision d‚sactiv‚s +950,Create new save +951,Replace existing save diff --git a/SOURCES/Assets/Text/it_ctxt.csv b/SOURCES/Assets/Text/it_ctxt.csv index 73ef0e9..8ad14da 100644 --- a/SOURCES/Assets/Text/it_ctxt.csv +++ b/SOURCES/Assets/Text/it_ctxt.csv @@ -1,2 +1,4 @@ 234,Danno da collisione attivato 34,Danno da collisione disattivato +950,Create new save +951,Replace existing save diff --git a/SOURCES/Assets/Text/sp_ctxt.csv b/SOURCES/Assets/Text/sp_ctxt.csv index a6521e3..8803e3d 100644 --- a/SOURCES/Assets/Text/sp_ctxt.csv +++ b/SOURCES/Assets/Text/sp_ctxt.csv @@ -1,2 +1,4 @@ 234,Da€os por colisi’n activados 34,Da€os por colisi’n desactivados +950,Create new save +951,Replace existing save diff --git a/SOURCES/GAMEMENU.C b/SOURCES/GAMEMENU.C index 9fc850a..09025de 100644 --- a/SOURCES/GAMEMENU.C +++ b/SOURCES/GAMEMENU.C @@ -30,10 +30,13 @@ UWORD GameMainMenu[] = { UWORD GameQuitMenu[] = { 0, // selected - 2, // nb entries + 5, // nb entries 240, // y center 0, // .dia num 0, 28, // continuer jeu + 0, 21, // load game + 0, 950, // new save + 0, 951, // gestion saved game 0, 27 // abandonner partie } ; @@ -1227,13 +1230,33 @@ WORD FindPlayerFile() /*──────────────────────────────────────────────────────────────────────────*/ -void SaveGame() +void SaveGame() +{ + SaveGameWithName("AUTO"); +} + +void SaveGameWithName(char* fileName) { FILE* handle ; WORD wword ; UBYTE wbyte ; - handle = OpenWrite( GamePathname ) ; + if (fileName) + { + char savePath[1024]; + + strcpy(savePath, PATH_RESSOURCE); + strcat(savePath, fileName); + strcat(savePath, ".LBA"); + + handle = OpenWrite(savePath); + } + else + { + Message("Invalid file name", TRUE); + return; + } + if( !handle ) { Message( "Error Writing Saved Game", TRUE ) ; @@ -1244,7 +1267,7 @@ void SaveGame() Write( handle, &NumVersion, 1 ) ; - Write( handle, PlayerName, strlen(PlayerName)+1 ) ; + Write( handle, fileName, strlen(fileName)+1 ) ; // list flag game wbyte = MAX_FLAGS_GAME ; @@ -1743,6 +1766,7 @@ WORD ChoosePlayerName( WORD mess ) while( Key != K_ESC ) { + if( flag == 1 ) { for( n=0; n<6; n++ ) @@ -2599,7 +2623,7 @@ LONG MainGameMenu() if( !ChoosePlayerName( 21 ) ) break ; InitGame( -1, 0 ) ; - Introduction() ; + //Introduction() ; if( MainLoop() ) { #ifdef DEMO @@ -2635,13 +2659,14 @@ LONG MainGameMenu() LONG QuitMenu() { + LONG retValue = -999; WORD select ; LONG memoflagspeak ; CopyScreen( Log, Screen ) ; HQ_StopSample() ; - while( TRUE ) + while( retValue == -999 ) { memoflagspeak = FlagSpeak ; FlagSpeak = FALSE ; @@ -2654,13 +2679,68 @@ LONG QuitMenu() switch( select ) // num mess { - case 28: // continue - return FALSE ; + case 21: // load + if (!ChoosePlayerName(21)) break; + + InitGame(-1, 0); + + if (MainLoop()) + { + #ifdef DEMO + PlayMidiFile(6); + Credits(); + TheEnd(PROGRAM_OK, "* End of Demo version."); + #else + Credits(); + PlayAnimFla("The_End"); + Cls(); + Flip(); + Palette(PtrPal); + #endif + } + CopyScreen(Log, Screen); + while (Key OR Fire); // provisoire + + retValue = FALSE; + break; case 27: // abandonner - return TRUE ; + retValue = TRUE; + break; + + case 28: // continue + retValue = FALSE; + break; + + case 950: + if (InputPlayerName(44)) + { + SceneStartX = ListObjet[NUM_PERSO].PosObjX; + SceneStartY = ListObjet[NUM_PERSO].PosObjY; + SceneStartZ = ListObjet[NUM_PERSO].PosObjZ; + + SaveGameWithName(PlayerName); + } + + retValue = FALSE; + break; + + case 951: + if (ChoosePlayerName(41)) + { + SceneStartX = ListObjet[NUM_PERSO].PosObjX; + SceneStartY = ListObjet[NUM_PERSO].PosObjY; + SceneStartZ = ListObjet[NUM_PERSO].PosObjZ; + + SaveGameWithName(PlayerName); + } + + retValue = FALSE; + break; } } + + return retValue; } /*══════════════════════════════════════════════════════════════════════════* From 1255e266b6a22f5203ab557cd10ae90bf9a931f6 Mon Sep 17 00:00:00 2001 From: Rui Date: Sat, 18 Jun 2022 22:40:56 +0100 Subject: [PATCH 02/40] Applied a fix to show previously obtained inventory upon loading a game --- SOURCES/GAMEMENU.C | 11 ++++++++--- SOURCES/GERELIFE.C | 5 ++++- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/SOURCES/GAMEMENU.C b/SOURCES/GAMEMENU.C index 09025de..ab0f97f 100644 --- a/SOURCES/GAMEMENU.C +++ b/SOURCES/GAMEMENU.C @@ -1377,7 +1377,6 @@ void LoadGame() Read( handle, &NbFourLeafClover, 1 ) ; Read( handle, &Weapon, 2 ) ; - Close( handle ) ; NumCube = -1 ; @@ -2684,7 +2683,7 @@ LONG QuitMenu() InitGame(-1, 0); - if (MainLoop()) +/* if (MainLoop()) { #ifdef DEMO PlayMidiFile(6); @@ -2697,7 +2696,7 @@ LONG QuitMenu() Flip(); Palette(PtrPal); #endif - } + }*/ CopyScreen(Log, Screen); while (Key OR Fire); // provisoire @@ -2715,6 +2714,9 @@ LONG QuitMenu() case 950: if (InputPlayerName(44)) { + SaveComportement = Comportement; + SaveBeta = ListObjet[NUM_PERSO].Beta; + SceneStartX = ListObjet[NUM_PERSO].PosObjX; SceneStartY = ListObjet[NUM_PERSO].PosObjY; SceneStartZ = ListObjet[NUM_PERSO].PosObjZ; @@ -2728,6 +2730,9 @@ LONG QuitMenu() case 951: if (ChoosePlayerName(41)) { + SaveComportement = Comportement; + SaveBeta = ListObjet[NUM_PERSO].Beta; + SceneStartX = ListObjet[NUM_PERSO].PosObjX; SceneStartY = ListObjet[NUM_PERSO].PosObjY; SceneStartZ = ListObjet[NUM_PERSO].PosObjZ; diff --git a/SOURCES/GERELIFE.C b/SOURCES/GERELIFE.C index c67e3a6..089ccba 100644 --- a/SOURCES/GERELIFE.C +++ b/SOURCES/GERELIFE.C @@ -755,7 +755,10 @@ void DoLife( WORD numobj ) case LM_SET_FLAG_GAME: num = *PtrPrg++ ; - ListFlagGame[num] = *PtrPrg++ ; + + //If ListFlagName[num] is already populated, do nothing (this appears to allow to keep inventory when loading a save in the middle of a scene) + if (!ListFlagGame[num]) + ListFlagGame[num] = *PtrPrg++ ; //Text( 0,100, "%Fset ListFlagGame %d = %d",num,ListFlagGame[num] ) ; From 233d2e93544f1d682b6035c7e2411ea450e19614 Mon Sep 17 00:00:00 2001 From: Rui Date: Sat, 18 Jun 2022 23:43:05 +0100 Subject: [PATCH 03/40] Now persisting number of keys obtained in a save file --- SOURCES/C_EXTERN.H | 2 ++ SOURCES/GAMEMENU.C | 4 ++++ SOURCES/GLOBAL.C | 2 ++ SOURCES/OBJECT.C | 4 +++- 4 files changed, 11 insertions(+), 1 deletion(-) diff --git a/SOURCES/C_EXTERN.H b/SOURCES/C_EXTERN.H index 5e2c85b..d20e59f 100644 --- a/SOURCES/C_EXTERN.H +++ b/SOURCES/C_EXTERN.H @@ -242,6 +242,8 @@ extern UBYTE Island ; extern WORD Fuel ; extern WORD NumPingouin ; +extern WORD HasLoadedKeysOnSave ; + extern WORD NbFourLeafClover ; extern WORD NbCloverBox ; diff --git a/SOURCES/GAMEMENU.C b/SOURCES/GAMEMENU.C index ab0f97f..02f37d1 100644 --- a/SOURCES/GAMEMENU.C +++ b/SOURCES/GAMEMENU.C @@ -1310,6 +1310,7 @@ void SaveGameWithName(char* fileName) // others Write( handle, &NbFourLeafClover, 1 ) ; Write( handle, &Weapon, 2 ) ; + Write( handle, &NbLittleKeys, 1 ); Close( handle ) ; } @@ -1376,6 +1377,9 @@ void LoadGame() // others Read( handle, &NbFourLeafClover, 1 ) ; Read( handle, &Weapon, 2 ) ; + Read( handle, &NbLittleKeys, 1 ); + + HasLoadedKeysOnSave = NbLittleKeys && NbLittleKeys > 0; Close( handle ) ; diff --git a/SOURCES/GLOBAL.C b/SOURCES/GLOBAL.C index f71cf31..8bf1d84 100644 --- a/SOURCES/GLOBAL.C +++ b/SOURCES/GLOBAL.C @@ -171,6 +171,8 @@ WORD Chapitre = 0 ; WORD NbFourLeafClover = 2 ; WORD NbCloverBox = 2 ; +WORD HasLoadedKeysOnSave = 0; + WORD Island = 0 ; WORD Fuel = 0 ; WORD NumPingouin = -1 ; diff --git a/SOURCES/OBJECT.C b/SOURCES/OBJECT.C index 4a3e183..0c65062 100644 --- a/SOURCES/OBJECT.C +++ b/SOURCES/OBJECT.C @@ -478,7 +478,7 @@ void ChangeCube() StartInitAllObjs() ; - NbLittleKeys = 0 ; + NbLittleKeys = HasLoadedKeysOnSave ? NbLittleKeys : 0 ; MagicBall = -1 ; LastJoyFlag = TRUE ; ZoneGrm = -1 ; @@ -494,6 +494,8 @@ void ChangeCube() SamplePlayed = 2+4+8 ; // joue le premier sample en 1er TimerNextAmbiance = 0 ; + HasLoadedKeysOnSave = 0; + StartXCube = ((ListObjet[NumObjFollow].PosObjX+DEMI_BRICK_XZ)/SIZE_BRICK_XZ) ; StartYCube = ((ListObjet[NumObjFollow].PosObjY+SIZE_BRICK_Y)/SIZE_BRICK_Y) ; StartZCube = ((ListObjet[NumObjFollow].PosObjZ+DEMI_BRICK_XZ)/SIZE_BRICK_XZ) ; From 5aad63b821bd8ffcf5f84351abbdb4ddb816a97c Mon Sep 17 00:00:00 2001 From: Rui Date: Sun, 19 Jun 2022 12:21:38 +0100 Subject: [PATCH 04/40] Fixed situation where inventory could not be obtained when recaptured in prison. Now preventing auto save right after a save is loaded. --- SOURCES/C_EXTERN.H | 2 ++ SOURCES/GAMEMENU.C | 6 ++++-- SOURCES/GERELIFE.C | 9 ++++++++- SOURCES/GLOBAL.C | 2 ++ SOURCES/OBJECT.C | 4 +++- 5 files changed, 19 insertions(+), 4 deletions(-) diff --git a/SOURCES/C_EXTERN.H b/SOURCES/C_EXTERN.H index d20e59f..c6a7617 100644 --- a/SOURCES/C_EXTERN.H +++ b/SOURCES/C_EXTERN.H @@ -242,7 +242,9 @@ extern UBYTE Island ; extern WORD Fuel ; extern WORD NumPingouin ; +extern WORD HasLoadedSave ; extern WORD HasLoadedKeysOnSave ; +extern WORD HasLoadedInventoryOnSave; extern WORD NbFourLeafClover ; extern WORD NbCloverBox ; diff --git a/SOURCES/GAMEMENU.C b/SOURCES/GAMEMENU.C index 02f37d1..f621ab1 100644 --- a/SOURCES/GAMEMENU.C +++ b/SOURCES/GAMEMENU.C @@ -1379,10 +1379,12 @@ void LoadGame() Read( handle, &Weapon, 2 ) ; Read( handle, &NbLittleKeys, 1 ); - HasLoadedKeysOnSave = NbLittleKeys && NbLittleKeys > 0; - Close( handle ) ; + HasLoadedSave = 1; + HasLoadedKeysOnSave = NbLittleKeys && NbLittleKeys > 0; + HasLoadedInventoryOnSave = 1; + NumCube = -1 ; FlagChgCube = 3 ; } diff --git a/SOURCES/GERELIFE.C b/SOURCES/GERELIFE.C index 089ccba..2dc28f0 100644 --- a/SOURCES/GERELIFE.C +++ b/SOURCES/GERELIFE.C @@ -757,9 +757,13 @@ void DoLife( WORD numobj ) num = *PtrPrg++ ; //If ListFlagName[num] is already populated, do nothing (this appears to allow to keep inventory when loading a save in the middle of a scene) - if (!ListFlagGame[num]) + // TODO: Fix this to predict cases where inventory is lost (when going to jail) + if (HasLoadedInventoryOnSave && !ListFlagGame[num]) ListFlagGame[num] = *PtrPrg++ ; + if (!HasLoadedInventoryOnSave) + ListFlagGame[num] = *PtrPrg++; + //Text( 0,100, "%Fset ListFlagGame %d = %d",num,ListFlagGame[num] ) ; break ; @@ -1280,4 +1284,7 @@ void DoLife( WORD numobj ) break ; } } + + + HasLoadedInventoryOnSave = 0; } diff --git a/SOURCES/GLOBAL.C b/SOURCES/GLOBAL.C index 8bf1d84..80bb129 100644 --- a/SOURCES/GLOBAL.C +++ b/SOURCES/GLOBAL.C @@ -171,7 +171,9 @@ WORD Chapitre = 0 ; WORD NbFourLeafClover = 2 ; WORD NbCloverBox = 2 ; +WORD HasLoadedSave = 0; WORD HasLoadedKeysOnSave = 0; +WORD HasLoadedInventoryOnSave = 0; WORD Island = 0 ; WORD Fuel = 0 ; diff --git a/SOURCES/OBJECT.C b/SOURCES/OBJECT.C index 0c65062..8f4ad70 100644 --- a/SOURCES/OBJECT.C +++ b/SOURCES/OBJECT.C @@ -467,13 +467,15 @@ void ChangeCube() SetLightVector( AlphaLight, BetaLight, 0 ) ; // PlayMidiFile( CubeJingle ) ; - if( NewCube != oldcube ) + if( NewCube != oldcube && !HasLoadedSave) { SaveComportement = Comportement ; SaveBeta = ListObjet[NUM_PERSO].Beta ; SaveGame() ; } + HasLoadedSave = 0; + RestartPerso() ; StartInitAllObjs() ; From 8d4e9d32fa39e66b80ed25e8e50cf281eb8f6c8b Mon Sep 17 00:00:00 2001 From: Rui Date: Sun, 19 Jun 2022 20:16:22 +0100 Subject: [PATCH 05/40] Now persisting NPCs (positioning, alive status) and objects on save files --- SOURCES/C_EXTERN.H | 1 + SOURCES/DISKFUNC.C | 199 +++++++++++++++++++++++++++++++-------------- SOURCES/GAMEMENU.C | 9 +- SOURCES/GERELIFE.C | 24 +++--- SOURCES/GLOBAL.C | 1 + SOURCES/OBJECT.C | 6 +- SOURCES/PERSO.C | 2 + 7 files changed, 167 insertions(+), 75 deletions(-) diff --git a/SOURCES/C_EXTERN.H b/SOURCES/C_EXTERN.H index c6a7617..08f98e0 100644 --- a/SOURCES/C_EXTERN.H +++ b/SOURCES/C_EXTERN.H @@ -243,6 +243,7 @@ extern WORD Fuel ; extern WORD NumPingouin ; extern WORD HasLoadedSave ; +extern WORD HasLoadedListObjetsOnSave; extern WORD HasLoadedKeysOnSave ; extern WORD HasLoadedInventoryOnSave; diff --git a/SOURCES/DISKFUNC.C b/SOURCES/DISKFUNC.C index 02987da..f4774bf 100644 --- a/SOURCES/DISKFUNC.C +++ b/SOURCES/DISKFUNC.C @@ -37,6 +37,136 @@ void RestoreDiskEnv() β–€β–€β–€β–€β–€ β–€β–€β–€β–€β–€ β–€β–€β–€β–€β–€ β–€β–€ β–€ β–€β–€β–€β–€β–€ β–€β–€β–€β–€β–€ β–€β–€ β–€β–€ β–€β–€β–€β–€β–€ β–€β–€β–€β–€β–€ *══════════════════════════════════════════════════════════════════════════*/ /*──────────────────────────────────────────────────────────────────────────*/ +void LoadObjetFromScene(WORD n, T_OBJET *ptrobj, WORD sizetoload) +{ + WORD indexfile3d; + + InitObject(n); + + ptrobj->Flags = GET_WORD; + + indexfile3d = GET_WORD; + + if (!(ptrobj->Flags & SPRITE_3D)) + { + + HQRM_Load(PATH_RESSOURCE"File3D.hqr", indexfile3d, (void**)&ptrobj->PtrFile3D); + CHECK_MEMORY + + /* ptrobj->PtrFile3D = + LoadMalloc_HQR( + PATH_RESSOURCE"File3D.hqr", + indexfile3d ) ; + */ + + } + + ptrobj->GenBody = GET_BYTE; + ptrobj->GenAnim = GET_BYTE; + /* + if( n==5 ) + { + CoulText( 15,0 ) ; + Text( 10, 300, "obj 5 org anim: %d", ptrobj->GenAnim ) ; + } + */ + + ptrobj->Sprite = GET_WORD; + + ptrobj->OldPosX = ptrobj->PosObjX = GET_WORD; + ptrobj->OldPosY = ptrobj->PosObjY = GET_WORD; + ptrobj->OldPosZ = ptrobj->PosObjZ = GET_WORD; + ptrobj->HitForce = GET_BYTE; + ptrobj->OptionFlags = GET_WORD; + ptrobj->OptionFlags &= ~EXTRA_GIVE_NOTHING; + ptrobj->Beta = GET_WORD; + ptrobj->SRot = GET_WORD; + ptrobj->Move = GET_WORD; + + ptrobj->Info = GET_WORD; + ptrobj->Info1 = GET_WORD; + ptrobj->Info2 = GET_WORD; + ptrobj->Info3 = GET_WORD; + + ptrobj->NbBonus = GET_BYTE; + ptrobj->CoulObj = GET_BYTE; + ptrobj->Armure = GET_BYTE; + ptrobj->LifePoint = GET_BYTE; + + sizetoload = GET_WORD; + ptrobj->PtrTrack = PtrSce; + PtrSce = PtrSce + sizetoload; + + sizetoload = GET_WORD; + ptrobj->PtrLife = PtrSce; + PtrSce = PtrSce + sizetoload; +} + +void LoadObjetFromSave(WORD n, T_OBJET* ptrobj, WORD sizetoload) +{ + WORD indexfile3d; + + ptrobj->Flags = GET_WORD; + indexfile3d = GET_WORD; + + if (!(ptrobj->Flags & SPRITE_3D)) + { + + HQRM_Load(PATH_RESSOURCE"File3D.hqr", indexfile3d, (void**)&ptrobj->PtrFile3D); + CHECK_MEMORY + + /* ptrobj->PtrFile3D = + LoadMalloc_HQR( + PATH_RESSOURCE"File3D.hqr", + indexfile3d ) ; + */ + + } + + if (ptrobj->LifePoint > 0) + ptrobj->GenBody = GET_BYTE; + else + { + GET_BYTE; + ptrobj->GenBody = NO_BODY; + } + + ptrobj->GenAnim = GET_BYTE; + + ptrobj->Sprite = GET_WORD; + + GET_WORD; + GET_WORD; + GET_WORD; + + ptrobj->HitForce = GET_BYTE; + ptrobj->OptionFlags = GET_WORD; + ptrobj->OptionFlags &= ~EXTRA_GIVE_NOTHING; + ptrobj->Beta = GET_WORD; + ptrobj->SRot = GET_WORD; + ptrobj->Move = GET_WORD; + + ptrobj->Info = GET_WORD; + ptrobj->Info1 = GET_WORD; + ptrobj->Info2 = GET_WORD; + ptrobj->Info3 = GET_WORD; + + ptrobj->NbBonus = GET_BYTE; + ptrobj->CoulObj = GET_BYTE; + ptrobj->Armure = GET_BYTE; + + //ptrobj->LifePoint = GET_BYTE; + GET_BYTE; + + sizetoload = GET_WORD; + ptrobj->PtrTrack = PtrSce; + PtrSce = PtrSce + sizetoload; + + sizetoload = GET_WORD; + ptrobj->PtrLife = PtrSce; + PtrSce = PtrSce + sizetoload; +} + WORD LoadScene( WORD numscene ) { @@ -45,7 +175,6 @@ WORD LoadScene( WORD numscene ) UBYTE string[256] ; UBYTE mess[256] ; WORD sizetoload ; - WORD indexfile3d ; // PtrScene = PtrSce = LoadMalloc_HQR( PATH_RESSOURCE"scene.hqr", numscene ) ; @@ -118,69 +247,19 @@ WORD LoadScene( WORD numscene ) // objets: OBJECT NbObjets = GET_WORD ; - for( n=1; nFlags = GET_WORD ; - indexfile3d = GET_WORD ; - - if( !(ptrobj->Flags & SPRITE_3D) ) + for (n = 1; n < NbObjets; n++, ptrobj++) + { + if (HasLoadedListObjetsOnSave) { - - HQRM_Load( PATH_RESSOURCE"File3D.hqr", indexfile3d, (void**)&ptrobj->PtrFile3D ) ; - CHECK_MEMORY - -/* ptrobj->PtrFile3D = - LoadMalloc_HQR( - PATH_RESSOURCE"File3D.hqr", - indexfile3d ) ; -*/ - + LoadObjetFromSave(n, ptrobj, sizetoload); + } + else + { + LoadObjetFromScene(n, ptrobj, sizetoload); } - - ptrobj->GenBody = GET_BYTE ; - ptrobj->GenAnim = GET_BYTE ; -/* -if( n==5 ) -{ - CoulText( 15,0 ) ; - Text( 10, 300, "obj 5 org anim: %d", ptrobj->GenAnim ) ; -} -*/ - - ptrobj->Sprite = GET_WORD ; - - ptrobj->OldPosX = ptrobj->PosObjX = GET_WORD ; - ptrobj->OldPosY = ptrobj->PosObjY = GET_WORD ; - ptrobj->OldPosZ = ptrobj->PosObjZ = GET_WORD ; - ptrobj->HitForce = GET_BYTE ; - ptrobj->OptionFlags = GET_WORD ; - ptrobj->OptionFlags &= ~EXTRA_GIVE_NOTHING ; - ptrobj->Beta = GET_WORD ; - ptrobj->SRot = GET_WORD ; - ptrobj->Move = GET_WORD ; - - ptrobj->Info = GET_WORD ; - ptrobj->Info1 = GET_WORD ; - ptrobj->Info2 = GET_WORD ; - ptrobj->Info3 = GET_WORD ; - - ptrobj->NbBonus = GET_BYTE ; - ptrobj->CoulObj = GET_BYTE ; - ptrobj->Armure = GET_BYTE ; - ptrobj->LifePoint = GET_BYTE ; - - sizetoload = GET_WORD ; - ptrobj->PtrTrack = PtrSce ; - PtrSce = PtrSce + sizetoload ; - - sizetoload = GET_WORD ; - ptrobj->PtrLife = PtrSce ; - PtrSce = PtrSce + sizetoload ; } - + // zone declechement: ZONE NbZones = GET_WORD ; diff --git a/SOURCES/GAMEMENU.C b/SOURCES/GAMEMENU.C index f621ab1..8db8546 100644 --- a/SOURCES/GAMEMENU.C +++ b/SOURCES/GAMEMENU.C @@ -1311,6 +1311,7 @@ void SaveGameWithName(char* fileName) Write( handle, &NbFourLeafClover, 1 ) ; Write( handle, &Weapon, 2 ) ; Write( handle, &NbLittleKeys, 1 ); + Write (handle, &ListObjet, sizeof(T_OBJET) * MAX_OBJETS); Close( handle ) ; } @@ -1323,6 +1324,7 @@ void LoadGame() WORD wword ; UBYTE wbyte ; UBYTE *ptr ; + int successKeys, successListObjets ; handle = OpenRead( GamePathname ) ; @@ -1377,12 +1379,15 @@ void LoadGame() // others Read( handle, &NbFourLeafClover, 1 ) ; Read( handle, &Weapon, 2 ) ; - Read( handle, &NbLittleKeys, 1 ); + + successKeys = Read( handle, &NbLittleKeys, 1 ); + successListObjets = Read(handle, &ListObjet, sizeof(T_OBJET) * MAX_OBJETS); Close( handle ) ; HasLoadedSave = 1; - HasLoadedKeysOnSave = NbLittleKeys && NbLittleKeys > 0; + HasLoadedListObjetsOnSave = successListObjets; + HasLoadedKeysOnSave = successKeys && NbLittleKeys > 0; HasLoadedInventoryOnSave = 1; NumCube = -1 ; diff --git a/SOURCES/GERELIFE.C b/SOURCES/GERELIFE.C index 2dc28f0..96ff322 100644 --- a/SOURCES/GERELIFE.C +++ b/SOURCES/GERELIFE.C @@ -507,7 +507,7 @@ void DoLife( WORD numobj ) break ; case LM_KILL_OBJ: - num = *PtrPrg++ ; + num = *PtrPrg++; CheckCarrier( num ) ; ListObjet[num].WorkFlags |= OBJ_DEAD ; ListObjet[num].Body = -1 ; @@ -756,13 +756,18 @@ void DoLife( WORD numobj ) case LM_SET_FLAG_GAME: num = *PtrPrg++ ; - //If ListFlagName[num] is already populated, do nothing (this appears to allow to keep inventory when loading a save in the middle of a scene) - // TODO: Fix this to predict cases where inventory is lost (when going to jail) - if (HasLoadedInventoryOnSave && !ListFlagGame[num]) - ListFlagGame[num] = *PtrPrg++ ; - - if (!HasLoadedInventoryOnSave) - ListFlagGame[num] = *PtrPrg++; + //If ListFlagName[num] is already populated for inventory, do nothing (this appears to allow to keep inventory when loading a save in the middle of a scene) + if (HasLoadedInventoryOnSave) + { + if (num < MAX_INVENTORY) + { + if (!ListFlagGame[num]) + ListFlagGame[num] = *PtrPrg++; + else *PtrPrg++; + } + else ListFlagGame[num] = *PtrPrg++; + } + else ListFlagGame[num] = *PtrPrg++; //Text( 0,100, "%Fset ListFlagGame %d = %d",num,ListFlagGame[num] ) ; @@ -1284,7 +1289,4 @@ void DoLife( WORD numobj ) break ; } } - - - HasLoadedInventoryOnSave = 0; } diff --git a/SOURCES/GLOBAL.C b/SOURCES/GLOBAL.C index 80bb129..0eaba52 100644 --- a/SOURCES/GLOBAL.C +++ b/SOURCES/GLOBAL.C @@ -172,6 +172,7 @@ WORD NbFourLeafClover = 2 ; WORD NbCloverBox = 2 ; WORD HasLoadedSave = 0; +WORD HasLoadedListObjetsOnSave = 0; WORD HasLoadedKeysOnSave = 0; WORD HasLoadedInventoryOnSave = 0; diff --git a/SOURCES/OBJECT.C b/SOURCES/OBJECT.C index 8f4ad70..d702dc7 100644 --- a/SOURCES/OBJECT.C +++ b/SOURCES/OBJECT.C @@ -46,7 +46,7 @@ void InitObject( WORD numobj ) ptrobj = &ListObjet[numobj] ; - ptrobj->GenBody = GEN_BODY_NORMAL ; + ptrobj->GenBody = GEN_BODY_NORMAL ; ptrobj->GenAnim = GEN_ANIM_RIEN ; ptrobj->PosObjX = 0 ; @@ -478,7 +478,9 @@ void ChangeCube() RestartPerso() ; - StartInitAllObjs() ; + StartInitAllObjs(); + + HasLoadedListObjetsOnSave = 0; NbLittleKeys = HasLoadedKeysOnSave ? NbLittleKeys : 0 ; MagicBall = -1 ; diff --git a/SOURCES/PERSO.C b/SOURCES/PERSO.C index ed9992f..ecd282d 100644 --- a/SOURCES/PERSO.C +++ b/SOURCES/PERSO.C @@ -957,6 +957,8 @@ startloop: } } + if (NbObjets > 0) + HasLoadedInventoryOnSave = 0; /* ptrobj = &ListObjet[ 4 ] ; CoulText( 15, 0 ) ; From 0a6d88d79d9abe7aa31ed835d22e4a75857e96e8 Mon Sep 17 00:00:00 2001 From: Rui Date: Tue, 21 Jun 2022 17:55:30 +0100 Subject: [PATCH 06/40] Now saving state of clover boxes and items on the floor. Cleared and optimized code on Diskfunc to handle saved states. --- SOURCES/DISKFUNC.C | 205 ++++++++++++++++----------------------------- SOURCES/OBJECT.C | 2 - 2 files changed, 71 insertions(+), 136 deletions(-) diff --git a/SOURCES/DISKFUNC.C b/SOURCES/DISKFUNC.C index f4774bf..f98f2b1 100644 --- a/SOURCES/DISKFUNC.C +++ b/SOURCES/DISKFUNC.C @@ -37,141 +37,12 @@ void RestoreDiskEnv() β–€β–€β–€β–€β–€ β–€β–€β–€β–€β–€ β–€β–€β–€β–€β–€ β–€β–€ β–€ β–€β–€β–€β–€β–€ β–€β–€β–€β–€β–€ β–€β–€ β–€β–€ β–€β–€β–€β–€β–€ β–€β–€β–€β–€β–€ *══════════════════════════════════════════════════════════════════════════*/ /*──────────────────────────────────────────────────────────────────────────*/ -void LoadObjetFromScene(WORD n, T_OBJET *ptrobj, WORD sizetoload) -{ - WORD indexfile3d; - - InitObject(n); - - ptrobj->Flags = GET_WORD; - - indexfile3d = GET_WORD; - - if (!(ptrobj->Flags & SPRITE_3D)) - { - - HQRM_Load(PATH_RESSOURCE"File3D.hqr", indexfile3d, (void**)&ptrobj->PtrFile3D); - CHECK_MEMORY - - /* ptrobj->PtrFile3D = - LoadMalloc_HQR( - PATH_RESSOURCE"File3D.hqr", - indexfile3d ) ; - */ - - } - - ptrobj->GenBody = GET_BYTE; - ptrobj->GenAnim = GET_BYTE; - /* - if( n==5 ) - { - CoulText( 15,0 ) ; - Text( 10, 300, "obj 5 org anim: %d", ptrobj->GenAnim ) ; - } - */ - - ptrobj->Sprite = GET_WORD; - - ptrobj->OldPosX = ptrobj->PosObjX = GET_WORD; - ptrobj->OldPosY = ptrobj->PosObjY = GET_WORD; - ptrobj->OldPosZ = ptrobj->PosObjZ = GET_WORD; - ptrobj->HitForce = GET_BYTE; - ptrobj->OptionFlags = GET_WORD; - ptrobj->OptionFlags &= ~EXTRA_GIVE_NOTHING; - ptrobj->Beta = GET_WORD; - ptrobj->SRot = GET_WORD; - ptrobj->Move = GET_WORD; - - ptrobj->Info = GET_WORD; - ptrobj->Info1 = GET_WORD; - ptrobj->Info2 = GET_WORD; - ptrobj->Info3 = GET_WORD; - - ptrobj->NbBonus = GET_BYTE; - ptrobj->CoulObj = GET_BYTE; - ptrobj->Armure = GET_BYTE; - ptrobj->LifePoint = GET_BYTE; - - sizetoload = GET_WORD; - ptrobj->PtrTrack = PtrSce; - PtrSce = PtrSce + sizetoload; - - sizetoload = GET_WORD; - ptrobj->PtrLife = PtrSce; - PtrSce = PtrSce + sizetoload; -} - -void LoadObjetFromSave(WORD n, T_OBJET* ptrobj, WORD sizetoload) -{ - WORD indexfile3d; - - ptrobj->Flags = GET_WORD; - indexfile3d = GET_WORD; - - if (!(ptrobj->Flags & SPRITE_3D)) - { - - HQRM_Load(PATH_RESSOURCE"File3D.hqr", indexfile3d, (void**)&ptrobj->PtrFile3D); - CHECK_MEMORY - - /* ptrobj->PtrFile3D = - LoadMalloc_HQR( - PATH_RESSOURCE"File3D.hqr", - indexfile3d ) ; - */ - - } - - if (ptrobj->LifePoint > 0) - ptrobj->GenBody = GET_BYTE; - else - { - GET_BYTE; - ptrobj->GenBody = NO_BODY; - } - - ptrobj->GenAnim = GET_BYTE; - - ptrobj->Sprite = GET_WORD; - - GET_WORD; - GET_WORD; - GET_WORD; - - ptrobj->HitForce = GET_BYTE; - ptrobj->OptionFlags = GET_WORD; - ptrobj->OptionFlags &= ~EXTRA_GIVE_NOTHING; - ptrobj->Beta = GET_WORD; - ptrobj->SRot = GET_WORD; - ptrobj->Move = GET_WORD; - - ptrobj->Info = GET_WORD; - ptrobj->Info1 = GET_WORD; - ptrobj->Info2 = GET_WORD; - ptrobj->Info3 = GET_WORD; - - ptrobj->NbBonus = GET_BYTE; - ptrobj->CoulObj = GET_BYTE; - ptrobj->Armure = GET_BYTE; - - //ptrobj->LifePoint = GET_BYTE; - GET_BYTE; - - sizetoload = GET_WORD; - ptrobj->PtrTrack = PtrSce; - PtrSce = PtrSce + sizetoload; - - sizetoload = GET_WORD; - ptrobj->PtrLife = PtrSce; - PtrSce = PtrSce + sizetoload; -} - WORD LoadScene( WORD numscene ) { T_OBJET *ptrobj ; WORD n, info3 ; + WORD indexfile3d; UBYTE string[256] ; UBYTE mess[256] ; WORD sizetoload ; @@ -250,16 +121,82 @@ WORD LoadScene( WORD numscene ) for (n = 1; n < NbObjets; n++, ptrobj++) { - if (HasLoadedListObjetsOnSave) + WORD savedLifePoint = ptrobj->LifePoint; + + InitObject(n); + + ptrobj->Flags = GET_WORD; + + indexfile3d = GET_WORD; + + if (!(ptrobj->Flags & SPRITE_3D)) { - LoadObjetFromSave(n, ptrobj, sizetoload); + + HQRM_Load(PATH_RESSOURCE"File3D.hqr", indexfile3d, (void**)&ptrobj->PtrFile3D); + CHECK_MEMORY + + /* ptrobj->PtrFile3D = + LoadMalloc_HQR( + PATH_RESSOURCE"File3D.hqr", + indexfile3d ) ; + */ + } - else + + ptrobj->GenBody = GET_BYTE; + ptrobj->GenAnim = GET_BYTE; + /* + if( n==5 ) + { + CoulText( 15,0 ) ; + Text( 10, 300, "obj 5 org anim: %d", ptrobj->GenAnim ) ; + } + */ + + ptrobj->Sprite = GET_WORD; + + ptrobj->OldPosX = ptrobj->PosObjX = GET_WORD; + ptrobj->OldPosY = ptrobj->PosObjY = GET_WORD; + ptrobj->OldPosZ = ptrobj->PosObjZ = GET_WORD; + ptrobj->HitForce = GET_BYTE; + ptrobj->OptionFlags = GET_WORD; + ptrobj->OptionFlags &= ~EXTRA_GIVE_NOTHING; + ptrobj->Beta = GET_WORD; + ptrobj->SRot = GET_WORD; + ptrobj->Move = GET_WORD; + + ptrobj->Info = GET_WORD; + ptrobj->Info1 = GET_WORD; + ptrobj->Info2 = GET_WORD; + ptrobj->Info3 = GET_WORD; + + ptrobj->NbBonus = GET_BYTE; + ptrobj->CoulObj = GET_BYTE; + ptrobj->Armure = GET_BYTE; + ptrobj->LifePoint = GET_BYTE; + + sizetoload = GET_WORD; + ptrobj->PtrTrack = PtrSce; + PtrSce = PtrSce + sizetoload; + + sizetoload = GET_WORD; + ptrobj->PtrLife = PtrSce; + PtrSce = PtrSce + sizetoload; + + //Do not render object if it's marked as dead on save + if (HasLoadedListObjetsOnSave && savedLifePoint <= 0) { - LoadObjetFromScene(n, ptrobj, sizetoload); + ptrobj->GenBody = NO_BODY; + ptrobj->WorkFlags |= OBJ_DEAD; + ptrobj->Sprite = -1; + ptrobj->Body = -1; + ptrobj->ZoneSce = -1; + ptrobj->LifePoint = 0; } } + HasLoadedListObjetsOnSave = 0; + // zone declechement: ZONE NbZones = GET_WORD ; diff --git a/SOURCES/OBJECT.C b/SOURCES/OBJECT.C index d702dc7..ebe6aea 100644 --- a/SOURCES/OBJECT.C +++ b/SOURCES/OBJECT.C @@ -480,8 +480,6 @@ void ChangeCube() StartInitAllObjs(); - HasLoadedListObjetsOnSave = 0; - NbLittleKeys = HasLoadedKeysOnSave ? NbLittleKeys : 0 ; MagicBall = -1 ; LastJoyFlag = TRUE ; From b112e5c0b6c1d5a3991c327b0ee194c55742e2e6 Mon Sep 17 00:00:00 2001 From: Rui Date: Tue, 21 Jun 2022 18:37:49 +0100 Subject: [PATCH 07/40] Fixed new save and replace save menu titles --- SOURCES/GAMEMENU.C | 40 +++++++++++++++++++++++----------------- 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/SOURCES/GAMEMENU.C b/SOURCES/GAMEMENU.C index 8db8546..69683dc 100644 --- a/SOURCES/GAMEMENU.C +++ b/SOURCES/GAMEMENU.C @@ -206,6 +206,24 @@ void WaitReleaseSpace() RestoreTimer() ; } +char* GetMenuMultiTextAux(WORD num, char* dst) +{ + char* multiTextPtr = GetMultiText(num, dst); + + // IF text reference doesn't exist in TEXT.HQR file, use text in source code + if (!multiTextPtr) + { + char* customTextPtr = GetCustomizedMultiText(num); + + if (customTextPtr) + strcpy(dst, customTextPtr); + + free(customTextPtr); + } + + return dst; +} + /*══════════════════════════════════════════════════════════════════════════* β–ˆβ–€β–€β–€β–€ β–ˆβ–€β–€β–€β–ˆ β–ˆβ–„ β–„β–ˆ β–ˆβ–€β–€β–€β–€ β–ˆβ–„ β–„β–ˆ β–ˆβ–€β–€β–€β–€ β–ˆβ–ˆβ–„ β–ˆ β–ˆ β–ˆ β–ˆβ–ˆ β–€β–ˆ β–ˆβ–ˆβ–€β–€β–ˆ β–ˆβ–ˆβ–€ β–ˆ β–ˆβ–ˆβ–€β–€ β–ˆβ–ˆβ–€ β–ˆ β–ˆβ–ˆβ–€β–€ β–ˆβ–ˆβ–€β–ˆβ–ˆ β–ˆβ–ˆ β–ˆ @@ -1587,7 +1605,7 @@ try_again: InitDial( 0 ) ; - GetMultiText( nummess, string ) ; + GetMenuMultiTextAux( nummess, string ) ; CoulFont( COUL_LETTER_INPUT ) ; Font( 320 - SizeFont(string)/2, 20, string ) ; CopyBlockPhys( 0,0,639,99 ) ; @@ -1772,7 +1790,7 @@ WORD ChoosePlayerName( WORD mess ) InitDial( 0 ) ; - DrawSingleString( 320, 40, (UBYTE*)GetMultiText( mess,string ) ) ; + DrawSingleString( 320, 40, (UBYTE*)GetMenuMultiTextAux( mess,string ) ) ; while( Key != K_ESC ) { @@ -1855,7 +1873,6 @@ WORD ChoosePlayerName( WORD mess ) void DrawOneChoice( WORD x, WORD y, WORD type, WORD num, WORD select ) { - char* multiTextPtr; WORD x2, x0,y0,x1,y1 ; UBYTE string[256] ; ULONG volleft, volright ; @@ -1934,18 +1951,7 @@ void DrawOneChoice( WORD x, WORD y, WORD type, WORD num, WORD select ) // text CoulFont( COUL_TEXT_MENU ) ; - multiTextPtr = GetMultiText( num, string ) ; - - // IF text reference doesn't exist in TEXT.HQR file, use text in source code - if(!multiTextPtr) - { - char *customTextPtr = GetCustomizedMultiText( num ); - - if (customTextPtr) - strcpy(string, customTextPtr); - - free(customTextPtr); - } + GetMenuMultiTextAux( num, string ) ; Font( x - SizeFont( string )/2, y-18, string ) ; @@ -2723,7 +2729,7 @@ LONG QuitMenu() break; case 950: - if (InputPlayerName(44)) + if (InputPlayerName(950)) { SaveComportement = Comportement; SaveBeta = ListObjet[NUM_PERSO].Beta; @@ -2739,7 +2745,7 @@ LONG QuitMenu() break; case 951: - if (ChoosePlayerName(41)) + if (ChoosePlayerName(951)) { SaveComportement = Comportement; SaveBeta = ListObjet[NUM_PERSO].Beta; From 8bf69f40dce6dad661a7a35693ad7248d7d547cf Mon Sep 17 00:00:00 2001 From: Rui Date: Tue, 21 Jun 2022 19:41:33 +0100 Subject: [PATCH 08/40] Added missing code, for retaining NPC position and other object states, after code refactoring. Also additional code optimizations for keeping saved states in LoadScene in DiskFunc --- SOURCES/DISKFUNC.C | 37 ++++++++++++++++++++++++++++--------- 1 file changed, 28 insertions(+), 9 deletions(-) diff --git a/SOURCES/DISKFUNC.C b/SOURCES/DISKFUNC.C index f98f2b1..cc1e1a7 100644 --- a/SOURCES/DISKFUNC.C +++ b/SOURCES/DISKFUNC.C @@ -121,7 +121,15 @@ WORD LoadScene( WORD numscene ) for (n = 1; n < NbObjets; n++, ptrobj++) { - WORD savedLifePoint = ptrobj->LifePoint; + T_OBJET* savedPtrObj; + + if (HasLoadedListObjetsOnSave) + { + savedPtrObj = malloc(sizeof(T_OBJET)); + + if (savedPtrObj) + *savedPtrObj = *ptrobj; + } InitObject(n); @@ -183,15 +191,26 @@ WORD LoadScene( WORD numscene ) ptrobj->PtrLife = PtrSce; PtrSce = PtrSce + sizetoload; - //Do not render object if it's marked as dead on save - if (HasLoadedListObjetsOnSave && savedLifePoint <= 0) + //If loading from a save, replace content with the saved one (but keep the SCENE.HQR file reading flow from LoadScene for other necessary readings afterwards) + if (HasLoadedListObjetsOnSave && savedPtrObj) { - ptrobj->GenBody = NO_BODY; - ptrobj->WorkFlags |= OBJ_DEAD; - ptrobj->Sprite = -1; - ptrobj->Body = -1; - ptrobj->ZoneSce = -1; - ptrobj->LifePoint = 0; + //Starting animation will still be the one from SCENE.HQR file (this is to avoid a glitch when a NPC is in the middle of an animation when a save is made, other than the default one like getting hit) + savedPtrObj->GenAnim = ptrobj->GenAnim; + + //This will retain NPC and object position and other states when loading a save + *ptrobj = *savedPtrObj; + + //Do not render object if it's marked as dead on save + if (savedPtrObj->LifePoint <= 0) + { + ptrobj->GenBody = NO_BODY; + ptrobj->WorkFlags |= OBJ_DEAD; + ptrobj->Sprite = -1; + ptrobj->Body = -1; + ptrobj->ZoneSce = -1; + } + + free(savedPtrObj); } } From c1e6da37b68a3d6e22cd3a90a489431ae07d72be Mon Sep 17 00:00:00 2001 From: Rui Date: Wed, 22 Jun 2022 00:45:00 +0100 Subject: [PATCH 09/40] Work done for saving ListZone state (for hidden items in trash cans, barrels, bins, etc). Also work for ListExtra but still preliminary --- SOURCES/C_EXTERN.H | 1 + SOURCES/DISKFUNC.C | 9 +++++---- SOURCES/GAMEMENU.C | 32 ++++++++++++++++++++++++++++---- SOURCES/GLOBAL.C | 1 + 4 files changed, 35 insertions(+), 8 deletions(-) diff --git a/SOURCES/C_EXTERN.H b/SOURCES/C_EXTERN.H index 08f98e0..cef3211 100644 --- a/SOURCES/C_EXTERN.H +++ b/SOURCES/C_EXTERN.H @@ -244,6 +244,7 @@ extern WORD NumPingouin ; extern WORD HasLoadedSave ; extern WORD HasLoadedListObjetsOnSave; +extern WORD HasLoadedListZoneOnSave; extern WORD HasLoadedKeysOnSave ; extern WORD HasLoadedInventoryOnSave; diff --git a/SOURCES/DISKFUNC.C b/SOURCES/DISKFUNC.C index cc1e1a7..9ca7277 100644 --- a/SOURCES/DISKFUNC.C +++ b/SOURCES/DISKFUNC.C @@ -213,13 +213,11 @@ WORD LoadScene( WORD numscene ) free(savedPtrObj); } } - - HasLoadedListObjetsOnSave = 0; // zone declechement: ZONE - NbZones = GET_WORD ; - ListZone = (T_ZONE*)PtrSce ; + if (!HasLoadedListZoneOnSave) //add flag for zones + ListZone = (T_ZONE*)PtrSce ; PtrSce += NbZones * 12 * 2 ; // point track: TRACK @@ -227,6 +225,9 @@ WORD LoadScene( WORD numscene ) NbBrickTrack = GET_WORD ; ListBrickTrack = (T_TRACK*)PtrSce ; + HasLoadedListObjetsOnSave = 0; + HasLoadedListZoneOnSave = 0; + return TRUE ; } diff --git a/SOURCES/GAMEMENU.C b/SOURCES/GAMEMENU.C index 69683dc..3312d1b 100644 --- a/SOURCES/GAMEMENU.C +++ b/SOURCES/GAMEMENU.C @@ -1258,6 +1258,7 @@ void SaveGameWithName(char* fileName) FILE* handle ; WORD wword ; UBYTE wbyte ; + int i; if (fileName) { @@ -1329,7 +1330,15 @@ void SaveGameWithName(char* fileName) Write( handle, &NbFourLeafClover, 1 ) ; Write( handle, &Weapon, 2 ) ; Write( handle, &NbLittleKeys, 1 ); - Write (handle, &ListObjet, sizeof(T_OBJET) * MAX_OBJETS); + Write( handle, &ListObjet, sizeof(T_OBJET) * MAX_OBJETS ); + Write( handle, &ListExtra, sizeof(T_EXTRA) * MAX_EXTRAS ); + Write( handle, &NbZones, 2 ); + + //Iterating for ListZone because it has a different data type + for (i = 0; i < NbZones; i++) + { + Write(handle, &ListZone[i], sizeof(T_ZONE)); + } Close( handle ) ; } @@ -1342,7 +1351,9 @@ void LoadGame() WORD wword ; UBYTE wbyte ; UBYTE *ptr ; - int successKeys, successListObjets ; + int successInventory, successKeys, successListObjets, successNbZones; + int successListZones = 1; + int i; handle = OpenRead( GamePathname ) ; @@ -1358,7 +1369,8 @@ void LoadGame() // list flag game Read( handle, &wbyte, 1 ) ; // nb octets - Read( handle, ListFlagGame, wbyte ) ; + + successInventory = Read( handle, ListFlagGame, wbyte ) ; NewCube = 0 ; Read( handle, &NewCube, 1 ) ; @@ -1400,13 +1412,25 @@ void LoadGame() successKeys = Read( handle, &NbLittleKeys, 1 ); successListObjets = Read(handle, &ListObjet, sizeof(T_OBJET) * MAX_OBJETS); + Read(handle, &ListExtra, sizeof(T_EXTRA) * MAX_EXTRAS); + successNbZones = Read(handle, &NbZones, 2); + + ListZone = malloc(sizeof(T_ZONE) * NbZones); + + //Iterating for ListZone because it has a different data type + for (i = 0; i < NbZones; i++) + { + successListZones &= Read(handle, &ListZone[i], sizeof(T_ZONE)); + } Close( handle ) ; + //These flags are here to help the code identify if objects in a scene are coming from a save or from the HQR file. They also help with keeping retro compatibility with previous version save files HasLoadedSave = 1; + HasLoadedInventoryOnSave = successInventory; HasLoadedListObjetsOnSave = successListObjets; + HasLoadedListZoneOnSave = successNbZones && NbZones > 0 && successListZones; HasLoadedKeysOnSave = successKeys && NbLittleKeys > 0; - HasLoadedInventoryOnSave = 1; NumCube = -1 ; FlagChgCube = 3 ; diff --git a/SOURCES/GLOBAL.C b/SOURCES/GLOBAL.C index 0eaba52..8e2bda6 100644 --- a/SOURCES/GLOBAL.C +++ b/SOURCES/GLOBAL.C @@ -173,6 +173,7 @@ WORD NbCloverBox = 2 ; WORD HasLoadedSave = 0; WORD HasLoadedListObjetsOnSave = 0; +WORD HasLoadedListZoneOnSave = 0; WORD HasLoadedKeysOnSave = 0; WORD HasLoadedInventoryOnSave = 0; From dfcd516a296c418a58df100ca2149a40a2eceb75 Mon Sep 17 00:00:00 2001 From: Rui Date: Wed, 22 Jun 2022 17:24:28 +0100 Subject: [PATCH 10/40] Now persisting and loading extra items generated from bins, trash cans, containers, killed NPCs, etc. --- SOURCES/C_EXTERN.H | 1 + SOURCES/EXTRA.C | 12 ++++++++++-- SOURCES/GAMEMENU.C | 12 +++++++----- SOURCES/GLOBAL.C | 1 + SOURCES/OBJECT.C | 2 ++ 5 files changed, 21 insertions(+), 7 deletions(-) diff --git a/SOURCES/C_EXTERN.H b/SOURCES/C_EXTERN.H index cef3211..6933946 100644 --- a/SOURCES/C_EXTERN.H +++ b/SOURCES/C_EXTERN.H @@ -244,6 +244,7 @@ extern WORD NumPingouin ; extern WORD HasLoadedSave ; extern WORD HasLoadedListObjetsOnSave; +extern WORD HasLoadedListExtraOnSave; extern WORD HasLoadedListZoneOnSave; extern WORD HasLoadedKeysOnSave ; extern WORD HasLoadedInventoryOnSave; diff --git a/SOURCES/EXTRA.C b/SOURCES/EXTRA.C index 1d04e12..8a68e7d 100644 --- a/SOURCES/EXTRA.C +++ b/SOURCES/EXTRA.C @@ -677,8 +677,16 @@ void ClearExtra() for( n=0; n 0 && successListZones; HasLoadedKeysOnSave = successKeys && NbLittleKeys > 0; @@ -2724,7 +2725,7 @@ LONG QuitMenu() InitGame(-1, 0); -/* if (MainLoop()) + if (MainLoop()) { #ifdef DEMO PlayMidiFile(6); @@ -2737,11 +2738,12 @@ LONG QuitMenu() Flip(); Palette(PtrPal); #endif - }*/ + } CopyScreen(Log, Screen); while (Key OR Fire); // provisoire - retValue = FALSE; + //Returning false was blocking the menu sometimes, returning true should stop the previous main loop game flow, doesn't appear to cause issues + retValue = TRUE; break; case 27: // abandonner diff --git a/SOURCES/GLOBAL.C b/SOURCES/GLOBAL.C index 8e2bda6..7f5fe02 100644 --- a/SOURCES/GLOBAL.C +++ b/SOURCES/GLOBAL.C @@ -173,6 +173,7 @@ WORD NbCloverBox = 2 ; WORD HasLoadedSave = 0; WORD HasLoadedListObjetsOnSave = 0; +WORD HasLoadedListExtraOnSave = 0; WORD HasLoadedListZoneOnSave = 0; WORD HasLoadedKeysOnSave = 0; WORD HasLoadedInventoryOnSave = 0; diff --git a/SOURCES/OBJECT.C b/SOURCES/OBJECT.C index ebe6aea..2fde654 100644 --- a/SOURCES/OBJECT.C +++ b/SOURCES/OBJECT.C @@ -404,6 +404,8 @@ void ChangeCube() FreeGrille() ; ClearScene() ; + HasLoadedListExtraOnSave = 0; + // perso reinit LoadFicPerso() ; From b61e5c576dc417dfbd0602920660f7eb027c1e48 Mon Sep 17 00:00:00 2001 From: Rui Date: Wed, 22 Jun 2022 19:59:35 +0100 Subject: [PATCH 11/40] Fixed RestoreTimer when using the new ingame load game option. Refactored code to initialize loaded game after the previous main loop has ended, to avoid excess overhead (could probably do with some optimizations still...) --- SOURCES/DEFINES.H | 2 + SOURCES/GAMEMENU.C | 99 +++++++++++++++++++--------------------------- SOURCES/PERSO.C | 21 +++++++--- 3 files changed, 59 insertions(+), 63 deletions(-) diff --git a/SOURCES/DEFINES.H b/SOURCES/DEFINES.H index 4d274c4..cd6520c 100644 --- a/SOURCES/DEFINES.H +++ b/SOURCES/DEFINES.H @@ -150,6 +150,8 @@ extern ULONG UsedHQMemory ; #define GEN_ANIM_SABRE 23 #define GEN_ANIM_DEGAINE 24 +#define MAIN_LOOP_LOAD_GAME 3 + /*──────────────────────────────────────────────────────────────────────────*/ /*──────────────────────────────────────────────────────────────────────────*/ typedef struct diff --git a/SOURCES/GAMEMENU.C b/SOURCES/GAMEMENU.C index e494ddf..b16fe5a 100644 --- a/SOURCES/GAMEMENU.C +++ b/SOURCES/GAMEMENU.C @@ -175,6 +175,39 @@ extern WORD IndexGrm ; /*══════════════════════════════════════════════════════════════════════════* *══════════════════════════════════════════════════════════════════════════*/ /*──────────────────────────────────────────────────────────────────────────*/ +void MenuInitGame(int argc, UBYTE* argv[], WORD showIntroduction) +{ + int retMainLoop; + + InitGame(argc, argv); + + if (showIntroduction) + Introduction(); + + if (retMainLoop = MainLoop()) + { +#ifdef DEMO + PlayMidiFile(6); + Credits(); + TheEnd(PROGRAM_OK, "* End of Demo version."); +#else + if (retMainLoop == MAIN_LOOP_LOAD_GAME) + { + MenuInitGame(-1, 0, 0); + } + else + { + Credits(); + PlayAnimFla("The_End"); + Cls(); + Flip(); + Palette(PtrPal); + } +#endif + } + CopyScreen(Log, Screen); +} + void Init3DGame() { @@ -2638,48 +2671,15 @@ LONG MainGameMenu() } while( FileSize( GamePathname ) != 0 ) ; - InitGame( 1, 0 ) ; - Introduction() ; - if( MainLoop() ) - { -#ifdef DEMO - PlayMidiFile( 6 ) ; - Credits() ; - TheEnd( PROGRAM_OK, "* End of Demo version." ) ; -#else - Credits() ; - PlayAnimFla( "The_End" ) ; - Cls() ; - Flip() ; - Palette( PtrPal ) ; -#endif - } - - CopyScreen( Log, Screen ) ; + MenuInitGame(1,0,1); while( Key OR Fire ) ; // provisoire break ; case 21: // load if( !ChoosePlayerName( 21 ) ) break ; - - InitGame( -1, 0 ) ; - //Introduction() ; - if( MainLoop() ) - { -#ifdef DEMO - PlayMidiFile( 6 ) ; - Credits() ; - TheEnd( PROGRAM_OK, "* End of Demo version." ) ; -#else - Credits() ; - PlayAnimFla( "The_End" ) ; - Cls() ; - Flip() ; - Palette( PtrPal ) ; -#endif - } - CopyScreen( Log, Screen ) ; + + MenuInitGame(-1,0,0); while( Key OR Fire ) ; // provisoire break ; @@ -2723,35 +2723,18 @@ LONG QuitMenu() case 21: // load if (!ChoosePlayerName(21)) break; - InitGame(-1, 0); - - if (MainLoop()) - { - #ifdef DEMO - PlayMidiFile(6); - Credits(); - TheEnd(PROGRAM_OK, "* End of Demo version."); - #else - Credits(); - PlayAnimFla("The_End"); - Cls(); - Flip(); - Palette(PtrPal); - #endif - } - CopyScreen(Log, Screen); while (Key OR Fire); // provisoire //Returning false was blocking the menu sometimes, returning true should stop the previous main loop game flow, doesn't appear to cause issues - retValue = TRUE; + retValue = 2; break; case 27: // abandonner - retValue = TRUE; + retValue = 1; break; case 28: // continue - retValue = FALSE; + retValue = 0; break; case 950: @@ -2767,7 +2750,7 @@ LONG QuitMenu() SaveGameWithName(PlayerName); } - retValue = FALSE; + retValue = 0; break; case 951: @@ -2783,7 +2766,7 @@ LONG QuitMenu() SaveGameWithName(PlayerName); } - retValue = FALSE; + retValue = 0; break; } } diff --git a/SOURCES/PERSO.C b/SOURCES/PERSO.C index ecd282d..ecfe384 100644 --- a/SOURCES/PERSO.C +++ b/SOURCES/PERSO.C @@ -406,19 +406,30 @@ startloop: AND (!(ListObjet[NUM_PERSO].Flags&INVISIBLE)) ) { + int retQuitMenu; + // confirmation sortie TestRestoreModeSVGA( TRUE ) ; SaveTimer() ; - if( QuitMenu() ) + retQuitMenu = QuitMenu(); + if( retQuitMenu == 2) { RestoreTimer() ; AffScene( TRUE ) ; - SaveTimer() ; - SaveGame() ; - RestoreTimer() ; - break ; + return MAIN_LOOP_LOAD_GAME; + } + else if (retQuitMenu == 1) + { + RestoreTimer(); + AffScene(TRUE); + + //SaveTimer() ; + //SaveGame() ; + //RestoreTimer() ; + + break; } else { From 2f09f07f90b6267b2b93b6820c5d0533338a376e Mon Sep 17 00:00:00 2001 From: Rui Date: Thu, 23 Jun 2022 16:33:32 +0100 Subject: [PATCH 12/40] Work done to load NPC tracks state as they were at the moment of saving --- SOURCES/C_EXTERN.H | 1 + SOURCES/DEFINES.H | 2 ++ SOURCES/DISKFUNC.C | 8 ++++++-- SOURCES/GAMEMENU.C | 1 + SOURCES/GERELIFE.C | 14 ++++++++++++-- SOURCES/GERETRAK.C | 9 ++++++--- SOURCES/GLOBAL.C | 1 + SOURCES/OBJECT.C | 10 +++++++--- SOURCES/PERSO.C | 3 +++ 9 files changed, 39 insertions(+), 10 deletions(-) diff --git a/SOURCES/C_EXTERN.H b/SOURCES/C_EXTERN.H index 6933946..0fd5121 100644 --- a/SOURCES/C_EXTERN.H +++ b/SOURCES/C_EXTERN.H @@ -244,6 +244,7 @@ extern WORD NumPingouin ; extern WORD HasLoadedSave ; extern WORD HasLoadedListObjetsOnSave; +extern WORD HasLoadedListObjetTracksOnSave; extern WORD HasLoadedListExtraOnSave; extern WORD HasLoadedListZoneOnSave; extern WORD HasLoadedKeysOnSave ; diff --git a/SOURCES/DEFINES.H b/SOURCES/DEFINES.H index cd6520c..4ff27c0 100644 --- a/SOURCES/DEFINES.H +++ b/SOURCES/DEFINES.H @@ -245,6 +245,8 @@ typedef struct UBYTE CodeJeu ; // brick spΓ©ciale sample ou action + UBYTE MemoTrackGenAnim ; + } T_OBJET ; /* diff --git a/SOURCES/DISKFUNC.C b/SOURCES/DISKFUNC.C index 9ca7277..cb9a216 100644 --- a/SOURCES/DISKFUNC.C +++ b/SOURCES/DISKFUNC.C @@ -195,7 +195,8 @@ WORD LoadScene( WORD numscene ) if (HasLoadedListObjetsOnSave && savedPtrObj) { //Starting animation will still be the one from SCENE.HQR file (this is to avoid a glitch when a NPC is in the middle of an animation when a save is made, other than the default one like getting hit) - savedPtrObj->GenAnim = ptrobj->GenAnim; + //If the NPC has a tracking flow, attempt to use the last memorized track animation + savedPtrObj->GenAnim = savedPtrObj->OffsetTrack != -1 && savedPtrObj->MemoTrackGenAnim ? savedPtrObj->MemoTrackGenAnim : ptrobj->GenAnim; //This will retain NPC and object position and other states when loading a save *ptrobj = *savedPtrObj; @@ -204,10 +205,13 @@ WORD LoadScene( WORD numscene ) if (savedPtrObj->LifePoint <= 0) { ptrobj->GenBody = NO_BODY; + ptrobj->GenAnim = GEN_ANIM_RIEN; ptrobj->WorkFlags |= OBJ_DEAD; ptrobj->Sprite = -1; ptrobj->Body = -1; ptrobj->ZoneSce = -1; + ptrobj->OffsetLife = -1; + ptrobj->OffsetTrack = -1; } free(savedPtrObj); @@ -225,8 +229,8 @@ WORD LoadScene( WORD numscene ) NbBrickTrack = GET_WORD ; ListBrickTrack = (T_TRACK*)PtrSce ; - HasLoadedListObjetsOnSave = 0; HasLoadedListZoneOnSave = 0; + HasLoadedListObjetsOnSave = 0; return TRUE ; } diff --git a/SOURCES/GAMEMENU.C b/SOURCES/GAMEMENU.C index b16fe5a..26ec403 100644 --- a/SOURCES/GAMEMENU.C +++ b/SOURCES/GAMEMENU.C @@ -1462,6 +1462,7 @@ void LoadGame() HasLoadedSave = 1; HasLoadedInventoryOnSave = successInventory; HasLoadedListObjetsOnSave = successListObjets; + HasLoadedListObjetTracksOnSave = successListObjets; HasLoadedListExtraOnSave = successListExtras; HasLoadedListZoneOnSave = successNbZones && NbZones > 0 && successListZones; HasLoadedKeysOnSave = successKeys && NbLittleKeys > 0; diff --git a/SOURCES/GERELIFE.C b/SOURCES/GERELIFE.C index 96ff322..acde632 100644 --- a/SOURCES/GERELIFE.C +++ b/SOURCES/GERELIFE.C @@ -571,13 +571,23 @@ void DoLife( WORD numobj ) break ; case LM_SET_TRACK: - ptrobj->OffsetTrack = *(WORD*)PtrPrg ; + if (HasLoadedListObjetTracksOnSave) + { + if (ptrobj->OffsetTrack == -1) + ptrobj->OffsetTrack = *(WORD*)PtrPrg; + } + else ptrobj->OffsetTrack = *(WORD*)PtrPrg ; PtrPrg += 2 ; break ; case LM_SET_TRACK_OBJ: num = *PtrPrg++ ; - ListObjet[num].OffsetTrack = *(WORD*)PtrPrg ; + if (HasLoadedListObjetTracksOnSave) + { + if (ptrobj->OffsetTrack == -1) + ListObjet[num].OffsetTrack = *(WORD*)PtrPrg; + } + else ListObjet[num].OffsetTrack = *(WORD*)PtrPrg; PtrPrg += 2 ; break ; diff --git a/SOURCES/GERETRAK.C b/SOURCES/GERETRAK.C index a8d1fff..23604c2 100644 --- a/SOURCES/GERETRAK.C +++ b/SOURCES/GERETRAK.C @@ -24,6 +24,7 @@ void DoTrack( WORD numobj ) WORD overflow = 0 ; UBYTE *ptr ; UBYTE n, c ; + UBYTE memoanimtrack; ptrobj = &ListObjet[numobj] ; @@ -107,15 +108,17 @@ void DoTrack( WORD numobj ) /*-------------------------------------------------------------------------*/ case TM_ANIM: - if( !InitAnim( *ptrtrack++, ANIM_REPEAT, 0, numobj ) ) - { + memoanimtrack = *ptrtrack++; + if (!InitAnim(memoanimtrack, ANIM_REPEAT, 0, numobj)) + { ptrobj->OffsetTrack = memooffsettrack ; flag = FALSE ; } else { - ptrobj->OffsetTrack++ ; + ptrobj->MemoTrackGenAnim = memoanimtrack; + ptrobj->OffsetTrack++; } break ; diff --git a/SOURCES/GLOBAL.C b/SOURCES/GLOBAL.C index 7f5fe02..e6dc17b 100644 --- a/SOURCES/GLOBAL.C +++ b/SOURCES/GLOBAL.C @@ -173,6 +173,7 @@ WORD NbCloverBox = 2 ; WORD HasLoadedSave = 0; WORD HasLoadedListObjetsOnSave = 0; +WORD HasLoadedListObjetTracksOnSave = 0; WORD HasLoadedListExtraOnSave = 0; WORD HasLoadedListZoneOnSave = 0; WORD HasLoadedKeysOnSave = 0; diff --git a/SOURCES/OBJECT.C b/SOURCES/OBJECT.C index 2fde654..e752905 100644 --- a/SOURCES/OBJECT.C +++ b/SOURCES/OBJECT.C @@ -144,9 +144,13 @@ void StartInitObj( WORD numobj ) 0, &ptrobj->RealAngle ) ; } - ptrobj->OffsetTrack = -1 ; - ptrobj->LabelTrack = -1 ; - ptrobj->OffsetLife = 0 ; + + if (!HasLoadedListObjetTracksOnSave) + { + ptrobj->OffsetTrack = -1 ; + ptrobj->LabelTrack = -1 ; + ptrobj->OffsetLife = 0; + } } diff --git a/SOURCES/PERSO.C b/SOURCES/PERSO.C index ecfe384..99b52d3 100644 --- a/SOURCES/PERSO.C +++ b/SOURCES/PERSO.C @@ -969,7 +969,10 @@ startloop: } if (NbObjets > 0) + { HasLoadedInventoryOnSave = 0; + HasLoadedListObjetTracksOnSave = 0; + } /* ptrobj = &ListObjet[ 4 ] ; CoulText( 15, 0 ) ; From 8cccae7ffe0b293bb5bcfbea6de0803af3ac6b69 Mon Sep 17 00:00:00 2001 From: Rui Date: Thu, 23 Jun 2022 17:08:30 +0100 Subject: [PATCH 13/40] Increased max number of saves that can be displayed in the load game menu --- SOURCES/GAMEMENU.C | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SOURCES/GAMEMENU.C b/SOURCES/GAMEMENU.C index 26ec403..f2ba7c7 100644 --- a/SOURCES/GAMEMENU.C +++ b/SOURCES/GAMEMENU.C @@ -123,7 +123,7 @@ ULONG TimerSample ; // save players games -#define MAX_PLAYER 50 +#define MAX_PLAYER 200 UBYTE NumVersion = 0 ; From 4907c4b297558fe2c9c7b86992b90cf22c14c23e Mon Sep 17 00:00:00 2001 From: Rui Date: Thu, 23 Jun 2022 19:45:08 +0100 Subject: [PATCH 14/40] UI improvements on handling AUTO save: now showing AUTO save on top of the list on load menu, and hiding AUTO save on replace existing save and delete save menus. Changed AUTO save logic to be the same as it was before the changes in this branch (scene object states are only included in manual saves). --- SOURCES/GAMEMENU.C | 88 ++++++++++++++++++++++++++++++++------------ SOURCES/GAMEMENU.DEF | 4 +- 2 files changed, 66 insertions(+), 26 deletions(-) diff --git a/SOURCES/GAMEMENU.C b/SOURCES/GAMEMENU.C index f2ba7c7..bb150c4 100644 --- a/SOURCES/GAMEMENU.C +++ b/SOURCES/GAMEMENU.C @@ -124,6 +124,7 @@ ULONG TimerSample ; // save players games #define MAX_PLAYER 200 +#define AUTO_SAVE_NAME "AUTO" UBYTE NumVersion = 0 ; @@ -1194,7 +1195,7 @@ void CopyBlockPhysMCGA( LONG x0, LONG y0, LONG x1, LONG y1 ) *══════════════════════════════════════════════════════════════════════════*/ /*──────────────────────────────────────────────────────────────────────────*/ -WORD PlayerGameList( UBYTE **ptrlistname, UBYTE *listname ) +WORD PlayerGameList( UBYTE **ptrlistname, UBYTE *listname, WORD showAutoSave ) { struct find_t fileinfo ; ULONG rc ; @@ -1203,13 +1204,48 @@ WORD PlayerGameList( UBYTE **ptrlistname, UBYTE *listname ) WORD nb = 0 ; FILE* handle ; - strcpy( pathname, PATH_RESSOURCE"*.LBA" ) ; + if (showAutoSave) + { + strcpy(pathname, PATH_RESSOURCE); + strcat(pathname, AUTO_SAVE_NAME".LBA"); + + //Get Auto save file first + rc = _dos_findfirst(pathname, _A_NORMAL, &fileinfo); + if (!rc) + { + int i = 0; + int autoNameLen = strlen(AUTO_SAVE_NAME); + + *ptrlistname++ = listname; + for (i = 0; i < autoNameLen; i++) + { + *listname++ = AUTO_SAVE_NAME[i]; + } + + *listname++ = 0; + + nb++; + if (nb == MAX_PLAYER) return nb; + } + } + + strcpy(pathname, PATH_RESSOURCE"*.LBA"); + + //Get all the other save files rc = _dos_findfirst( pathname, _A_NORMAL, &fileinfo ) ; while( !rc ) { + //ignore auto save file + if (strcmp(fileinfo.name, AUTO_SAVE_NAME".LBA") == 0) + { + rc = _dos_findnext(&fileinfo); + continue; + } + strcpy( pathname, PATH_RESSOURCE ) ; strcat( pathname, fileinfo.name ) ; + handle = OpenRead( pathname ) ; if( handle ) { @@ -1283,10 +1319,10 @@ WORD FindPlayerFile() void SaveGame() { - SaveGameWithName("AUTO"); + SaveGameWithName(AUTO_SAVE_NAME, 1); } -void SaveGameWithName(char* fileName) +void SaveGameWithName(char* fileName, WORD isAutoSave) { FILE* handle ; WORD wword ; @@ -1362,15 +1398,19 @@ void SaveGameWithName(char* fileName) // others Write( handle, &NbFourLeafClover, 1 ) ; Write( handle, &Weapon, 2 ) ; - Write( handle, &NbLittleKeys, 1 ); - Write( handle, &ListObjet, sizeof(T_OBJET) * MAX_OBJETS ); - Write( handle, &ListExtra, sizeof(T_EXTRA) * MAX_EXTRAS ); - Write( handle, &NbZones, 2 ); - //Iterating for ListZone because it has a different data type - for (i = 0; i < NbZones; i++) + if (!isAutoSave) { - Write(handle, &ListZone[i], sizeof(T_ZONE)); + Write(handle, &NbLittleKeys, 1); + Write(handle, &ListObjet, sizeof(T_OBJET) * MAX_OBJETS); + Write(handle, &ListExtra, sizeof(T_EXTRA) * MAX_EXTRAS); + Write(handle, &NbZones, 2); + + //Iterating for ListZone because it has a different data type + for (i = 0; i < NbZones; i++) + { + Write(handle, &ListZone[i], sizeof(T_ZONE)); + } } Close( handle ) ; @@ -1820,7 +1860,7 @@ try_again: #define NB_GAME_CHOICE 6 -WORD ChoosePlayerName( WORD mess ) +WORD ChoosePlayerName( WORD mess, WORD showAutoSave ) { WORD flag = 1 ; UBYTE *listplayername ; @@ -1843,7 +1883,7 @@ WORD ChoosePlayerName( WORD mess ) TheEnd( NOT_ENOUGH_MEM, "Choose Player Name" ) ; } - nb = PlayerGameList( ptrlist, listplayername ) ; + nb = PlayerGameList( ptrlist, listplayername, showAutoSave ) ; if( !nb ) return FALSE ; @@ -2454,7 +2494,7 @@ void SavedGameManagement() break ; case 41: // copier - if( ChoosePlayerName( 41 ) ) + if( ChoosePlayerName( 41, 1 ) ) { UBYTE *ptr,*ptrs ; LONG size ; @@ -2492,7 +2532,7 @@ void SavedGameManagement() break ; case 45: // detruire - if( ChoosePlayerName( 45 ) ) + if( ChoosePlayerName( 45, 0 ) ) { CopyScreen( Screen, Log ) ; @@ -2664,13 +2704,13 @@ LONG MainGameMenu() if( !InputPlayerName( 42 ) ) break ; - do + /**do { strcpy( GamePathname, PATH_RESSOURCE"S" ) ; strcat( GamePathname, Itoa( Rnd(10000) ) ) ; strcat( GamePathname, ".LBA" ) ; } - while( FileSize( GamePathname ) != 0 ) ; + while( FileSize( GamePathname ) != 0 ) ;*/ MenuInitGame(1,0,1); while( Key OR Fire ) ; // provisoire @@ -2678,7 +2718,7 @@ LONG MainGameMenu() case 21: // load - if( !ChoosePlayerName( 21 ) ) break ; + if( !ChoosePlayerName( 21, 1 ) ) break ; MenuInitGame(-1,0,0); while( Key OR Fire ) ; // provisoire @@ -2722,7 +2762,7 @@ LONG QuitMenu() switch( select ) // num mess { case 21: // load - if (!ChoosePlayerName(21)) break; + if (!ChoosePlayerName(21, 1)) break; while (Key OR Fire); // provisoire @@ -2738,7 +2778,7 @@ LONG QuitMenu() retValue = 0; break; - case 950: + case 950: // new save if (InputPlayerName(950)) { SaveComportement = Comportement; @@ -2748,14 +2788,14 @@ LONG QuitMenu() SceneStartY = ListObjet[NUM_PERSO].PosObjY; SceneStartZ = ListObjet[NUM_PERSO].PosObjZ; - SaveGameWithName(PlayerName); + SaveGameWithName(PlayerName, 0); } retValue = 0; break; - case 951: - if (ChoosePlayerName(951)) + case 951: //replace save + if (ChoosePlayerName(951, 0)) { SaveComportement = Comportement; SaveBeta = ListObjet[NUM_PERSO].Beta; @@ -2764,7 +2804,7 @@ LONG QuitMenu() SceneStartY = ListObjet[NUM_PERSO].PosObjY; SceneStartZ = ListObjet[NUM_PERSO].PosObjZ; - SaveGameWithName(PlayerName); + SaveGameWithName(PlayerName, 0); } retValue = 0; diff --git a/SOURCES/GAMEMENU.DEF b/SOURCES/GAMEMENU.DEF index 0ef361a..a7837e5 100644 --- a/SOURCES/GAMEMENU.DEF +++ b/SOURCES/GAMEMENU.DEF @@ -16,7 +16,7 @@ extern void ExtInitMcga(void); extern void ExtInitSvga(void); extern void TestRestoreModeSVGA(long ); extern void CopyBlockPhysMCGA(long ,long ,long ,long ); -extern short PlayerGameList(unsigned char **,unsigned char *); +extern short PlayerGameList(unsigned char **,unsigned char *, short ); extern short FindPlayerFile(void); extern void SaveGame(void); extern void LoadGame(void); @@ -25,7 +25,7 @@ extern void DrawSingleString(short ,short ,unsigned char *); extern void DrawOneLetter(short ,short ,short ); extern void DrawAllLetters(void); extern short InputPlayerName(short ); -extern short ChoosePlayerName(short ); +extern short ChoosePlayerName(short, short ); extern void DrawOneChoice(short ,short ,short ,short ,short ); extern void InfoWallCollisionDamage(); extern void DrawGameMenu(unsigned short *,short ); From 4f2e7e932b0e70c8b7abf110a2924df4188f3bcd Mon Sep 17 00:00:00 2001 From: Rui Date: Sat, 25 Jun 2022 14:23:59 +0100 Subject: [PATCH 15/40] Added a fix for a situation where Twinsen's position would be reset and keyboard input disabled, inside Twinsen's house (possibly prevents other similar situations as well) --- SOURCES/GERELIFE.C | 27 +++++++++++++++++++++------ SOURCES/OBJECT.C | 32 ++++++++++++++++---------------- SOURCES/PERSO.C | 1 + 3 files changed, 38 insertions(+), 22 deletions(-) diff --git a/SOURCES/GERELIFE.C b/SOURCES/GERELIFE.C index acde632..8e7ac01 100644 --- a/SOURCES/GERELIFE.C +++ b/SOURCES/GERELIFE.C @@ -423,6 +423,7 @@ void DoLife( WORD numobj ) UBYTE macro ; T_OBJET *ptrobj ; + WORD auxMove; LONG obj ; LONG num ; UBYTE index ; @@ -432,12 +433,15 @@ void DoLife( WORD numobj ) UBYTE string[256] ; LONG dx, n ; + WORD isPersoFromLoad = HasLoadedSave && numobj == NUM_PERSO; + ptrobj = &ListObjet[numobj] ; PtrPrg = ptrobj->PtrLife + ptrobj->OffsetLife ; while( flag != -1 ) { + ptrmacro = PtrPrg ; switch( *PtrPrg++ ) { @@ -524,10 +528,17 @@ void DoLife( WORD numobj ) break ; case LM_SET_DIR: - ptrobj->Move = *PtrPrg++ ; - if( ptrobj->Move == MOVE_FOLLOW ) + auxMove = *PtrPrg++ ; + + if (!isPersoFromLoad) + ptrobj->Move = auxMove; + + if( auxMove == MOVE_FOLLOW ) { - ptrobj->Info3 = *PtrPrg++ ; + WORD auxInfo3 = *PtrPrg++; + + if (!isPersoFromLoad) + ptrobj->Info3 = auxInfo3 ; } break ; @@ -1007,9 +1018,13 @@ void DoLife( WORD numobj ) Y0 = ListBrickTrack[Value].Y ; Z0 = ListBrickTrack[Value].Z ; - ptrobj->PosObjX = X0 ; - ptrobj->PosObjY = Y0 ; - ptrobj->PosObjZ = Z0 ; + + if (!isPersoFromLoad) + { + ptrobj->PosObjX = X0; + ptrobj->PosObjY = Y0; + ptrobj->PosObjZ = Z0; + } break ; case LM_PLAY_FLA: diff --git a/SOURCES/OBJECT.C b/SOURCES/OBJECT.C index e752905..5d17f20 100644 --- a/SOURCES/OBJECT.C +++ b/SOURCES/OBJECT.C @@ -283,21 +283,23 @@ void RestartPerso() ptrobj = &ListObjet[NUM_PERSO] ; - ptrobj->Move = MOVE_MANUAL ; + ptrobj->Move = MOVE_MANUAL; + ptrobj->WorkFlags = 0; + ptrobj->Flags = OBJ_FALLABLE + + CHECK_ZONE + + CHECK_OBJ_COL + + CHECK_BRICK_COL + + CHECK_CODE_JEU; - ptrobj->WorkFlags = 0 ; - ptrobj->Flags = OBJ_FALLABLE - + CHECK_ZONE - + CHECK_OBJ_COL - + CHECK_BRICK_COL - + CHECK_CODE_JEU ; - - ptrobj->Armure = 1 ; + if (!HasLoadedSave) + { + ptrobj->Armure = 1; - ptrobj->OffsetTrack = -1 ; - ptrobj->LabelTrack = -1 ; - ptrobj->OffsetLife = 0 ; - ptrobj->ZoneSce = -1 ; + ptrobj->OffsetTrack = -1; + ptrobj->LabelTrack = -1; + ptrobj->OffsetLife = 0; + ptrobj->ZoneSce = -1; + } ptrobj->Beta = SaveBeta ; @@ -479,9 +481,7 @@ void ChangeCube() SaveBeta = ListObjet[NUM_PERSO].Beta ; SaveGame() ; } - - HasLoadedSave = 0; - + RestartPerso() ; StartInitAllObjs(); diff --git a/SOURCES/PERSO.C b/SOURCES/PERSO.C index 99b52d3..ba63135 100644 --- a/SOURCES/PERSO.C +++ b/SOURCES/PERSO.C @@ -970,6 +970,7 @@ startloop: if (NbObjets > 0) { + HasLoadedSave = 0; HasLoadedInventoryOnSave = 0; HasLoadedListObjetTracksOnSave = 0; } From 27acf59a055dc76bd9064bb8a8be3f7c0167fb06 Mon Sep 17 00:00:00 2001 From: Rui Date: Sun, 26 Jun 2022 12:16:03 +0100 Subject: [PATCH 16/40] Applied a fix to keep the scene state as it is when loosing a clover leaf (do not respawn dead NPCs, do not close opened doors, etc). If death occurs in water, reset Twinsen position to start of scene (to avoid situations where he respawns in the water) --- SOURCES/PERSO.C | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/SOURCES/PERSO.C b/SOURCES/PERSO.C index ba63135..ca33a50 100644 --- a/SOURCES/PERSO.C +++ b/SOURCES/PERSO.C @@ -908,17 +908,30 @@ startloop: { if( NbFourLeafClover > 0 ) { - FlagWater = FALSE ; - // restart NbFourLeafClover-- ; - ListObjet[NUM_PERSO].PosObjX = SceneStartX ; - ListObjet[NUM_PERSO].PosObjY = SceneStartY ; - ListObjet[NUM_PERSO].PosObjZ = SceneStartZ ; + //For now, if death occurs in water, set position to cube start. Ideally it should work like in LBA2 but might require some code refactoring + //Do not reset scene any longer + if (FlagWater) + { + //If respawning Twinsen in cube start position generates softlocks, uncomment these to respawn all objects to scene start + //NewCube = NumCube; + //FlagChgCube = 3; + + SceneStartX = CubeStartX; + SceneStartY = CubeStartY; + SceneStartZ = CubeStartZ; + } + + FlagWater = FALSE; + + ListObjet[NUM_PERSO].PosObjX = SceneStartX; + ListObjet[NUM_PERSO].PosObjY = SceneStartY; + ListObjet[NUM_PERSO].PosObjZ = SceneStartZ; + + ListObjet[NUM_PERSO].Move = MOVE_MANUAL; - NewCube = NumCube ; - FlagChgCube = 3 ; ListObjet[NUM_PERSO].LifePoint = 50 ; MagicPoint = MagicLevel * 20 ; From c74f653352fe4a69c3ccd1c08322b3509a3650e4 Mon Sep 17 00:00:00 2001 From: Rui Date: Tue, 28 Jun 2022 11:23:05 +0100 Subject: [PATCH 17/40] Fix for empty or wrong text dialogs after doing a save (resetting dialog file with InitDial after doing a save) --- .gitignore | 1 + SOURCES/GAMEMENU.C | 13 ++++++++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 3d4efd0..463d963 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ *.OBJ *.ERR SOURCES/LBA0.EXE +BIN/ \ No newline at end of file diff --git a/SOURCES/GAMEMENU.C b/SOURCES/GAMEMENU.C index bb150c4..0775d22 100644 --- a/SOURCES/GAMEMENU.C +++ b/SOURCES/GAMEMENU.C @@ -2762,7 +2762,12 @@ LONG QuitMenu() switch( select ) // num mess { case 21: // load - if (!ChoosePlayerName(21, 1)) break; + if (!ChoosePlayerName(21, 1)) + { + //if no load file is selected, reset dialog file to current island + InitDial(START_FILE_ISLAND + Island); + break; + } while (Key OR Fire); // provisoire @@ -2791,6 +2796,9 @@ LONG QuitMenu() SaveGameWithName(PlayerName, 0); } + //reset dialog file to current island + InitDial(START_FILE_ISLAND + Island); + retValue = 0; break; @@ -2807,6 +2815,9 @@ LONG QuitMenu() SaveGameWithName(PlayerName, 0); } + //reset dialog file to current island + InitDial(START_FILE_ISLAND + Island); + retValue = 0; break; } From 6a02ef11c6c15505f7e74e70401c4bc78cffded4 Mon Sep 17 00:00:00 2001 From: Rui Date: Tue, 28 Jun 2022 14:25:37 +0100 Subject: [PATCH 18/40] Fix for cases that allowed saving in the middle of an animation (now if Twinsen is in animation, the Escape Quit Menu will hide the save options) --- SOURCES/GAMEMENU.C | 13 +++++++++++-- SOURCES/GAMEMENU.DEF | 2 +- SOURCES/PERSO.C | 3 ++- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/SOURCES/GAMEMENU.C b/SOURCES/GAMEMENU.C index 0775d22..da6d662 100644 --- a/SOURCES/GAMEMENU.C +++ b/SOURCES/GAMEMENU.C @@ -28,6 +28,15 @@ UWORD GameMainMenu[] = { 0, 22 // ret dos } ; +UWORD GameQuitMenuWithoutSave[] = { + 0, // selected + 2, // nb entries + 240, // y center + 0, // .dia num + 0, 28, // continuer jeu + 0, 27 // abandonner partie +}; + UWORD GameQuitMenu[] = { 0, // selected 5, // nb entries @@ -2739,7 +2748,7 @@ LONG MainGameMenu() /*══════════════════════════════════════════════════════════════════════════*/ /*──────────────────────────────────────────────────────────────────────────*/ -LONG QuitMenu() +LONG QuitMenu(WORD showSaveOptions) { LONG retValue = -999; WORD select ; @@ -2755,7 +2764,7 @@ LONG QuitMenu() InitDial( 0 ) ;// SYS FlagSpeak = memoflagspeak ; - select = DoGameMenu( GameQuitMenu ) ; + select = DoGameMenu( showSaveOptions ? GameQuitMenu : GameQuitMenuWithoutSave) ; InitDial( START_FILE_ISLAND+Island ) ;// SYS diff --git a/SOURCES/GAMEMENU.DEF b/SOURCES/GAMEMENU.DEF index a7837e5..742dd49 100644 --- a/SOURCES/GAMEMENU.DEF +++ b/SOURCES/GAMEMENU.DEF @@ -36,7 +36,7 @@ extern void VolumeOptions(void); extern void SavedGameManagement(void); extern void AdvancedOptions(void); extern long MainGameMenu(void); -extern long QuitMenu(void); +extern long QuitMenu(short ); extern void GameAskChoice(short ); extern void GameOver(void); extern void Credits(void); diff --git a/SOURCES/PERSO.C b/SOURCES/PERSO.C index ca33a50..c283431 100644 --- a/SOURCES/PERSO.C +++ b/SOURCES/PERSO.C @@ -412,7 +412,8 @@ startloop: TestRestoreModeSVGA( TRUE ) ; SaveTimer() ; - retQuitMenu = QuitMenu(); + //If Twinsen is in MOVE_MANUAL mode, show save options in QuitMenu. If Twinsen is in another move mode (a tracking in the middle of a cutscene, or another automatic mode), hide save options + retQuitMenu = QuitMenu( ListObjet[NUM_PERSO].Move == MOVE_MANUAL ); if( retQuitMenu == 2) { RestoreTimer() ; From 3015f472518d95f09dc4bfba23045dff2b665028 Mon Sep 17 00:00:00 2001 From: Rui Date: Tue, 28 Jun 2022 15:43:02 +0100 Subject: [PATCH 19/40] Fix for black screen when saving near NPCs or objects with automatic messages based on distance --- SOURCES/GERELIFE.C | 118 ++++++++++++++++++++++++++++----------------- 1 file changed, 74 insertions(+), 44 deletions(-) diff --git a/SOURCES/GERELIFE.C b/SOURCES/GERELIFE.C index 8e7ac01..14e91ee 100644 --- a/SOURCES/GERELIFE.C +++ b/SOURCES/GERELIFE.C @@ -709,35 +709,50 @@ void DoLife( WORD numobj ) break ; case LM_MESSAGE_OBJ: - SaveTimer() ; - TestRestoreModeSVGA( TRUE ) ; - num = *PtrPrg++ ; - if( Bulle ) DrawBulle( num ) ; - TestCoulDial( ListObjet[num].CoulObj ) ; + if (!HasLoadedSave) + { + SaveTimer(); + TestRestoreModeSVGA(TRUE); + num = *PtrPrg++; + if (Bulle) DrawBulle(num); + TestCoulDial(ListObjet[num].CoulObj); #ifdef CDROM - NumObjSpeak = num ; + NumObjSpeak = num; #endif - Dial( *(WORD*)PtrPrg ) ; - PtrPrg += 2 ; - RestoreTimer() ; + Dial(*(WORD*)PtrPrg); + PtrPrg += 2; + RestoreTimer(); - AffScene(TRUE) ; - WaitReleaseSpace() ; + AffScene(TRUE); + WaitReleaseSpace(); + } + else + { + num = *PtrPrg++; + PtrPrg += 2; + } break ; case LM_MESSAGE: - SaveTimer() ; - TestRestoreModeSVGA( TRUE ) ; - if( Bulle ) DrawBulle( numobj ) ; - TestCoulDial( ptrobj->CoulObj ) ; + if (!HasLoadedSave) + { + SaveTimer(); + TestRestoreModeSVGA(TRUE); + if (Bulle) DrawBulle(numobj); + TestCoulDial(ptrobj->CoulObj); #ifdef CDROM - NumObjSpeak = numobj ; + NumObjSpeak = numobj; #endif - Dial( *(WORD*)PtrPrg ) ; - PtrPrg += 2 ; - RestoreTimer() ; - AffScene(TRUE) ; - WaitReleaseSpace() ; + Dial(*(WORD*)PtrPrg); + PtrPrg += 2; + RestoreTimer(); + AffScene(TRUE); + WaitReleaseSpace(); + } + else + { + PtrPrg += 2; + } break ; case LM_SAY_MESSAGE_OBJ: @@ -1047,34 +1062,49 @@ void DoLife( WORD numobj ) case LM_ASK_CHOICE: #ifndef DEMO - SaveTimer() ; - TestRestoreModeSVGA( TRUE ) ; - if( Bulle ) DrawBulle( numobj ) ; - TestCoulDial( ptrobj->CoulObj ) ; - GameAskChoice( *(WORD*)PtrPrg ) ; - GameNbChoices = 0 ; - PtrPrg += 2 ; -// FlagFade = TRUE ; - RestoreTimer() ; - AffScene(TRUE) ; - WaitReleaseSpace() ; + if (!HasLoadedSave) + { + SaveTimer(); + TestRestoreModeSVGA(TRUE); + if (Bulle) DrawBulle(numobj); + TestCoulDial(ptrobj->CoulObj); + GameAskChoice(*(WORD*)PtrPrg); + GameNbChoices = 0; + PtrPrg += 2; + // FlagFade = TRUE ; + RestoreTimer(); + AffScene(TRUE); + WaitReleaseSpace(); + } + else { + GameNbChoices = 0; + PtrPrg += 2; + } #endif break ; case LM_ASK_CHOICE_OBJ: #ifndef DEMO - SaveTimer() ; - num = *PtrPrg++ ; - TestRestoreModeSVGA( TRUE ) ; - if( Bulle ) DrawBulle( num ) ; - TestCoulDial( ListObjet[num].CoulObj ) ; - GameAskChoice( *(WORD*)PtrPrg ) ; - GameNbChoices = 0 ; - PtrPrg += 2 ; -// FlagFade = TRUE ; - RestoreTimer() ; - AffScene(TRUE) ; - WaitReleaseSpace() ; + if (!HasLoadedSave) + { + SaveTimer(); + num = *PtrPrg++; + TestRestoreModeSVGA(TRUE); + if (Bulle) DrawBulle(num); + TestCoulDial(ListObjet[num].CoulObj); + GameAskChoice(*(WORD*)PtrPrg); + GameNbChoices = 0; + PtrPrg += 2; + // FlagFade = TRUE ; + RestoreTimer(); + AffScene(TRUE); + WaitReleaseSpace(); + } + else { + num = *PtrPrg++; + GameNbChoices = 0; + PtrPrg += 2; + } #endif break ; From 2edc30db0d82d4ecea1a9a4a5c612be1ff9cd97b Mon Sep 17 00:00:00 2001 From: Rui Date: Tue, 28 Jun 2022 16:03:24 +0100 Subject: [PATCH 20/40] Improved retro compatibility with previous version save files and AUTO save files. This fixes the scenario where Twinsen immediately drowns when loading AUTO save in Rebellion Island. --- SOURCES/GAMEMENU.C | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/SOURCES/GAMEMENU.C b/SOURCES/GAMEMENU.C index da6d662..c5b1875 100644 --- a/SOURCES/GAMEMENU.C +++ b/SOURCES/GAMEMENU.C @@ -1433,8 +1433,7 @@ void LoadGame() WORD wword ; UBYTE wbyte ; UBYTE *ptr ; - int successInventory, successKeys, successListObjets, successNbZones, successListExtras; - int successListZones = 1; + int successInventory = 0, successKeys = 0, successListObjets = 0, successNbZones = 0, successListZones = 0, successListExtras = 0; int i; handle = OpenRead( GamePathname ) ; @@ -1497,18 +1496,26 @@ void LoadGame() successListExtras = Read(handle, &ListExtra, sizeof(T_EXTRA) * MAX_EXTRAS); successNbZones = Read(handle, &NbZones, 2); - ListZone = malloc(sizeof(T_ZONE) * NbZones); - - //Iterating for ListZone because it has a different data type - for (i = 0; i < NbZones; i++) + if (successNbZones && NbZones > 0) { - successListZones &= Read(handle, &ListZone[i], sizeof(T_ZONE)); + ListZone = malloc(sizeof(T_ZONE) * NbZones); + + successListZones = 1; + + //Iterating for ListZone because it has a different data type + for (i = 0; i < NbZones; i++) + { + successListZones &= Read(handle, &ListZone[i], sizeof(T_ZONE)); + } } Close( handle ) ; //These flags are here to help the code identify if objects in a scene are coming from a save or from the HQR file. They also help with keeping retro compatibility with previous version save files - HasLoadedSave = 1; + HasLoadedSave = successListObjets || successListExtras || successNbZones || successListZones || successKeys; /*If any of these are present in the save file, + it means we are loading a new version of the save files. If not, it means we are loading a previous version AUTO save file, + therefore the code should run the same logic for previous versions. + Inventory is not checked because it was already in original save files.*/ HasLoadedInventoryOnSave = successInventory; HasLoadedListObjetsOnSave = successListObjets; HasLoadedListObjetTracksOnSave = successListObjets; From 31c2bcbdb25019e4beae56d9c48b3a31306edc4c Mon Sep 17 00:00:00 2001 From: Rui Date: Tue, 28 Jun 2022 17:20:03 +0100 Subject: [PATCH 21/40] Fix saving close to boat/dinofly/etc causing Twinsen to be inside it on reload --- SOURCES/OBJECT.C | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/SOURCES/OBJECT.C b/SOURCES/OBJECT.C index 5d17f20..4a39304 100644 --- a/SOURCES/OBJECT.C +++ b/SOURCES/OBJECT.C @@ -3339,7 +3339,9 @@ void CheckZoneSce( T_OBJET *ptrobj, WORD numobj ) break ; case 2: // zone scenarique - ptrobj->ZoneSce = ptrz->Num ; + // Prevent entering boat, dinofly, vehicle, immediately on load save file + if(!(HasLoadedSave && numobj == NUM_PERSO)) + ptrobj->ZoneSce = ptrz->Num ; break ; case 3: // zone grm From 3e928343605837b54042441e7435cbcdce254c36 Mon Sep 17 00:00:00 2001 From: Rui Date: Wed, 29 Jun 2022 17:06:53 +0100 Subject: [PATCH 22/40] Fix for doors, saved in open state, not closing (for those that are expected to close again in animation, naturally doors opened with keys will remain open) --- SOURCES/DISKFUNC.C | 1 - SOURCES/OBJECT.C | 3 ++- SOURCES/PERSO.C | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/SOURCES/DISKFUNC.C b/SOURCES/DISKFUNC.C index cb9a216..f07ac11 100644 --- a/SOURCES/DISKFUNC.C +++ b/SOURCES/DISKFUNC.C @@ -230,7 +230,6 @@ WORD LoadScene( WORD numscene ) ListBrickTrack = (T_TRACK*)PtrSce ; HasLoadedListZoneOnSave = 0; - HasLoadedListObjetsOnSave = 0; return TRUE ; } diff --git a/SOURCES/OBJECT.C b/SOURCES/OBJECT.C index 4a39304..c948b08 100644 --- a/SOURCES/OBJECT.C +++ b/SOURCES/OBJECT.C @@ -120,7 +120,8 @@ void StartInitObj( WORD numobj ) InitRealAngle( 0,0,0, &ptrobj->RealAngle ) ; - if( ptrobj->Flags & SPRITE_CLIP ) + //Do not set AnimStepX, Y, Z if the values are coming from a save. Use what's already in the save state instead. These variables are used as a reference to where an object should be animated to (e.g. like a closed door, and if the door is saved in an open state, the reference would be set to the open position, but it should be in the closed position) + if( ptrobj->Flags & SPRITE_CLIP && !HasLoadedListObjetsOnSave ) { ptrobj->AnimStepX = ptrobj->PosObjX ; ptrobj->AnimStepY = ptrobj->PosObjY ; diff --git a/SOURCES/PERSO.C b/SOURCES/PERSO.C index c283431..f013ccb 100644 --- a/SOURCES/PERSO.C +++ b/SOURCES/PERSO.C @@ -986,6 +986,7 @@ startloop: { HasLoadedSave = 0; HasLoadedInventoryOnSave = 0; + HasLoadedListObjetsOnSave = 0; HasLoadedListObjetTracksOnSave = 0; } /* From c19f2be50165d2a4532ba93d7b9b13fc11951f7d Mon Sep 17 00:00:00 2001 From: Rui Date: Thu, 30 Jun 2022 11:37:28 +0100 Subject: [PATCH 23/40] Now persisting ListFlagCube on save files. Fixes teleportation center softlock and possibly other scenarios. --- SOURCES/C_EXTERN.H | 1 + SOURCES/GAMEMENU.C | 25 +++++++++++++++++++------ SOURCES/GLOBAL.C | 1 + SOURCES/OBJECT.C | 7 +++++-- SOURCES/PERSO.C | 1 + 5 files changed, 27 insertions(+), 8 deletions(-) diff --git a/SOURCES/C_EXTERN.H b/SOURCES/C_EXTERN.H index 0fd5121..a51d41a 100644 --- a/SOURCES/C_EXTERN.H +++ b/SOURCES/C_EXTERN.H @@ -249,6 +249,7 @@ extern WORD HasLoadedListExtraOnSave; extern WORD HasLoadedListZoneOnSave; extern WORD HasLoadedKeysOnSave ; extern WORD HasLoadedInventoryOnSave; +extern WORD HasLoadedListFlagCubeOnSave; extern WORD NbFourLeafClover ; extern WORD NbCloverBox ; diff --git a/SOURCES/GAMEMENU.C b/SOURCES/GAMEMENU.C index c5b1875..724aacb 100644 --- a/SOURCES/GAMEMENU.C +++ b/SOURCES/GAMEMENU.C @@ -1415,11 +1415,16 @@ void SaveGameWithName(char* fileName, WORD isAutoSave) Write(handle, &ListExtra, sizeof(T_EXTRA) * MAX_EXTRAS); Write(handle, &NbZones, 2); - //Iterating for ListZone because it has a different data type + // Iterating for ListZone because it has a different data type for (i = 0; i < NbZones; i++) { Write(handle, &ListZone[i], sizeof(T_ZONE)); } + + // list flag cube + wbyte = MAX_FLAGS_CUBE; + Write(handle, &wbyte, 1); // nb octets + Write(handle, &ListFlagCube, MAX_FLAGS_CUBE); } Close( handle ) ; @@ -1433,7 +1438,7 @@ void LoadGame() WORD wword ; UBYTE wbyte ; UBYTE *ptr ; - int successInventory = 0, successKeys = 0, successListObjets = 0, successNbZones = 0, successListZones = 0, successListExtras = 0; + int successInventory = 0, successKeys = 0, successListObjets = 0, successNbZones = 0, successListZones = 0, successListExtras = 0, successNbListFlagCube = 0, successListFlagCube = 0; int i; handle = OpenRead( GamePathname ) ; @@ -1509,19 +1514,27 @@ void LoadGame() } } + // List flag cube + successNbListFlagCube = Read(handle, &wbyte, 1); // nb octets + if (successNbListFlagCube && wbyte > 0) + successListFlagCube = Read(handle, &ListFlagCube, wbyte); + Close( handle ) ; //These flags are here to help the code identify if objects in a scene are coming from a save or from the HQR file. They also help with keeping retro compatibility with previous version save files - HasLoadedSave = successListObjets || successListExtras || successNbZones || successListZones || successKeys; /*If any of these are present in the save file, - it means we are loading a new version of the save files. If not, it means we are loading a previous version AUTO save file, - therefore the code should run the same logic for previous versions. - Inventory is not checked because it was already in original save files.*/ + HasLoadedSave = successListObjets || successListExtras || + successNbZones || successListZones || + successKeys || successNbListFlagCube || successListFlagCube; /*If any of these are present in the save file, + it means we are loading a new version of the save files. If not, it means we are loading a previous version AUTO save file, + therefore the code should run the same logic for previous versions. + Inventory is not checked because it was already in original save files.*/ HasLoadedInventoryOnSave = successInventory; HasLoadedListObjetsOnSave = successListObjets; HasLoadedListObjetTracksOnSave = successListObjets; HasLoadedListExtraOnSave = successListExtras; HasLoadedListZoneOnSave = successNbZones && NbZones > 0 && successListZones; HasLoadedKeysOnSave = successKeys && NbLittleKeys > 0; + HasLoadedListFlagCubeOnSave = successNbListFlagCube && successListFlagCube; NumCube = -1 ; FlagChgCube = 3 ; diff --git a/SOURCES/GLOBAL.C b/SOURCES/GLOBAL.C index e6dc17b..c738f41 100644 --- a/SOURCES/GLOBAL.C +++ b/SOURCES/GLOBAL.C @@ -178,6 +178,7 @@ WORD HasLoadedListExtraOnSave = 0; WORD HasLoadedListZoneOnSave = 0; WORD HasLoadedKeysOnSave = 0; WORD HasLoadedInventoryOnSave = 0; +WORD HasLoadedListFlagCubeOnSave = 0; WORD Island = 0 ; WORD Fuel = 0 ; diff --git a/SOURCES/OBJECT.C b/SOURCES/OBJECT.C index c948b08..287b9c2 100644 --- a/SOURCES/OBJECT.C +++ b/SOURCES/OBJECT.C @@ -321,9 +321,12 @@ void ClearFlagsCube() { WORD n ; - for( n=0; n Date: Thu, 30 Jun 2022 14:07:19 +0100 Subject: [PATCH 24/40] Fix reload red pal state on teleportation center when alarm is activated but all devices weren't destroyed yet --- SOURCES/OBJECT.C | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/SOURCES/OBJECT.C b/SOURCES/OBJECT.C index 287b9c2..f9acbd3 100644 --- a/SOURCES/OBJECT.C +++ b/SOURCES/OBJECT.C @@ -363,6 +363,44 @@ void ClearScene() ClearDial() ; } +void SetFadePalOnLoad() +{ + if (HasLoadedSave && HasLoadedListFlagCubeOnSave) + { + //Set red alarm pal on teleportation center when active (num cube is 99) + if (NumCube == 99) + { + int i; + int maxFlags = 7; // devices destroyed are stored in indexes from 0 to 6 + WORD isInAlarmState = 0; + + if (maxFlags <= MAX_FLAGS_CUBE) + { + int nbDevicesDestroyed = 0; + + for (i = 0; i < maxFlags; i++) + { + WORD deviceDestroyed = ListFlagCube[i] > 0; + + if (deviceDestroyed) + nbDevicesDestroyed++; + + isInAlarmState |= deviceDestroyed; + } + + if (isInAlarmState && nbDevicesDestroyed < maxFlags) + { + SaveTimer(); + Load_HQR(PATH_RESSOURCE"ress.hqr", PalettePcx, RESS_PAL_ALARM); + FadePalToPal(PtrPal, PalettePcx); + FlagPalettePcx = TRUE; + RestoreTimer(); + } + } + } + } +} + /*══════════════════════════════════════════════════════════════════════════*/ // need: NewCube @@ -518,6 +556,8 @@ void ChangeCube() { PlayMusic( CubeJingle ) ; } + + SetFadePalOnLoad(); } /*══════════════════════════════════════════════════════════════════════════* From 8640904d60c8af8c4d2459bc51af591135189cba Mon Sep 17 00:00:00 2001 From: Rui Date: Thu, 30 Jun 2022 16:33:41 +0100 Subject: [PATCH 25/40] Fix reload dark pal on museum when alarm is active --- SOURCES/OBJECT.C | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/SOURCES/OBJECT.C b/SOURCES/OBJECT.C index f9acbd3..cacf3cb 100644 --- a/SOURCES/OBJECT.C +++ b/SOURCES/OBJECT.C @@ -365,10 +365,27 @@ void ClearScene() void SetFadePalOnLoad() { - if (HasLoadedSave && HasLoadedListFlagCubeOnSave) + if (HasLoadedSave) { + //HasLoadedInventoryOnSave used for ListFlagGame + //Set dark pal on museum when alarm is active (num cube is 43) + if (HasLoadedInventoryOnSave && NumCube == 43) + { + int indexMuseumAlarm = 41; // index 41 is changed when activating the museum alarm + + //If the flag is set in ListFlagGame, apply the dark pal + if (indexMuseumAlarm < MAX_FLAGS_GAME && ListFlagGame[indexMuseumAlarm]) + { + SaveTimer(); + Load_HQR(PATH_RESSOURCE"ress.hqr", PalettePcx, RESS_PAL_MUSEE); + Palette(PalettePcx); + FlagPalettePcx = TRUE; + RestoreTimer(); + } + } + //Set red alarm pal on teleportation center when active (num cube is 99) - if (NumCube == 99) + if (HasLoadedListFlagCubeOnSave && NumCube == 99) { int i; int maxFlags = 7; // devices destroyed are stored in indexes from 0 to 6 From 06647a035b4f8caa7ddc8c816b9aaa1784947cea Mon Sep 17 00:00:00 2001 From: Rui Date: Thu, 30 Jun 2022 18:34:26 +0100 Subject: [PATCH 26/40] Some UI improvements. Changed text for existing save file from "this player exists" to "this save exists". Removed existing save check on New Game input. --- SOURCES/Assets/Text/de_ctxt.csv | 1 + SOURCES/Assets/Text/en_ctxt.csv | 1 + SOURCES/Assets/Text/fr_ctxt.csv | 1 + SOURCES/Assets/Text/it_ctxt.csv | 1 + SOURCES/Assets/Text/sp_ctxt.csv | 1 + SOURCES/GAMEMENU.C | 14 ++++++++------ SOURCES/GAMEMENU.DEF | 2 +- 7 files changed, 14 insertions(+), 7 deletions(-) diff --git a/SOURCES/Assets/Text/de_ctxt.csv b/SOURCES/Assets/Text/de_ctxt.csv index 1bf71b1..06c13dc 100644 --- a/SOURCES/Assets/Text/de_ctxt.csv +++ b/SOURCES/Assets/Text/de_ctxt.csv @@ -2,3 +2,4 @@ 34,Kollisionsschaden inaktiv 950,Create new save 951,Replace existing save +952,This save already exists! Try again. diff --git a/SOURCES/Assets/Text/en_ctxt.csv b/SOURCES/Assets/Text/en_ctxt.csv index d18fc2d..985de7d 100644 --- a/SOURCES/Assets/Text/en_ctxt.csv +++ b/SOURCES/Assets/Text/en_ctxt.csv @@ -2,3 +2,4 @@ 34,Collision Damage Off 950,Create new save 951,Replace existing save +952,This save already exists! Try again. diff --git a/SOURCES/Assets/Text/fr_ctxt.csv b/SOURCES/Assets/Text/fr_ctxt.csv index aaf68b8..93f2644 100644 --- a/SOURCES/Assets/Text/fr_ctxt.csv +++ b/SOURCES/Assets/Text/fr_ctxt.csv @@ -2,3 +2,4 @@ 34,D‚gƒts de collision d‚sactiv‚s 950,Create new save 951,Replace existing save +952,This save already exists! Try again. diff --git a/SOURCES/Assets/Text/it_ctxt.csv b/SOURCES/Assets/Text/it_ctxt.csv index 8ad14da..f0e7a09 100644 --- a/SOURCES/Assets/Text/it_ctxt.csv +++ b/SOURCES/Assets/Text/it_ctxt.csv @@ -2,3 +2,4 @@ 34,Danno da collisione disattivato 950,Create new save 951,Replace existing save +952,This save already exists! Try again. diff --git a/SOURCES/Assets/Text/sp_ctxt.csv b/SOURCES/Assets/Text/sp_ctxt.csv index 8803e3d..3868304 100644 --- a/SOURCES/Assets/Text/sp_ctxt.csv +++ b/SOURCES/Assets/Text/sp_ctxt.csv @@ -2,3 +2,4 @@ 34,Da€os por colisi’n desactivados 950,Create new save 951,Replace existing save +952,This save already exists! Try again. diff --git a/SOURCES/GAMEMENU.C b/SOURCES/GAMEMENU.C index 724aacb..d683ca1 100644 --- a/SOURCES/GAMEMENU.C +++ b/SOURCES/GAMEMENU.C @@ -1714,7 +1714,7 @@ void DrawAllLetters() /*──────────────────────────────────────────────────────────────────────────*/ /*──────────────────────────────────────────────────────────────────────────*/ -WORD InputPlayerName( WORD nummess ) +WORD InputPlayerName( WORD nummess, WORD isSaveGame ) { WORD flag = 1 ; UBYTE string[256] ; @@ -1864,9 +1864,11 @@ try_again: if( car == A_RETURN ) { - if( FindPlayerFile() == TRUE ) + //Ignore this check for new game, since what's input there does not influence the save name file anymore + if( isSaveGame && FindPlayerFile() == TRUE ) { - nummess = 43 ; + //nummess = 43 ; + nummess = 952; // use id from community text goto try_again ; } else retval = TRUE ; @@ -2536,7 +2538,7 @@ void SavedGameManagement() num = *ptr++ ; // num version n = strlen( ptr ) + 1 ; // size player name - if( InputPlayerName( 44 ) ) + if( InputPlayerName( 44, 1 ) ) { do { @@ -2731,7 +2733,7 @@ LONG MainGameMenu() case 20: // newgame - if( !InputPlayerName( 42 ) ) break ; + if( !InputPlayerName( 42, 0 ) ) break ; /**do { @@ -2813,7 +2815,7 @@ LONG QuitMenu(WORD showSaveOptions) break; case 950: // new save - if (InputPlayerName(950)) + if (InputPlayerName(950, 1)) { SaveComportement = Comportement; SaveBeta = ListObjet[NUM_PERSO].Beta; diff --git a/SOURCES/GAMEMENU.DEF b/SOURCES/GAMEMENU.DEF index 742dd49..690b3f3 100644 --- a/SOURCES/GAMEMENU.DEF +++ b/SOURCES/GAMEMENU.DEF @@ -24,7 +24,7 @@ extern void DrawOneString(short ,short ,unsigned char *,short ); extern void DrawSingleString(short ,short ,unsigned char *); extern void DrawOneLetter(short ,short ,short ); extern void DrawAllLetters(void); -extern short InputPlayerName(short ); +extern short InputPlayerName(short, short ); extern short ChoosePlayerName(short, short ); extern void DrawOneChoice(short ,short ,short ,short ,short ); extern void InfoWallCollisionDamage(); From 2b120e33348b35dbe98890656d4e622bbf1c5c05 Mon Sep 17 00:00:00 2001 From: Rui Date: Thu, 30 Jun 2022 19:58:49 +0100 Subject: [PATCH 27/40] Some UI modifications to texts and saving game (now creating and replacing are under one option). --- SOURCES/Assets/Text/de_ctxt.csv | 5 +- SOURCES/Assets/Text/en_ctxt.csv | 5 +- SOURCES/Assets/Text/fr_ctxt.csv | 5 +- SOURCES/Assets/Text/it_ctxt.csv | 5 +- SOURCES/Assets/Text/sp_ctxt.csv | 5 +- SOURCES/GAMEMENU.C | 98 +++++++++++++++++++-------------- SOURCES/GAMEMENU.DEF | 4 +- 7 files changed, 75 insertions(+), 52 deletions(-) diff --git a/SOURCES/Assets/Text/de_ctxt.csv b/SOURCES/Assets/Text/de_ctxt.csv index 06c13dc..258cabf 100644 --- a/SOURCES/Assets/Text/de_ctxt.csv +++ b/SOURCES/Assets/Text/de_ctxt.csv @@ -1,5 +1,6 @@ 234,Kollisionsschaden aktiv 34,Kollisionsschaden inaktiv -950,Create new save -951,Replace existing save +950,Load game +951,Save game 952,This save already exists! Try again. +953,New game diff --git a/SOURCES/Assets/Text/en_ctxt.csv b/SOURCES/Assets/Text/en_ctxt.csv index 985de7d..143252a 100644 --- a/SOURCES/Assets/Text/en_ctxt.csv +++ b/SOURCES/Assets/Text/en_ctxt.csv @@ -1,5 +1,6 @@ 234,Collision Damage On 34,Collision Damage Off -950,Create new save -951,Replace existing save +950,Load game +951,Save game 952,This save already exists! Try again. +953,New game diff --git a/SOURCES/Assets/Text/fr_ctxt.csv b/SOURCES/Assets/Text/fr_ctxt.csv index 93f2644..f3cba76 100644 --- a/SOURCES/Assets/Text/fr_ctxt.csv +++ b/SOURCES/Assets/Text/fr_ctxt.csv @@ -1,5 +1,6 @@ 234,D‚gƒts de collision activ‚s 34,D‚gƒts de collision d‚sactiv‚s -950,Create new save -951,Replace existing save +950,Load game +951,Save game 952,This save already exists! Try again. +953,New game diff --git a/SOURCES/Assets/Text/it_ctxt.csv b/SOURCES/Assets/Text/it_ctxt.csv index f0e7a09..442ae87 100644 --- a/SOURCES/Assets/Text/it_ctxt.csv +++ b/SOURCES/Assets/Text/it_ctxt.csv @@ -1,5 +1,6 @@ 234,Danno da collisione attivato 34,Danno da collisione disattivato -950,Create new save -951,Replace existing save +950,Load game +951,Save game 952,This save already exists! Try again. +953,New game diff --git a/SOURCES/Assets/Text/sp_ctxt.csv b/SOURCES/Assets/Text/sp_ctxt.csv index 3868304..e1ffa59 100644 --- a/SOURCES/Assets/Text/sp_ctxt.csv +++ b/SOURCES/Assets/Text/sp_ctxt.csv @@ -1,5 +1,6 @@ 234,Da€os por colisi’n activados 34,Da€os por colisi’n desactivados -950,Create new save -951,Replace existing save +950,Load game +951,Save game 952,This save already exists! Try again. +953,New game diff --git a/SOURCES/GAMEMENU.C b/SOURCES/GAMEMENU.C index d683ca1..1bac08a 100644 --- a/SOURCES/GAMEMENU.C +++ b/SOURCES/GAMEMENU.C @@ -39,13 +39,12 @@ UWORD GameQuitMenuWithoutSave[] = { UWORD GameQuitMenu[] = { 0, // selected - 5, // nb entries + 4, // nb entries 240, // y center 0, // .dia num 0, 28, // continuer jeu - 0, 21, // load game - 0, 950, // new save - 0, 951, // gestion saved game + 0, 950, // load game + 0, 951, // save game 0, 27 // abandonner partie } ; @@ -133,7 +132,7 @@ ULONG TimerSample ; // save players games #define MAX_PLAYER 200 -#define AUTO_SAVE_NAME "AUTO" +#define AUTO_SAVE_NAME "AUTOSAVE" UBYTE NumVersion = 0 ; @@ -1204,7 +1203,7 @@ void CopyBlockPhysMCGA( LONG x0, LONG y0, LONG x1, LONG y1 ) *══════════════════════════════════════════════════════════════════════════*/ /*──────────────────────────────────────────────────────────────────────────*/ -WORD PlayerGameList( UBYTE **ptrlistname, UBYTE *listname, WORD showAutoSave ) +WORD PlayerGameList( UBYTE **ptrlistname, UBYTE *listname, WORD showAutoSave, WORD showNewGame ) { struct find_t fileinfo ; ULONG rc ; @@ -1213,6 +1212,25 @@ WORD PlayerGameList( UBYTE **ptrlistname, UBYTE *listname, WORD showAutoSave ) WORD nb = 0 ; FILE* handle ; + if (showNewGame) + { + int i = 0; + UBYTE string[256]; + + GetMenuMultiTextAux(953, string); + + *ptrlistname++ = listname; + + for (i = 0; i < strlen(string) && string[i] != 0; i++) + { + *listname++ = string[i]; + } + + *listname++ = 0; + + nb++; + if (nb == MAX_PLAYER) return nb; + } if (showAutoSave) { @@ -1891,7 +1909,7 @@ try_again: #define NB_GAME_CHOICE 6 -WORD ChoosePlayerName( WORD mess, WORD showAutoSave ) +WORD ChoosePlayerName( WORD mess, WORD showAutoSave, WORD showNewGame ) { WORD flag = 1 ; UBYTE *listplayername ; @@ -1914,7 +1932,7 @@ WORD ChoosePlayerName( WORD mess, WORD showAutoSave ) TheEnd( NOT_ENOUGH_MEM, "Choose Player Name" ) ; } - nb = PlayerGameList( ptrlist, listplayername, showAutoSave ) ; + nb = PlayerGameList( ptrlist, listplayername, showAutoSave, showNewGame ) ; if( !nb ) return FALSE ; @@ -1977,7 +1995,8 @@ WORD ChoosePlayerName( WORD mess, WORD showAutoSave ) if( Fire ) { - retval = 1 ; + // New Game option is in index 0, return 2 if this is selected, else return 1 + retval = showNewGame && select == 0 ? 2 : 1 ; break ; } } @@ -2525,7 +2544,7 @@ void SavedGameManagement() break ; case 41: // copier - if( ChoosePlayerName( 41, 1 ) ) + if( ChoosePlayerName( 41, 1, 0 ) ) { UBYTE *ptr,*ptrs ; LONG size ; @@ -2563,7 +2582,7 @@ void SavedGameManagement() break ; case 45: // detruire - if( ChoosePlayerName( 45, 0 ) ) + if( ChoosePlayerName( 45, 0, 0 ) ) { CopyScreen( Screen, Log ) ; @@ -2749,7 +2768,7 @@ LONG MainGameMenu() case 21: // load - if( !ChoosePlayerName( 21, 1 ) ) break ; + if( !ChoosePlayerName( 21, 1, 0 ) ) break ; MenuInitGame(-1,0,0); while( Key OR Fire ) ; // provisoire @@ -2775,6 +2794,9 @@ LONG QuitMenu(WORD showSaveOptions) LONG retValue = -999; WORD select ; LONG memoflagspeak ; + WORD playerNameResult; + WORD doSaveGame = 0; + CopyScreen( Log, Screen ) ; HQ_StopSample() ; @@ -2792,8 +2814,16 @@ LONG QuitMenu(WORD showSaveOptions) switch( select ) // num mess { - case 21: // load - if (!ChoosePlayerName(21, 1)) + case 27: // abandonner + retValue = 1; + break; + + case 28: // continue + retValue = 0; + break; + + case 950: // load game + if (!ChoosePlayerName(950, 1, 0)) { //if no load file is selected, reset dialog file to current island InitDial(START_FILE_ISLAND + Island); @@ -2801,40 +2831,28 @@ LONG QuitMenu(WORD showSaveOptions) } while (Key OR Fire); // provisoire - + //Returning false was blocking the menu sometimes, returning true should stop the previous main loop game flow, doesn't appear to cause issues retValue = 2; break; - case 27: // abandonner - retValue = 1; - break; - - case 28: // continue - retValue = 0; - break; + case 951: //save game + playerNameResult = ChoosePlayerName(951, 0, 1); + doSaveGame = 0; - case 950: // new save - if (InputPlayerName(950, 1)) + if (playerNameResult == 2) { - SaveComportement = Comportement; - SaveBeta = ListObjet[NUM_PERSO].Beta; - - SceneStartX = ListObjet[NUM_PERSO].PosObjX; - SceneStartY = ListObjet[NUM_PERSO].PosObjY; - SceneStartZ = ListObjet[NUM_PERSO].PosObjZ; - - SaveGameWithName(PlayerName, 0); + if (InputPlayerName(951, 1)) + { + doSaveGame = 1; + } + } + else if (playerNameResult) + { + doSaveGame = 1; } - //reset dialog file to current island - InitDial(START_FILE_ISLAND + Island); - - retValue = 0; - break; - - case 951: //replace save - if (ChoosePlayerName(951, 0)) + if (doSaveGame) { SaveComportement = Comportement; SaveBeta = ListObjet[NUM_PERSO].Beta; diff --git a/SOURCES/GAMEMENU.DEF b/SOURCES/GAMEMENU.DEF index 690b3f3..077ed81 100644 --- a/SOURCES/GAMEMENU.DEF +++ b/SOURCES/GAMEMENU.DEF @@ -16,7 +16,7 @@ extern void ExtInitMcga(void); extern void ExtInitSvga(void); extern void TestRestoreModeSVGA(long ); extern void CopyBlockPhysMCGA(long ,long ,long ,long ); -extern short PlayerGameList(unsigned char **,unsigned char *, short ); +extern short PlayerGameList(unsigned char **,unsigned char *, short, short ); extern short FindPlayerFile(void); extern void SaveGame(void); extern void LoadGame(void); @@ -25,7 +25,7 @@ extern void DrawSingleString(short ,short ,unsigned char *); extern void DrawOneLetter(short ,short ,short ); extern void DrawAllLetters(void); extern short InputPlayerName(short, short ); -extern short ChoosePlayerName(short, short ); +extern short ChoosePlayerName(short, short, short ); extern void DrawOneChoice(short ,short ,short ,short ,short ); extern void InfoWallCollisionDamage(); extern void DrawGameMenu(unsigned short *,short ); From fcddc0b271bfde432e2cc979793b535a8641207b Mon Sep 17 00:00:00 2001 From: Rui Date: Fri, 1 Jul 2022 11:47:45 +0100 Subject: [PATCH 28/40] Undo .gitignore change --- .gitignore | 1 - 1 file changed, 1 deletion(-) diff --git a/.gitignore b/.gitignore index 463d963..3d4efd0 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,3 @@ *.OBJ *.ERR SOURCES/LBA0.EXE -BIN/ \ No newline at end of file From 2fed209db979b79b6eba5b0e6d14f5b3b04cf9ec Mon Sep 17 00:00:00 2001 From: Rui Date: Fri, 1 Jul 2022 16:15:16 +0100 Subject: [PATCH 29/40] Added #define to allow switching between Windows and DOS file name saving. Added compatibility to load and replace previous version save files (imported and named S0000.LBA, tested with TLBA Classic save files) --- SOURCES/C_EXTERN.H | 1 + SOURCES/DEFINES.H | 5 +++++ SOURCES/GAMEMENU.C | 46 ++++++++++++++++++++++++++++++++++++++++++---- SOURCES/GLOBAL.C | 1 + SOURCES/OBJECT.C | 2 +- SOURCES/PERSO.C | 1 + 6 files changed, 51 insertions(+), 5 deletions(-) diff --git a/SOURCES/C_EXTERN.H b/SOURCES/C_EXTERN.H index a51d41a..4a3f06d 100644 --- a/SOURCES/C_EXTERN.H +++ b/SOURCES/C_EXTERN.H @@ -250,6 +250,7 @@ extern WORD HasLoadedListZoneOnSave; extern WORD HasLoadedKeysOnSave ; extern WORD HasLoadedInventoryOnSave; extern WORD HasLoadedListFlagCubeOnSave; +extern WORD DisableAutoSave; extern WORD NbFourLeafClover ; extern WORD NbCloverBox ; diff --git a/SOURCES/DEFINES.H b/SOURCES/DEFINES.H index 4ff27c0..99907aa 100644 --- a/SOURCES/DEFINES.H +++ b/SOURCES/DEFINES.H @@ -36,6 +36,11 @@ //path des ressources #define PATH_RESSOURCE "" +// with this define, save file names will use the name inserted by the player (e.g. TWINSEN.LBA), but these will be truncated on DOS and open the possibility of different saves replacing each other +#define WINDOWS_SAVE 1 + +// uncomment this line to go back to DOS file name saving (S0000.LBA), to bypass the DOS truncating issue +//#undef WINDOWS_SAVE /*──────────────────────────────────────────────────────────────────────────*/ /*──────────────────────────────────────────────────────────────────────────*/ diff --git a/SOURCES/GAMEMENU.C b/SOURCES/GAMEMENU.C index 1bac08a..40b59de 100644 --- a/SOURCES/GAMEMENU.C +++ b/SOURCES/GAMEMENU.C @@ -1346,6 +1346,7 @@ WORD FindPlayerFile() void SaveGame() { + strcpy(PlayerName, AUTO_SAVE_NAME); SaveGameWithName(AUTO_SAVE_NAME, 1); } @@ -1359,10 +1360,45 @@ void SaveGameWithName(char* fileName, WORD isAutoSave) if (fileName) { char savePath[1024]; - - strcpy(savePath, PATH_RESSOURCE); - strcat(savePath, fileName); - strcat(savePath, ".LBA"); +#ifdef WINDOWS_SAVE + + //Added this check to make sure if there are S0000.LBA files that can be replaced. This allows to replace save files from previous versions without creating new ones (like TLBA Classic S0000.LBA save files) + if (FindPlayerFile()) + { + //Use the already existing save file path name (uses S0000.LBA if it already existed in the save folder) + strcpy(savePath, GamePathname); + } + else + { + //If the file doesn't exist, create a new one with fileName as name + strcpy(savePath, PATH_RESSOURCE); + strcat(savePath, fileName); + strcat(savePath, ".LBA"); + } +#else + if (isAutoSave) + { + strcpy(savePath, PATH_RESSOURCE); + strcat(savePath, fileName); + strcat(savePath, ".LBA"); + } + else + { + if (FindPlayerFile()) + { + strcpy(savePath, GamePathname); + } + else + { + do + { + strcpy(savePath, PATH_RESSOURCE"S"); + strcat(savePath, Itoa(Rnd(10000))); + strcat(savePath, ".LBA"); + } while (FileSize(savePath) != 0); + } + } +#endif handle = OpenWrite(savePath); } @@ -1554,6 +1590,8 @@ void LoadGame() HasLoadedKeysOnSave = successKeys && NbLittleKeys > 0; HasLoadedListFlagCubeOnSave = successNbListFlagCube && successListFlagCube; + DisableAutoSave = 1; // do not let the code auto save immediately after loading a save + NumCube = -1 ; FlagChgCube = 3 ; } diff --git a/SOURCES/GLOBAL.C b/SOURCES/GLOBAL.C index c738f41..3df151b 100644 --- a/SOURCES/GLOBAL.C +++ b/SOURCES/GLOBAL.C @@ -179,6 +179,7 @@ WORD HasLoadedListZoneOnSave = 0; WORD HasLoadedKeysOnSave = 0; WORD HasLoadedInventoryOnSave = 0; WORD HasLoadedListFlagCubeOnSave = 0; +WORD DisableAutoSave = 0; WORD Island = 0 ; WORD Fuel = 0 ; diff --git a/SOURCES/OBJECT.C b/SOURCES/OBJECT.C index cacf3cb..d85f908 100644 --- a/SOURCES/OBJECT.C +++ b/SOURCES/OBJECT.C @@ -534,7 +534,7 @@ void ChangeCube() SetLightVector( AlphaLight, BetaLight, 0 ) ; // PlayMidiFile( CubeJingle ) ; - if( NewCube != oldcube && !HasLoadedSave) + if( NewCube != oldcube && !DisableAutoSave) { SaveComportement = Comportement ; SaveBeta = ListObjet[NUM_PERSO].Beta ; diff --git a/SOURCES/PERSO.C b/SOURCES/PERSO.C index cd377b2..417ea93 100644 --- a/SOURCES/PERSO.C +++ b/SOURCES/PERSO.C @@ -989,6 +989,7 @@ startloop: HasLoadedListObjetsOnSave = 0; HasLoadedListObjetTracksOnSave = 0; HasLoadedListFlagCubeOnSave = 0; + DisableAutoSave = 0; } /* ptrobj = &ListObjet[ 4 ] ; From 88047aeb0b8b75fa481b63a5349e80ce54a82fb0 Mon Sep 17 00:00:00 2001 From: Rui Date: Fri, 1 Jul 2022 18:28:41 +0100 Subject: [PATCH 30/40] Small change to optimize how auto save is handled in SaveGameWithName function --- SOURCES/GAMEMENU.C | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/SOURCES/GAMEMENU.C b/SOURCES/GAMEMENU.C index 40b59de..a48ebdc 100644 --- a/SOURCES/GAMEMENU.C +++ b/SOURCES/GAMEMENU.C @@ -1363,14 +1363,15 @@ void SaveGameWithName(char* fileName, WORD isAutoSave) #ifdef WINDOWS_SAVE //Added this check to make sure if there are S0000.LBA files that can be replaced. This allows to replace save files from previous versions without creating new ones (like TLBA Classic S0000.LBA save files) - if (FindPlayerFile()) + //No need to perform this validation if we're doing an auto save + if (!isAutoSave && FindPlayerFile()) { //Use the already existing save file path name (uses S0000.LBA if it already existed in the save folder) strcpy(savePath, GamePathname); } else { - //If the file doesn't exist, create a new one with fileName as name + //If the file doesn't exist, create a new one with fileName as name, or replace if it's auto save or existing and not using S0000.LBA naming strcpy(savePath, PATH_RESSOURCE); strcat(savePath, fileName); strcat(savePath, ".LBA"); From 451348fa4f46e6e720e680a1678b542069a424c0 Mon Sep 17 00:00:00 2001 From: Rui Date: Sat, 2 Jul 2022 22:42:18 +0100 Subject: [PATCH 31/40] Implemented last valid state for Twinsen to return to when loosing a life. Added some time of invulnerability when he respawns to give the player a chance to move away from danger. --- SOURCES/C_EXTERN.H | 4 ++ SOURCES/GAMEMENU.C | 16 ++++-- SOURCES/GLOBAL.C | 4 ++ SOURCES/OBJECT.C | 6 ++- SOURCES/PERSO.C | 123 +++++++++++++++++++++++++++++++++------------ 5 files changed, 116 insertions(+), 37 deletions(-) diff --git a/SOURCES/C_EXTERN.H b/SOURCES/C_EXTERN.H index 4a3f06d..2dfa268 100644 --- a/SOURCES/C_EXTERN.H +++ b/SOURCES/C_EXTERN.H @@ -200,6 +200,8 @@ extern WORD GameListChoice[] ; /*--------- perso ----------------------------*/ +extern WORD PersoInvulnerable; + extern WORD FlagTheEnd ; extern WORD ActionNormal ; @@ -250,6 +252,7 @@ extern WORD HasLoadedListZoneOnSave; extern WORD HasLoadedKeysOnSave ; extern WORD HasLoadedInventoryOnSave; extern WORD HasLoadedListFlagCubeOnSave; +extern WORD HasLoadedLastValidPersoOnSave; extern WORD DisableAutoSave; extern WORD NbFourLeafClover ; @@ -307,6 +310,7 @@ extern T_HQR_HEADER *HQR_Anims ; extern LONG NbObjets ; extern T_OBJET ListObjet[] ; +extern T_OBJET LastValidPerso; extern T_SORT ListTri[] ; diff --git a/SOURCES/GAMEMENU.C b/SOURCES/GAMEMENU.C index a48ebdc..98e58bb 100644 --- a/SOURCES/GAMEMENU.C +++ b/SOURCES/GAMEMENU.C @@ -1480,6 +1480,7 @@ void SaveGameWithName(char* fileName, WORD isAutoSave) wbyte = MAX_FLAGS_CUBE; Write(handle, &wbyte, 1); // nb octets Write(handle, &ListFlagCube, MAX_FLAGS_CUBE); + Write(handle, &LastValidPerso, sizeof(T_OBJET)); } Close( handle ) ; @@ -1493,7 +1494,7 @@ void LoadGame() WORD wword ; UBYTE wbyte ; UBYTE *ptr ; - int successInventory = 0, successKeys = 0, successListObjets = 0, successNbZones = 0, successListZones = 0, successListExtras = 0, successNbListFlagCube = 0, successListFlagCube = 0; + int successInventory = 0, successKeys = 0, successListObjets = 0, successNbZones = 0, successListZones = 0, successListExtras = 0, successNbListFlagCube = 0, successListFlagCube = 0, successLastValidPerso = 0; int i; handle = OpenRead( GamePathname ) ; @@ -1574,15 +1575,19 @@ void LoadGame() if (successNbListFlagCube && wbyte > 0) successListFlagCube = Read(handle, &ListFlagCube, wbyte); + // Last valid perso obj + successLastValidPerso = Read(handle, &LastValidPerso, sizeof(T_OBJET)); + Close( handle ) ; //These flags are here to help the code identify if objects in a scene are coming from a save or from the HQR file. They also help with keeping retro compatibility with previous version save files HasLoadedSave = successListObjets || successListExtras || successNbZones || successListZones || - successKeys || successNbListFlagCube || successListFlagCube; /*If any of these are present in the save file, - it means we are loading a new version of the save files. If not, it means we are loading a previous version AUTO save file, - therefore the code should run the same logic for previous versions. - Inventory is not checked because it was already in original save files.*/ + successKeys || successNbListFlagCube | + successListFlagCube || successLastValidPerso; /*If any of these are present in the save file, + it means we are loading a new version of the save files. If not, it means we are loading a previous version AUTO save file, + therefore the code should run the same logic for previous versions. + Inventory is not checked because it was already in original save files.*/ HasLoadedInventoryOnSave = successInventory; HasLoadedListObjetsOnSave = successListObjets; HasLoadedListObjetTracksOnSave = successListObjets; @@ -1590,6 +1595,7 @@ void LoadGame() HasLoadedListZoneOnSave = successNbZones && NbZones > 0 && successListZones; HasLoadedKeysOnSave = successKeys && NbLittleKeys > 0; HasLoadedListFlagCubeOnSave = successNbListFlagCube && successListFlagCube; + HasLoadedLastValidPersoOnSave = successLastValidPerso; DisableAutoSave = 1; // do not let the code auto save immediately after loading a save diff --git a/SOURCES/GLOBAL.C b/SOURCES/GLOBAL.C index 3df151b..492d49c 100644 --- a/SOURCES/GLOBAL.C +++ b/SOURCES/GLOBAL.C @@ -127,6 +127,8 @@ WORD GameListChoice[10] ; // max 7 (normally) /*--------- perso ----------------------------*/ +WORD PersoInvulnerable = 0; + WORD FlagTheEnd = FALSE ; WORD ActionNormal = FALSE ; @@ -179,6 +181,7 @@ WORD HasLoadedListZoneOnSave = 0; WORD HasLoadedKeysOnSave = 0; WORD HasLoadedInventoryOnSave = 0; WORD HasLoadedListFlagCubeOnSave = 0; +WORD HasLoadedLastValidPersoOnSave = 0; WORD DisableAutoSave = 0; WORD Island = 0 ; @@ -241,6 +244,7 @@ T_HQR_HEADER *HQR_Anims ; LONG NbObjets = 0 ; T_OBJET ListObjet[MAX_OBJETS] ; +T_OBJET LastValidPerso; T_SORT ListTri[MAX_OBJETS+MAX_EXTRAS] ; diff --git a/SOURCES/OBJECT.C b/SOURCES/OBJECT.C index d85f908..74b064d 100644 --- a/SOURCES/OBJECT.C +++ b/SOURCES/OBJECT.C @@ -545,6 +545,9 @@ void ChangeCube() StartInitAllObjs(); + if (!HasLoadedLastValidPersoOnSave) + LastValidPerso = ListObjet[NUM_PERSO]; + NbLittleKeys = HasLoadedKeysOnSave ? NbLittleKeys : 0 ; MagicBall = -1 ; LastJoyFlag = TRUE ; @@ -591,7 +594,8 @@ void HitObj( WORD numhitter, WORD num, WORD hitforce, WORD beta ) ptrobjt = &ListObjet[ num ] ; - if( ptrobjt->LifePoint <= 0 ) return ; + // Ignore hits on Twinsen if he is marked as invulnerable (after loosing a life) + if( ptrobjt->LifePoint <= 0 || (num == NUM_PERSO && PersoInvulnerable)) return ; ptrobjt->HitBy = numhitter ; diff --git a/SOURCES/PERSO.C b/SOURCES/PERSO.C index 417ea93..b22ebd8 100644 --- a/SOURCES/PERSO.C +++ b/SOURCES/PERSO.C @@ -15,6 +15,8 @@ extern UBYTE *BufMemoSeek ; #endif ULONG SpriteMem, SampleMem, AnimMem ; +ULONG ValidPositionTimer; +ULONG PersoInvulnerableTimer; //WORD Lig=0 ; /*══════════════════════════════════════════════════════════════════════════*/ @@ -86,6 +88,52 @@ void CheckSavePcx() } #endif +/*══════════════════════════════════════════════════════════════════════════* + Auxiliary Functions + *══════════════════════════════════════════════════════════════════════════*/ + /*──────────────────────────────────────────────────────────────────────────*/ +WORD isObjectInAnimation(T_OBJET* ptrobj, WORD numAnim) +{ + return ptrobj->GenAnim == numAnim || ptrobj->Anim == numAnim || ptrobj->NextGenAnim == numAnim; +} + + +WORD validatePersoPosition() +{ + T_OBJET* ptrobj; + WORD isJumping = 0, isDrowning = 0, isGettingHit = 0; + + if (NbObjets <= NUM_PERSO) + return FALSE; + + ptrobj = &ListObjet[NUM_PERSO]; + + if (ptrobj->Body == -1 || ptrobj->WorkFlags & OBJ_DEAD) // if dead, not valid + return FALSE; + + if (ptrobj->Move != MOVE_MANUAL) // if player input for movement is disabled, not a valid position + return FALSE; + + if (Comportement == C_PROTOPACK && isObjectInAnimation(ptrobj, GEN_ANIM_MARCHE)) // if behavior is in protopack, and moving forward (flying), do not save position + return FALSE; + + isJumping = isObjectInAnimation(ptrobj, GEN_ANIM_SAUTE); + isDrowning = isObjectInAnimation(ptrobj, GEN_ANIM_NOYADE); + isGettingHit = isObjectInAnimation(ptrobj, GEN_ANIM_CHOC) || isObjectInAnimation(ptrobj, GEN_ANIM_CHOC2); + + // reset timer if character is in jumping, drowning or getting hit animation, this gives some time to revalidate once the animation is finished(i.e.when the animation finished on top of water but not yet drowning, to avoid saving position in this state) + if (isJumping || isDrowning || isGettingHit) + ValidPositionTimer = TimerRef; + + return !isJumping && // not jumping + !isDrowning && // not drowning + !isGettingHit && // not getting hit + !isObjectInAnimation(ptrobj, GEN_ANIM_MORT) && // not dying + !isObjectInAnimation(ptrobj, GEN_ANIM_ECHELLE) && // not climbing ladder + !isObjectInAnimation(ptrobj, GEN_ANIM_MONTE) && // not mounted + !isObjectInAnimation(ptrobj, GEN_ANIM_TOMBE) && !(ptrobj->WorkFlags & FALLING); // not falling +} + /*══════════════════════════════════════════════════════════════════════════* @@ -792,6 +840,13 @@ startloop: { InitAnim( GEN_ANIM_MORT, ANIM_SET, GEN_ANIM_RIEN, NUM_PERSO ) ; ptrobj->Move = NO_MOVE ; + //Disable collisions on Twinsen to allow other objects to continue their tracks while the death animation is playing + ptrobj->Flags = OBJ_FALLABLE + + ~CHECK_ZONE + + ~CHECK_OBJ_COL + + ~CHECK_BRICK_COL + + CHECK_CODE_JEU; + ptrobj->WorkFlags &= ~OK_HIT; } else // tout objet { @@ -912,37 +967,27 @@ startloop: // restart NbFourLeafClover-- ; - //For now, if death occurs in water, set position to cube start. Ideally it should work like in LBA2 but might require some code refactoring - //Do not reset scene any longer - if (FlagWater) - { - //If respawning Twinsen in cube start position generates softlocks, uncomment these to respawn all objects to scene start - //NewCube = NumCube; - //FlagChgCube = 3; - - SceneStartX = CubeStartX; - SceneStartY = CubeStartY; - SceneStartZ = CubeStartZ; - } - FlagWater = FALSE; - ListObjet[NUM_PERSO].PosObjX = SceneStartX; - ListObjet[NUM_PERSO].PosObjY = SceneStartY; - ListObjet[NUM_PERSO].PosObjZ = SceneStartZ; + PersoInvulnerable = 1; + PersoInvulnerableTimer = TimerRef; + ListObjet[NUM_PERSO] = LastValidPerso; ListObjet[NUM_PERSO].Move = MOVE_MANUAL; - + ListObjet[NUM_PERSO].GenAnim = ListObjet[NUM_PERSO].Anim = GEN_ANIM_RIEN; ListObjet[NUM_PERSO].LifePoint = 50 ; MagicPoint = MagicLevel * 20 ; - StartXCube = ((ListObjet[NUM_PERSO].PosObjX+DEMI_BRICK_XZ)/SIZE_BRICK_XZ) ; - StartYCube = ((ListObjet[NUM_PERSO].PosObjY+SIZE_BRICK_Y)/SIZE_BRICK_Y) ; - StartZCube = ((ListObjet[NUM_PERSO].PosObjZ+DEMI_BRICK_XZ)/SIZE_BRICK_XZ) ; + SetComportement( Comportement ); - FirstTime = TRUE ; - FlagFade = TRUE ; + InitIncrustDisp(INCRUST_OBJ, + FLAG_CLOVER, + 0, 0, + 0, 0, 3); + + //FirstTime = TRUE ; + //FlagFade = TRUE ; goto startloop ; } else // game over @@ -976,21 +1021,37 @@ startloop: } } + if (i == NUM_PERSO) + { + //About 3 seconds after, make character vulnerable again. Consider changing 150 to something more precise, as it may give different results based on framerate + if (PersoInvulnerable && TimerRef - PersoInvulnerableTimer >= 150) + PersoInvulnerable = 0; + + // 25 is approximately 500ms in LIB_SYS TimerRef. Consider changing 25 to something more precise, as it may give different results based on framerate + if (TimerRef - ValidPositionTimer >= 25 && validatePersoPosition()) + { + ValidPositionTimer = TimerRef; + + LastValidPerso = ListObjet[NUM_PERSO]; + } + } + if( NewCube != -1 ) { goto startloop ; } } - if (NbObjets > 0) - { - HasLoadedSave = 0; - HasLoadedInventoryOnSave = 0; - HasLoadedListObjetsOnSave = 0; - HasLoadedListObjetTracksOnSave = 0; - HasLoadedListFlagCubeOnSave = 0; - DisableAutoSave = 0; - } + if (NbObjets > 0) + { + HasLoadedSave = 0; + HasLoadedInventoryOnSave = 0; + HasLoadedListObjetsOnSave = 0; + HasLoadedListObjetTracksOnSave = 0; + HasLoadedListFlagCubeOnSave = 0; + HasLoadedLastValidPersoOnSave = 0; + DisableAutoSave = 0; + } /* ptrobj = &ListObjet[ 4 ] ; CoulText( 15, 0 ) ; From a56fe074c378d738ff5b130d83826e653597019c Mon Sep 17 00:00:00 2001 From: Rui Date: Sun, 3 Jul 2022 15:29:18 +0100 Subject: [PATCH 32/40] Fix grobo in library walking over table after save. --- SOURCES/DISKFUNC.C | 5 +++-- SOURCES/OBJECT.C | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/SOURCES/DISKFUNC.C b/SOURCES/DISKFUNC.C index f07ac11..82cd6a0 100644 --- a/SOURCES/DISKFUNC.C +++ b/SOURCES/DISKFUNC.C @@ -196,7 +196,7 @@ WORD LoadScene( WORD numscene ) { //Starting animation will still be the one from SCENE.HQR file (this is to avoid a glitch when a NPC is in the middle of an animation when a save is made, other than the default one like getting hit) //If the NPC has a tracking flow, attempt to use the last memorized track animation - savedPtrObj->GenAnim = savedPtrObj->OffsetTrack != -1 && savedPtrObj->MemoTrackGenAnim ? savedPtrObj->MemoTrackGenAnim : ptrobj->GenAnim; + savedPtrObj->GenAnim = savedPtrObj->OffsetTrack != -1 && savedPtrObj->MemoTrackGenAnim && savedPtrObj->MemoTrackGenAnim != NO_ANIM ? savedPtrObj->MemoTrackGenAnim : ptrobj->GenAnim; //This will retain NPC and object position and other states when loading a save *ptrobj = *savedPtrObj; @@ -205,7 +205,8 @@ WORD LoadScene( WORD numscene ) if (savedPtrObj->LifePoint <= 0) { ptrobj->GenBody = NO_BODY; - ptrobj->GenAnim = GEN_ANIM_RIEN; + ptrobj->GenAnim = NO_ANIM; + ptrobj->Anim = NO_ANIM; ptrobj->WorkFlags |= OBJ_DEAD; ptrobj->Sprite = -1; ptrobj->Body = -1; diff --git a/SOURCES/OBJECT.C b/SOURCES/OBJECT.C index 74b064d..ab572e3 100644 --- a/SOURCES/OBJECT.C +++ b/SOURCES/OBJECT.C @@ -48,6 +48,7 @@ void InitObject( WORD numobj ) ptrobj->GenBody = GEN_BODY_NORMAL ; ptrobj->GenAnim = GEN_ANIM_RIEN ; + ptrobj->MemoTrackGenAnim = NO_ANIM; ptrobj->PosObjX = 0 ; ptrobj->PosObjY = SIZE_BRICK_Y ; From d28aa0604d08a4316894f317f5c74dcd0a36e4bd Mon Sep 17 00:00:00 2001 From: Rui Date: Sun, 3 Jul 2022 18:08:05 +0100 Subject: [PATCH 33/40] Fix meca penguin not spawning after use on inventory, on reload save --- SOURCES/DISKFUNC.C | 8 ++++++-- SOURCES/GAMEMENU.C | 10 +++++++--- SOURCES/OBJECT.C | 4 ++++ 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/SOURCES/DISKFUNC.C b/SOURCES/DISKFUNC.C index 82cd6a0..1027aed 100644 --- a/SOURCES/DISKFUNC.C +++ b/SOURCES/DISKFUNC.C @@ -201,7 +201,7 @@ WORD LoadScene( WORD numscene ) //This will retain NPC and object position and other states when loading a save *ptrobj = *savedPtrObj; - //Do not render object if it's marked as dead on save + //Do not render object if it's marked as dead on save. if (savedPtrObj->LifePoint <= 0) { ptrobj->GenBody = NO_BODY; @@ -210,9 +210,13 @@ WORD LoadScene( WORD numscene ) ptrobj->WorkFlags |= OBJ_DEAD; ptrobj->Sprite = -1; ptrobj->Body = -1; + ptrobj->ZoneSce = -1; - ptrobj->OffsetLife = -1; ptrobj->OffsetTrack = -1; + + //Do not reset OffsetLife if the object is a meca penguin (because if it's in inventory, it's marked as dead in code, and it's still needed when used) + if (n != NumPingouin) + ptrobj->OffsetLife = -1; } free(savedPtrObj); diff --git a/SOURCES/GAMEMENU.C b/SOURCES/GAMEMENU.C index 98e58bb..e15eae5 100644 --- a/SOURCES/GAMEMENU.C +++ b/SOURCES/GAMEMENU.C @@ -1481,6 +1481,7 @@ void SaveGameWithName(char* fileName, WORD isAutoSave) Write(handle, &wbyte, 1); // nb octets Write(handle, &ListFlagCube, MAX_FLAGS_CUBE); Write(handle, &LastValidPerso, sizeof(T_OBJET)); + Write(handle, &NumPingouin, 2); // save meca penguin use reference } Close( handle ) ; @@ -1494,7 +1495,7 @@ void LoadGame() WORD wword ; UBYTE wbyte ; UBYTE *ptr ; - int successInventory = 0, successKeys = 0, successListObjets = 0, successNbZones = 0, successListZones = 0, successListExtras = 0, successNbListFlagCube = 0, successListFlagCube = 0, successLastValidPerso = 0; + int successInventory = 0, successKeys = 0, successListObjets = 0, successNbZones = 0, successListZones = 0, successListExtras = 0, successNbListFlagCube = 0, successListFlagCube = 0, successLastValidPerso = 0, successMecaPenguin = 0; int i; handle = OpenRead( GamePathname ) ; @@ -1578,13 +1579,16 @@ void LoadGame() // Last valid perso obj successLastValidPerso = Read(handle, &LastValidPerso, sizeof(T_OBJET)); + successMecaPenguin = Read(handle, &NumPingouin, 2); + Close( handle ) ; //These flags are here to help the code identify if objects in a scene are coming from a save or from the HQR file. They also help with keeping retro compatibility with previous version save files HasLoadedSave = successListObjets || successListExtras || successNbZones || successListZones || - successKeys || successNbListFlagCube | - successListFlagCube || successLastValidPerso; /*If any of these are present in the save file, + successKeys || successNbListFlagCube || + successListFlagCube || successLastValidPerso || + successMecaPenguin; /*If any of these are present in the save file, it means we are loading a new version of the save files. If not, it means we are loading a previous version AUTO save file, therefore the code should run the same logic for previous versions. Inventory is not checked because it was already in original save files.*/ diff --git a/SOURCES/OBJECT.C b/SOURCES/OBJECT.C index ab572e3..8c263ae 100644 --- a/SOURCES/OBJECT.C +++ b/SOURCES/OBJECT.C @@ -151,6 +151,10 @@ void StartInitObj( WORD numobj ) { ptrobj->OffsetTrack = -1 ; ptrobj->LabelTrack = -1 ; + } + + if (!HasLoadedListObjetsOnSave) + { ptrobj->OffsetLife = 0; } } From 90ec5d3666f3383f726e8711c425cca2c0c03af6 Mon Sep 17 00:00:00 2001 From: Rui Date: Sun, 3 Jul 2022 20:19:00 +0100 Subject: [PATCH 34/40] Fix for grobo in Funfrock HQ giving more than one key, and also fisherman in Tippet Island (added some auxiliary cube flags to handle this) --- SOURCES/COMMON.H | 1 + SOURCES/C_EXTERN.H | 3 +++ SOURCES/DEFINES.H | 8 ++++++ SOURCES/GAMEMENU.C | 17 +++++++++++-- SOURCES/GERELIFE.C | 61 ++++++++++++++++++++++++++++++++++++++++------ SOURCES/GLOBAL.C | 3 +++ SOURCES/OBJECT.C | 9 +++++++ SOURCES/PERSO.C | 6 +++++ 8 files changed, 99 insertions(+), 9 deletions(-) diff --git a/SOURCES/COMMON.H b/SOURCES/COMMON.H index a8b615c..1f735ce 100644 --- a/SOURCES/COMMON.H +++ b/SOURCES/COMMON.H @@ -107,6 +107,7 @@ #define MAX_FLAGS_CUBE 80 #define MAX_FLAGS_GAME 255 +#define MAX_AUX_FLAGS_CUBE 10 #define MAX_INVENTORY 28 diff --git a/SOURCES/C_EXTERN.H b/SOURCES/C_EXTERN.H index 2dfa268..3878858 100644 --- a/SOURCES/C_EXTERN.H +++ b/SOURCES/C_EXTERN.H @@ -179,6 +179,8 @@ extern T_FLAG ListFlagGame[] ; extern UBYTE ListFlagCube[] ; extern UBYTE ListFlagGame[] ; +extern T_AUX_FLAG_CUBE ListAuxFlagCube[]; //auxiliary cube flags set aside from the original ListFlagCube, to aid in manual saving + extern UBYTE ListFlagInventory[] ; @@ -252,6 +254,7 @@ extern WORD HasLoadedListZoneOnSave; extern WORD HasLoadedKeysOnSave ; extern WORD HasLoadedInventoryOnSave; extern WORD HasLoadedListFlagCubeOnSave; +extern WORD HasLoadedListAuxFlagCubeOnSave; extern WORD HasLoadedLastValidPersoOnSave; extern WORD DisableAutoSave; diff --git a/SOURCES/DEFINES.H b/SOURCES/DEFINES.H index 99907aa..0200a44 100644 --- a/SOURCES/DEFINES.H +++ b/SOURCES/DEFINES.H @@ -266,3 +266,11 @@ typedef struct WORD Y ; WORD Z ; } T_TRACK ; + +// struct for some additional cube flags +typedef struct +{ + WORD NumObj; + WORD PerformedOffsetLife; +} T_AUX_FLAG_CUBE; + diff --git a/SOURCES/GAMEMENU.C b/SOURCES/GAMEMENU.C index e15eae5..98a64a5 100644 --- a/SOURCES/GAMEMENU.C +++ b/SOURCES/GAMEMENU.C @@ -1482,6 +1482,9 @@ void SaveGameWithName(char* fileName, WORD isAutoSave) Write(handle, &ListFlagCube, MAX_FLAGS_CUBE); Write(handle, &LastValidPerso, sizeof(T_OBJET)); Write(handle, &NumPingouin, 2); // save meca penguin use reference + wbyte = MAX_AUX_FLAGS_CUBE; + Write(handle, &wbyte, 1); // nb octets + Write(handle, &ListAuxFlagCube, sizeof(T_AUX_FLAG_CUBE) * MAX_AUX_FLAGS_CUBE); // save auxiliary cube flags } Close( handle ) ; @@ -1495,7 +1498,9 @@ void LoadGame() WORD wword ; UBYTE wbyte ; UBYTE *ptr ; - int successInventory = 0, successKeys = 0, successListObjets = 0, successNbZones = 0, successListZones = 0, successListExtras = 0, successNbListFlagCube = 0, successListFlagCube = 0, successLastValidPerso = 0, successMecaPenguin = 0; + int successInventory = 0, successKeys = 0, successListObjets = 0, successNbZones = 0, successListZones = 0, + successListExtras = 0, successNbListFlagCube = 0, successListFlagCube = 0, successLastValidPerso = 0, + successMecaPenguin = 0, successNbListAuxFlagCube = 0, successListAuxFlagCube = 0; int i; handle = OpenRead( GamePathname ) ; @@ -1579,8 +1584,14 @@ void LoadGame() // Last valid perso obj successLastValidPerso = Read(handle, &LastValidPerso, sizeof(T_OBJET)); + // Meca Penguin successMecaPenguin = Read(handle, &NumPingouin, 2); + // Auxiliary Cube Flags + successNbListAuxFlagCube = Read(handle, &wbyte, 1); // nb octets + if (successNbListAuxFlagCube && wbyte > 0) + successListAuxFlagCube = Read(handle, &ListAuxFlagCube, sizeof(T_AUX_FLAG_CUBE) * wbyte); // read auxiliary cube flags + Close( handle ) ; //These flags are here to help the code identify if objects in a scene are coming from a save or from the HQR file. They also help with keeping retro compatibility with previous version save files @@ -1588,7 +1599,8 @@ void LoadGame() successNbZones || successListZones || successKeys || successNbListFlagCube || successListFlagCube || successLastValidPerso || - successMecaPenguin; /*If any of these are present in the save file, + successMecaPenguin || successNbListAuxFlagCube || + successListAuxFlagCube; /*If any of these are present in the save file, it means we are loading a new version of the save files. If not, it means we are loading a previous version AUTO save file, therefore the code should run the same logic for previous versions. Inventory is not checked because it was already in original save files.*/ @@ -1600,6 +1612,7 @@ void LoadGame() HasLoadedKeysOnSave = successKeys && NbLittleKeys > 0; HasLoadedListFlagCubeOnSave = successNbListFlagCube && successListFlagCube; HasLoadedLastValidPersoOnSave = successLastValidPerso; + HasLoadedListAuxFlagCubeOnSave = successNbListAuxFlagCube && successListAuxFlagCube; DisableAutoSave = 1; // do not let the code auto save immediately after loading a save diff --git a/SOURCES/GERELIFE.C b/SOURCES/GERELIFE.C index 14e91ee..3e3408f 100644 --- a/SOURCES/GERELIFE.C +++ b/SOURCES/GERELIFE.C @@ -19,6 +19,47 @@ extern WORD ZoneGrm ; extern LONG FlagDisplayText ; #endif +/*══════════════════════════════════════════════════════════════════════════* + Auxiliary Functions + *══════════════════════════════════════════════════════════════════════════*/ + /*──────────────────────────────────────────────────────────────────────────*/ +WORD CheckAuxCubeFlag(WORD numobj, WORD offsetLife) +{ + WORD retValue = FALSE; + + int i; + + if (NumCube == 74 && numobj == 5) //Tippet village, fisherman who gives you a key + { + if (ListAuxFlagCube[0].NumObj == numobj && ListAuxFlagCube[0].PerformedOffsetLife == offsetLife) + retValue = TRUE; + } + + if (NumCube == 105 && numobj == 8) //Funfrock headquarters, grobo who gives the key to the coffer with the sabre + { + if (ListAuxFlagCube[0].NumObj == numobj && ListAuxFlagCube[0].PerformedOffsetLife == offsetLife) + retValue = TRUE; + } + + return retValue; +} + +void InsertAuxCubeFlag(WORD numobj, WORD offsetLife) +{ + if (NumCube == 74 && numobj == 5) //Tippet village, fisherman who gives you a key + { + ListAuxFlagCube[0].NumObj = numobj; + ListAuxFlagCube[0].PerformedOffsetLife = offsetLife; + } + + if (NumCube == 105 && numobj == 8) //Funfrock headquarters, grobo who gives the key to the coffer with the sabre + { + ListAuxFlagCube[0].NumObj = numobj; + ListAuxFlagCube[0].PerformedOffsetLife = offsetLife; + } +} + + /*══════════════════════════════════════════════════════════════════════════* β–ˆβ–€β–€β–€β–„ β–ˆβ–€β–€β–€β–ˆ β–ˆ β–ˆ β–ˆβ–€β–€β–€β–€ β–ˆβ–€β–€β–€β–€ β–ˆβ–ˆ β–ˆ β–ˆβ–ˆ β–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆβ–€β–€ β–ˆβ–ˆβ–€β–€ @@ -922,16 +963,22 @@ void DoLife( WORD numobj ) break ; case LM_GIVE_BONUS: - if( ptrobj->OptionFlags & EXTRA_MASK ) + if (!CheckAuxCubeFlag(numobj, LM_GIVE_BONUS)) // check if bonus was already given in aux cube flags { - GiveExtraBonus( ptrobj ) ; + if (ptrobj->OptionFlags & EXTRA_MASK) + { + GiveExtraBonus(ptrobj); + } + if (*PtrPrg++) + { + // ne donne plus rien ???? + ptrobj->OptionFlags |= EXTRA_GIVE_NOTHING; + } + + InsertAuxCubeFlag(numobj, LM_GIVE_BONUS); // if bonus was not given before, insert it now in aux cube flags } - if( *PtrPrg++ ) - { - // ne donne plus rien ???? - ptrobj->OptionFlags |= EXTRA_GIVE_NOTHING ; - } + else *PtrPrg++; break ; case LM_CHANGE_CUBE: diff --git a/SOURCES/GLOBAL.C b/SOURCES/GLOBAL.C index 492d49c..caa93c2 100644 --- a/SOURCES/GLOBAL.C +++ b/SOURCES/GLOBAL.C @@ -108,6 +108,8 @@ T_FLAG ListFlagGame[MAX_FLAGS_GAME] ; UBYTE ListFlagCube[MAX_FLAGS_CUBE] ; UBYTE ListFlagGame[MAX_FLAGS_GAME] ; +T_AUX_FLAG_CUBE ListAuxFlagCube[MAX_AUX_FLAGS_CUBE]; + UBYTE ListFlagInventory[MAX_INVENTORY] ; /*--------- holomap ----------------------------*/ @@ -181,6 +183,7 @@ WORD HasLoadedListZoneOnSave = 0; WORD HasLoadedKeysOnSave = 0; WORD HasLoadedInventoryOnSave = 0; WORD HasLoadedListFlagCubeOnSave = 0; +WORD HasLoadedListAuxFlagCubeOnSave = 0; WORD HasLoadedLastValidPersoOnSave = 0; WORD DisableAutoSave = 0; diff --git a/SOURCES/OBJECT.C b/SOURCES/OBJECT.C index 8c263ae..cfb0d84 100644 --- a/SOURCES/OBJECT.C +++ b/SOURCES/OBJECT.C @@ -333,6 +333,15 @@ void ClearFlagsCube() ListFlagCube[n] = 0; } } + + if (!HasLoadedListAuxFlagCubeOnSave) + { + for (n = 0; n < MAX_AUX_FLAGS_CUBE; n++) + { + ListAuxFlagCube[n].NumObj = -1; + ListAuxFlagCube[n].PerformedOffsetLife = -1; + } + } } /*══════════════════════════════════════════════════════════════════════════* diff --git a/SOURCES/PERSO.C b/SOURCES/PERSO.C index b22ebd8..a9b8e18 100644 --- a/SOURCES/PERSO.C +++ b/SOURCES/PERSO.C @@ -174,6 +174,11 @@ void InitGameLists() { TabHoloPos[i] = 0 ; } + for (i = 0; i < MAX_AUX_FLAGS_CUBE; i++) + { + ListAuxFlagCube[i].NumObj = -1; + ListAuxFlagCube[i].PerformedOffsetLife = -1; + } NbObjets = 0 ; NbBodys = 0 ; @@ -1049,6 +1054,7 @@ startloop: HasLoadedListObjetsOnSave = 0; HasLoadedListObjetTracksOnSave = 0; HasLoadedListFlagCubeOnSave = 0; + HasLoadedListAuxFlagCubeOnSave = 0; HasLoadedLastValidPersoOnSave = 0; DisableAutoSave = 0; } From d9d9e82026dd6f45039d71fd9f27047720608032 Mon Sep 17 00:00:00 2001 From: Rui Date: Mon, 4 Jul 2022 09:56:28 +0100 Subject: [PATCH 35/40] Fix some NPC tracks not restoring their state. --- SOURCES/DISKFUNC.C | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/SOURCES/DISKFUNC.C b/SOURCES/DISKFUNC.C index 1027aed..2036e60 100644 --- a/SOURCES/DISKFUNC.C +++ b/SOURCES/DISKFUNC.C @@ -194,9 +194,9 @@ WORD LoadScene( WORD numscene ) //If loading from a save, replace content with the saved one (but keep the SCENE.HQR file reading flow from LoadScene for other necessary readings afterwards) if (HasLoadedListObjetsOnSave && savedPtrObj) { - //Starting animation will still be the one from SCENE.HQR file (this is to avoid a glitch when a NPC is in the middle of an animation when a save is made, other than the default one like getting hit) - //If the NPC has a tracking flow, attempt to use the last memorized track animation - savedPtrObj->GenAnim = savedPtrObj->OffsetTrack != -1 && savedPtrObj->MemoTrackGenAnim && savedPtrObj->MemoTrackGenAnim != NO_ANIM ? savedPtrObj->MemoTrackGenAnim : ptrobj->GenAnim; + //If object was saved while getting hit, starting animation will be the one from SCENE.HQR file (this is to avoid a glitch when a NPC is in the middle of an animation when a save is made) + if (savedPtrObj->GenAnim == GEN_ANIM_CHOC || savedPtrObj->GenAnim == GEN_ANIM_CHOC2) + savedPtrObj->GenAnim = ptrobj->GenAnim; //This will retain NPC and object position and other states when loading a save *ptrobj = *savedPtrObj; From aeabe962108ac262aa0af9c66cd15e6f5fc4256a Mon Sep 17 00:00:00 2001 From: Rui Date: Mon, 18 Jul 2022 20:22:44 +0100 Subject: [PATCH 36/40] Fix for Twinsen's position not being correct on GameOver AUTOSAVE --- SOURCES/PERSO.C | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/SOURCES/PERSO.C b/SOURCES/PERSO.C index a9b8e18..d435ade 100644 --- a/SOURCES/PERSO.C +++ b/SOURCES/PERSO.C @@ -1007,8 +1007,10 @@ startloop: if( GameOverCube != NumCube ) { NumCube = GameOverCube ; - SceneStartX = SceneStartY = SceneStartZ = -1 ; // mean use startpos } + + SceneStartX = SceneStartY = SceneStartZ = -1; // mean use startpos (manual save gaming: always use startpos, regardless of GameOverCube being different than NumCube or not, this is to prevent Twinsen spawning in the middle of a cube when loading AUTOSAVE, if Gameover was achieved after loading a manual save) + SaveGame() ; GameOver() ; From 8b2dcfd9b2e90e7275addd1d98d505fe988fd7e4 Mon Sep 17 00:00:00 2001 From: Rui Date: Mon, 18 Jul 2022 20:35:19 +0100 Subject: [PATCH 37/40] Fix for valid position when stop flying with protopack --- SOURCES/PERSO.C | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SOURCES/PERSO.C b/SOURCES/PERSO.C index d435ade..74fc094 100644 --- a/SOURCES/PERSO.C +++ b/SOURCES/PERSO.C @@ -94,7 +94,7 @@ void CheckSavePcx() /*──────────────────────────────────────────────────────────────────────────*/ WORD isObjectInAnimation(T_OBJET* ptrobj, WORD numAnim) { - return ptrobj->GenAnim == numAnim || ptrobj->Anim == numAnim || ptrobj->NextGenAnim == numAnim; + return ptrobj->GenAnim == numAnim || ptrobj->Anim == numAnim; //|| ptrobj->NextGenAnim == numAnim; } From 70f53931bce6fc8fa86925d89de544454261ce35 Mon Sep 17 00:00:00 2001 From: Rui Date: Mon, 18 Jul 2022 20:39:23 +0100 Subject: [PATCH 38/40] Changed text in UI for a new save from "New Game" to "Create new save" --- SOURCES/Assets/Text/de_ctxt.csv | 2 +- SOURCES/Assets/Text/en_ctxt.csv | 2 +- SOURCES/Assets/Text/fr_ctxt.csv | 2 +- SOURCES/Assets/Text/it_ctxt.csv | 2 +- SOURCES/Assets/Text/sp_ctxt.csv | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/SOURCES/Assets/Text/de_ctxt.csv b/SOURCES/Assets/Text/de_ctxt.csv index 258cabf..9da77e3 100644 --- a/SOURCES/Assets/Text/de_ctxt.csv +++ b/SOURCES/Assets/Text/de_ctxt.csv @@ -3,4 +3,4 @@ 950,Load game 951,Save game 952,This save already exists! Try again. -953,New game +953,Create new save diff --git a/SOURCES/Assets/Text/en_ctxt.csv b/SOURCES/Assets/Text/en_ctxt.csv index 143252a..25b806b 100644 --- a/SOURCES/Assets/Text/en_ctxt.csv +++ b/SOURCES/Assets/Text/en_ctxt.csv @@ -3,4 +3,4 @@ 950,Load game 951,Save game 952,This save already exists! Try again. -953,New game +953,Create new save diff --git a/SOURCES/Assets/Text/fr_ctxt.csv b/SOURCES/Assets/Text/fr_ctxt.csv index f3cba76..2adc5e9 100644 --- a/SOURCES/Assets/Text/fr_ctxt.csv +++ b/SOURCES/Assets/Text/fr_ctxt.csv @@ -3,4 +3,4 @@ 950,Load game 951,Save game 952,This save already exists! Try again. -953,New game +953,Create new save diff --git a/SOURCES/Assets/Text/it_ctxt.csv b/SOURCES/Assets/Text/it_ctxt.csv index 442ae87..d477fc5 100644 --- a/SOURCES/Assets/Text/it_ctxt.csv +++ b/SOURCES/Assets/Text/it_ctxt.csv @@ -3,4 +3,4 @@ 950,Load game 951,Save game 952,This save already exists! Try again. -953,New game +953,Create new save diff --git a/SOURCES/Assets/Text/sp_ctxt.csv b/SOURCES/Assets/Text/sp_ctxt.csv index e1ffa59..f73b8df 100644 --- a/SOURCES/Assets/Text/sp_ctxt.csv +++ b/SOURCES/Assets/Text/sp_ctxt.csv @@ -3,4 +3,4 @@ 950,Load game 951,Save game 952,This save already exists! Try again. -953,New game +953,Create new save From acd808a0546e3aadfe469376b96452b01ecc2410 Mon Sep 17 00:00:00 2001 From: Rui Date: Tue, 19 Jul 2022 14:15:53 +0100 Subject: [PATCH 39/40] Disable auto save on gameover, and disable copy saved game feature. --- SOURCES/DEFINES.H | 13 +++++++++++++ SOURCES/GAMEMENU.C | 11 +++++++++-- SOURCES/PERSO.C | 8 ++++---- 3 files changed, 26 insertions(+), 6 deletions(-) diff --git a/SOURCES/DEFINES.H b/SOURCES/DEFINES.H index 0200a44..b21960b 100644 --- a/SOURCES/DEFINES.H +++ b/SOURCES/DEFINES.H @@ -41,6 +41,19 @@ // uncomment this line to go back to DOS file name saving (S0000.LBA), to bypass the DOS truncating issue //#undef WINDOWS_SAVE + +// disable auto saving on game over +#define DISABLE_GAME_OVER_SAVE 1 + +// uncomment to reenable auto saving on game over +//#undef DISABLE_GAME_OVER_SAVE + +// disable copy saved game feature +#define DISABLE_COPY_SAVED_GAME 1 + +// uncomment to reenable copy saved game feature +//#undef DISABLE_COPY_SAVED_GAME + /*──────────────────────────────────────────────────────────────────────────*/ /*──────────────────────────────────────────────────────────────────────────*/ diff --git a/SOURCES/GAMEMENU.C b/SOURCES/GAMEMENU.C index 98a64a5..9e1a980 100644 --- a/SOURCES/GAMEMENU.C +++ b/SOURCES/GAMEMENU.C @@ -92,12 +92,18 @@ UWORD GameVolumeMenu[] = { UWORD SavedGameMenu[] = { 0, // selected +#ifndef DISABLE_COPY_SAVED_GAME 3, // nb entries +#else + 2, // nb entries +#endif 0, // y from top. 0, // .dia num 0, 26, // retour menu prec +#ifndef DISABLE_COPY_SAVED_GAME 0, 41, // copier une sauvegarde +#endif 0, 45 // dΓ©truire une sauvegarde } ; @@ -2604,7 +2610,8 @@ void SavedGameManagement() case 26: // quitter flag = 1 ; break ; - +// Do not show copy saved game feature any longer, player can pretty much copy save games with Create New Save feature now +#ifndef DISABLE_COPY_SAVED_GAME case 41: // copier if( ChoosePlayerName( 41, 1, 0 ) ) { @@ -2642,7 +2649,7 @@ void SavedGameManagement() } CopyScreen( Screen, Log ) ; break ; - +#endif case 45: // detruire if( ChoosePlayerName( 45, 0, 0 ) ) { diff --git a/SOURCES/PERSO.C b/SOURCES/PERSO.C index 74fc094..3e7c32e 100644 --- a/SOURCES/PERSO.C +++ b/SOURCES/PERSO.C @@ -997,7 +997,8 @@ startloop: } else // game over { - +// Do not save game when game over is reached any longer +#ifndef DISABLE_GAME_OVER_SAVE NbFourLeafClover = NbCloverBox / 2 ; ListObjet[NUM_PERSO].LifePoint = 25 ; MagicPoint = (MagicLevel*20) / 2 ; @@ -1007,12 +1008,11 @@ startloop: if( GameOverCube != NumCube ) { NumCube = GameOverCube ; + SceneStartX = SceneStartY = SceneStartZ = -1; // mean use startpos } - SceneStartX = SceneStartY = SceneStartZ = -1; // mean use startpos (manual save gaming: always use startpos, regardless of GameOverCube being different than NumCube or not, this is to prevent Twinsen spawning in the middle of a cube when loading AUTOSAVE, if Gameover was achieved after loading a manual save) - SaveGame() ; - +#endif GameOver() ; return 0 ; From ddde6925f7ca561ad80a3498943fafb1f85ac9d1 Mon Sep 17 00:00:00 2001 From: Rui Date: Tue, 19 Jul 2022 14:43:05 +0100 Subject: [PATCH 40/40] Cleared unnecessary code (used previously for memorizing npc track animations but no longer used). --- SOURCES/DEFINES.H | 2 -- SOURCES/GERETRAK.C | 8 ++------ SOURCES/OBJECT.C | 1 - 3 files changed, 2 insertions(+), 9 deletions(-) diff --git a/SOURCES/DEFINES.H b/SOURCES/DEFINES.H index b21960b..c7c7f6b 100644 --- a/SOURCES/DEFINES.H +++ b/SOURCES/DEFINES.H @@ -263,8 +263,6 @@ typedef struct UBYTE CodeJeu ; // brick spΓ©ciale sample ou action - UBYTE MemoTrackGenAnim ; - } T_OBJET ; /* diff --git a/SOURCES/GERETRAK.C b/SOURCES/GERETRAK.C index 23604c2..e28e3fd 100644 --- a/SOURCES/GERETRAK.C +++ b/SOURCES/GERETRAK.C @@ -24,7 +24,6 @@ void DoTrack( WORD numobj ) WORD overflow = 0 ; UBYTE *ptr ; UBYTE n, c ; - UBYTE memoanimtrack; ptrobj = &ListObjet[numobj] ; @@ -108,17 +107,14 @@ void DoTrack( WORD numobj ) /*-------------------------------------------------------------------------*/ case TM_ANIM: - memoanimtrack = *ptrtrack++; - - if (!InitAnim(memoanimtrack, ANIM_REPEAT, 0, numobj)) + if (!InitAnim( *ptrtrack++, ANIM_REPEAT, 0, numobj ) ) { ptrobj->OffsetTrack = memooffsettrack ; flag = FALSE ; } else { - ptrobj->MemoTrackGenAnim = memoanimtrack; - ptrobj->OffsetTrack++; + ptrobj->OffsetTrack++ ; } break ; diff --git a/SOURCES/OBJECT.C b/SOURCES/OBJECT.C index cfb0d84..1b311e8 100644 --- a/SOURCES/OBJECT.C +++ b/SOURCES/OBJECT.C @@ -48,7 +48,6 @@ void InitObject( WORD numobj ) ptrobj->GenBody = GEN_BODY_NORMAL ; ptrobj->GenAnim = GEN_ANIM_RIEN ; - ptrobj->MemoTrackGenAnim = NO_ANIM; ptrobj->PosObjX = 0 ; ptrobj->PosObjY = SIZE_BRICK_Y ;