Skip to content

Commit

Permalink
Beginnings of Playback Mode:
Browse files Browse the repository at this point in the history
~ Playback Mode button opens a replay selection dialog
~ StartPlayback is then called, which matches a level to the replay file and then auto-plays it
~ The Playback Index is stored and incremented via the Postview screen, so that the next item in the Playback list is loaded with each call
~ Playback Mode can be deactivated at any time by simply cancelling the replay in-game
  • Loading branch information
Willicious committed May 17, 2024
1 parent f41e45c commit 80da87c
Show file tree
Hide file tree
Showing 8 changed files with 135 additions and 6 deletions.
10 changes: 10 additions & 0 deletions FSuperLemmixLevelSelect.dfm
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ object FLevelSelect: TFLevelSelect
Font.Style = []
OldCreateOrder = False
Position = poMainFormCenter
OnClick = btnPlaybackModeClick
OnCreate = FormCreate
OnDestroy = FormDestroy
OnShow = FormShow
Expand Down Expand Up @@ -215,6 +216,15 @@ object FLevelSelect: TFLevelSelect
TabOrder = 4
OnClick = btnResetTalismansClick
end
object btnPlaybackMode: TButton
Left = 916
Top = 264
Width = 134
Height = 25
Caption = 'Playback Mode'
TabOrder = 11
OnClick = btnPlaybackModeClick
end
object ilStatuses: TImageList
end
end
29 changes: 28 additions & 1 deletion FSuperLemmixLevelSelect.pas
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ interface
Generics.Collections,
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Buttons,
Dialogs, ComCtrls, StdCtrls, ExtCtrls, ImgList, StrUtils, UMisc, Math, UITypes,
Types, IOUtils, Vcl.FileCtrl, // For Playback Mode
ActiveX, ShlObj, ComObj, // For the shortcut creation
LemNeoParser, GR32_Image, System.ImageList;

Expand All @@ -37,6 +38,7 @@ TFLevelSelect = class(TForm)
btnCleanseOne: TButton;
btnClearRecords: TButton;
btnResetTalismans: TBitBtn;
btnPlaybackMode: TButton;
procedure FormCreate(Sender: TObject);
procedure btnOKClick(Sender: TObject);
procedure tvLevelSelectClick(Sender: TObject);
Expand All @@ -45,6 +47,7 @@ TFLevelSelect = class(TForm)
procedure FormDestroy(Sender: TObject);
procedure btnSaveImageClick(Sender: TObject);
procedure btnMassReplayClick(Sender: TObject);
procedure btnPlaybackModeClick(Sender:TObject);
procedure btnCleanseLevelsClick(Sender: TObject);
procedure btnCleanseOneClick(Sender: TObject);
procedure btnClearRecordsClick(Sender: TObject);
Expand Down Expand Up @@ -429,6 +432,30 @@ procedure TFLevelSelect.btnOKClick(Sender: TObject);
ModalResult := mrOk;
end;

procedure TFLevelSelect.btnPlaybackModeClick(Sender: TObject);
var
ReplayFolder: string;
ReplayFiles: TStringDynArray;
ReplayFile: string;
InitialDir: string;
begin
InitialDir := IncludeTrailingPathDelimiter(AppPath) + SFReplays;

if not SelectDirectory('Select folder containing replays', InitialDir, ReplayFolder) then
Exit;

// Get list of replay files
ReplayFiles := TDirectory.GetFiles(ReplayFolder, '*.nxrp');

// Add replay file names to PlaybackList
for ReplayFile in ReplayFiles do
GameParams.PlaybackList.Add(ReplayFile); // Storing full path for easier access later

GameParams.PlaybackMode := True;
WriteToParams;
ModalResult := mrRetry;
end;

procedure TFLevelSelect.btnResetTalismansClick(Sender: TObject);
var
Obj: TObject;
Expand Down Expand Up @@ -1189,7 +1216,7 @@ procedure TFLevelSelect.btnCleanseLevelsClick(Sender: TObject);

Group := Group.ParentBasePack;

if DirectoryExists(AppPath + 'Cleanse\' + MakeSafeForFilename(Group.Name) + '\') then
if SysUtils.DirectoryExists(AppPath + 'Cleanse\' + MakeSafeForFilename(Group.Name) + '\') then
if MessageDlg('Folder "Cleanse\' + MakeSafeForFilename(Group.Name) + '\" already exists. Continuing will erase it. Continue?',
mtCustom, [mbYes, mbNo], 0) = mrNo then
Exit;
Expand Down
83 changes: 81 additions & 2 deletions GameBaseMenuScreen.pas
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ interface
GameControl,
GR32, GR32_Image, GR32_Layers, GR32_Resamplers,
Generics.Collections,
Math, Forms, Controls, ExtCtrls, Dialogs, Classes, SysUtils, Windows;
Math, Forms, Controls, ExtCtrls, Dialogs, Classes, SysUtils, Windows,
IOUtils, Vcl.FileCtrl; // For Playback Mode

const
// Determines the size of the available window space
Expand Down Expand Up @@ -170,6 +171,7 @@ TGameBaseMenuScreen = class(TGameBaseScreen)
procedure MainFormResized; override;
procedure DrawClassicModeButton;
procedure HandleClassicModeClick;
procedure StartPlayback(Index: Integer);
end;

implementation
Expand All @@ -195,6 +197,80 @@ procedure TGameBaseMenuScreen.CloseScreen(aNextScreen: TGameScreenType);
inherited;
end;

procedure TGameBaseMenuScreen.StartPlayback(Index: Integer);
var
ReplayContent: TStringList;
LevelContent: TStringList;
ReplayFile: string;
LevelFile: string;
ReplayID, LevelID: string;
LevelFiles: TStringDynArray;
LevelsDirectory: string;
j: Integer;
begin
if GameParams.PlaybackMode and ((Index < 0) or (Index >= GameParams.PlaybackList.Count)) then
begin
ShowMessage('Invalid replay index.');
Exit;
end;

LevelsDirectory := GameParams.CurrentLevel.Group.Path;

if LevelsDirectory = '' then
begin
ShowMessage('No valid directory found for the selected level.');
Exit;
end;

LevelFiles := TDirectory.GetFiles(LevelsDirectory, '*.nxlv', TSearchOption.soAllDirectories);

ReplayContent := TStringList.Create;
LevelContent := TStringList.Create;
try
ReplayFile := GameParams.PlaybackList[Index]; // Accessing full path

// Load replay file content
try
ReplayContent.LoadFromFile(ReplayFile);
except
on E: Exception do
begin
ShowMessage('Failed to load replay file: ' + E.Message);
Exit;
end;
end;

// Extract the Replay ID
for j := 0 to ReplayContent.Count - 1 do
begin
if Pos('ID x', ReplayContent[j]) = 1 then
begin
ReplayID := Copy(ReplayContent[j], 4, Length(ReplayContent[j]));
Break;
end;
end;

// Search for "ID x" line in level file
GameParams.FindLevelByID(ReplayID);
GameParams.LoadCurrentLevel();

// Set the value of the current Playback index
GameParams.PlaybackIndex := Index;

// Reload settings to align GameParams with current level
GameParams.Save(scImportant);
GameParams.Load;

LoadedReplayFile := ReplayFile;
LoadReplay;

CloseScreen(gstPreview);
finally
ReplayContent.Free;
LevelContent.Free;
end;
end;

constructor TGameBaseMenuScreen.Create(aOwner: TComponent);
begin
inherited;
Expand Down Expand Up @@ -936,7 +1012,10 @@ procedure TGameBaseMenuScreen.DoLevelSelect;

if PopupResult = mrRetry then
begin
CloseScreen(gstReplayTest)
if GameParams.PlaybackMode then
StartPlayback(0)
else
CloseScreen(gstReplayTest)
end else if not Success then
begin
GameParams.SetLevel(OldLevel);
Expand Down
3 changes: 1 addition & 2 deletions GameBaseScreenCommon.pas
Original file line number Diff line number Diff line change
Expand Up @@ -209,11 +209,10 @@ function TGameBaseScreen.LoadReplay: Boolean;
begin
s := '';

if OpenedViaReplay then
if OpenedViaReplay or GameParams.PlaybackMode then
begin
Result := true; // Return true if opened by replay
s := LoadedReplayFile;

end else begin
Dlg := TOpenDialog.Create(self);
try
Expand Down
8 changes: 7 additions & 1 deletion GameControl.pas
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,6 @@ TDosGameParams = class(TPersistent)
LevelString: String;
BaseLevelPack: TNeoLevelGroup;


// This is initialized by the window in which the game will be played
TargetBitmap : TBitmap32;

Expand All @@ -204,6 +203,10 @@ TDosGameParams = class(TPersistent)
//SysDat : TSysDatRec;
ReplayCheckPath: String;

PlaybackList: TStringList;
PlaybackMode: Boolean;
PlaybackIndex: Integer;

TestModeLevel: TNeoLevelEntry;

constructor Create;
Expand Down Expand Up @@ -948,6 +951,8 @@ constructor TDosGameParams.Create;
E.ClassName + ': ' + E.Message + #10 +
'Default hotkeys have been loaded. Customizations to hotkeys during this session will not be saved.');
end;

PlaybackList := TStringList.Create;
end;

procedure TDosGameParams.CreateBasePack;
Expand Down Expand Up @@ -980,6 +985,7 @@ destructor TDosGameParams.Destroy;
begin
fHotkeys.Free;
BaseLevelPack.Free;
PlaybackList.Free;
inherited Destroy;
end;

Expand Down
3 changes: 3 additions & 0 deletions GamePostviewScreen.pas
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,9 @@ procedure TGamePostviewScreen.BuildScreen;

DrawAllClickables;
ReloadCursor('postview.png');

if GameParams.PlaybackMode then
StartPlayback(GameParams.PlaybackIndex + 1);
finally
ScreenImg.EndUpdate;
end;
Expand Down
3 changes: 3 additions & 0 deletions GamePreviewScreen.pas
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,9 @@ procedure TGamePreviewScreen.BuildScreen;
MakeTalismanOptions;

DrawAllClickables;

if GameParams.PlaybackMode then
BeginPlay;
finally
W.Free;
ScreenImg.EndUpdate;
Expand Down
2 changes: 2 additions & 0 deletions LemGame.pas
Original file line number Diff line number Diff line change
Expand Up @@ -8411,6 +8411,8 @@ procedure TLemmingGame.SetGameResult;

procedure TLemmingGame.RegainControl(Force: Boolean = false);
begin
if Force then GameParams.PlaybackMode := False;

if ReplayInsert and not Force then Exit;

if CurrentIteration > fReplayManager.LastActionFrame then Exit;
Expand Down

0 comments on commit 80da87c

Please sign in to comment.