Subversion Repositories spacemission

Rev

Rev 51 | Rev 53 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 51 Rev 52
Line 74... Line 74...
74
function GetLevelFileName(lev: integer; forceuserdir: boolean): string;
74
function GetLevelFileName(lev: integer; forceuserdir: boolean): string;
75
 
75
 
76
implementation
76
implementation
77
 
77
 
78
uses
78
uses
79
  SysUtils, StrUtils, Global, Windows;
79
  SysUtils, StrUtils, Global, Windows, System.Types;
-
 
80
 
-
 
81
const
-
 
82
  // { iso(1) identified-organization(3) dod(6) internet(1) private(4) enterprise(1) 37476 products(2) spacemission(8) file-format(1) lev-sav-v12(1) }
-
 
83
  // https://hosted.oidplus.com/viathinksoft/?goto=oid%3A1.3.6.1.4.1.37476.2.8.1.1
-
 
84
  OID_LEVSAV_VER12 = '1.3.6.1.4.1.37476.2.8.1.1';
80
 
85
 
81
function GetLevelFileName(lev: integer; forceuserdir: boolean): string;
86
function GetLevelFileName(lev: integer; forceuserdir: boolean): string;
82
 
87
 
83
  function _GetLevelVerzeichnisSystem: string;
88
  function _GetLevelVerzeichnisSystem: string;
84
  begin
89
  begin
Line 137... Line 142...
137
  if fileexists(usr) or forceuserdir then exit(usr);
142
  if fileexists(usr) or forceuserdir then exit(usr);
138
  if fileexists(sys) then exit(sys);
143
  if fileexists(sys) then exit(sys);
139
  exit(usr);
144
  exit(usr);
140
end;
145
end;
141
 
146
 
-
 
147
// this is just an example, there are many
-
 
148
// different ways you can implement this
-
 
149
// more efficiently, ie using a TStringBuilder,
-
 
150
// or even modifying the String in-place...
-
 
151
function CollapseSpaces(const S: string): string;
-
 
152
var
-
 
153
  P: PChar;
-
 
154
  AddSpace: Boolean;
-
 
155
begin
-
 
156
  Result := '';
-
 
157
  AddSpace := False;
-
 
158
  P := PChar(S);
-
 
159
  while P^ <> #0 do
-
 
160
  begin
-
 
161
    while CharInSet(P^, [#1..' ']) do Inc(P);
-
 
162
    if P^ = #0 then Exit;
-
 
163
    if AddSpace then
-
 
164
      Result := Result + ' '
-
 
165
    else
-
 
166
      AddSpace := True;
-
 
167
    repeat
-
 
168
      Result := Result + P^;
-
 
169
      Inc(P);
-
 
170
    until P^ <= ' ';
-
 
171
  end;
-
 
172
end;
-
 
173
 
142
{ TLevelData }
174
{ TLevelData }
143
 
175
 
144
procedure TLevelData.AssignTo(Dest: TPersistent);
176
procedure TLevelData.AssignTo(Dest: TPersistent);
145
var
177
var
146
  DestLevelData: TLevelData;
178
  DestLevelData: TLevelData;
Line 258... Line 290...
258
  curline: integer;
290
  curline: integer;
259
  z, act: integer;
291
  z, act: integer;
260
  sl2: TStringList;
292
  sl2: TStringList;
261
  tmpX, tmpY, tmpLifes: integer;
293
  tmpX, tmpY, tmpLifes: integer;
262
  tmpEnemy: TEnemyType;
294
  tmpEnemy: TEnemyType;
263
  tmpRest: string;
-
 
264
  ergebnis: string;
295
  ergebnis: string;
-
 
296
  ary: TStringDynArray;
-
 
297
  sLine: string;
265
begin
298
begin
266
  Clear;
299
  Clear;
267
 
300
 
268
  LevelEditorLength := DefaultLevelLength;
301
  LevelEditorLength := DefaultLevelLength;
269
  LevelName := '';
302
  LevelName := '';
270
  LevelAuthor := '';
303
  LevelAuthor := '';
271
 
304
 
272
  if sl.Strings[0] = '; SpaceMission 0.3' then
305
  if sl.Strings[0] = '; SpaceMission 0.3' then // do not localize
273
  begin
306
  begin
274
    {$REGION 'Backwards compatibility level format 0.3 (convert to 0.4)'}
307
    {$REGION 'Backwards compatibility level format 0.3 (convert to 0.4)'}
275
    sl.Strings[0] := '; SpaceMission 0.4';
308
    sl.Strings[0] := '; SpaceMission 0.4'; // do not localize
276
    sl.Insert(1, '; LEV-File');
309
    sl.Insert(1, '; LEV-File'); // do not localize
277
    {$ENDREGION}
310
    {$ENDREGION}
278
  end;
311
  end;
279
 
312
 
280
  if (sl.Strings[0] = '; SpaceMission 0.4') and
313
  if (sl.Strings[0] = '; SpaceMission 0.4') and // do not localize
281
     (sl.Strings[1] = '; LEV-File') then
314
     (sl.Strings[1] = '; LEV-File') then // do not localize
282
  begin
315
  begin
283
    {$REGION 'Backwards compatibility level format 0.4 (convert to 1.0)'}
316
    {$REGION 'Backwards compatibility level format 0.4 (convert to 1.0)'}
284
    sl2 := TStringList.Create;
317
    sl2 := TStringList.Create;
285
    try
318
    try
286
      z := 0;
319
      z := 0;
Line 315... Line 348...
315
      FreeAndNil(sl2);
348
      FreeAndNil(sl2);
316
    end;
349
    end;
317
    {$ENDREGION}
350
    {$ENDREGION}
318
  end;
351
  end;
319
 
352
 
320
  if (sl.Strings[0] = '; SpaceMission 1.0') and
353
  if (sl.Strings[0] = '; SpaceMission 1.0') and // do not localize
321
     (sl.Strings[1] = '; LEV-File') then
354
     (sl.Strings[1] = '; LEV-File') then // do not localize
322
  begin
355
  begin
323
    {$REGION 'Level format 1.0'}
356
    {$REGION 'Level format 1.0'}
324
    LevelEditorLength := StrToInt(sl.Strings[2]);
357
    LevelEditorLength := StrToInt(sl.Strings[2]);
325
    curline := 3;
358
    curline := 3;
326
    while curline < sl.Count do
359
    while curline < sl.Count do
Line 335... Line 368...
335
      Inc(curline);
368
      Inc(curline);
336
      AddEnemy(tmpX, tmpY, tmpEnemy, tmpLifes);
369
      AddEnemy(tmpX, tmpY, tmpEnemy, tmpLifes);
337
    end;
370
    end;
338
    {$ENDREGION}
371
    {$ENDREGION}
339
  end
372
  end
340
  else if (SameText(sl.Strings[0], '[SpaceMission Level, Format 1.2]')) or
373
  else if (SameText(sl.Strings[0], '['+OID_LEVSAV_VER12+']')) then
341
          (SameText(sl.Strings[0], '[SpaceMission Savegame, Format 1.2]')) then
-
 
342
  begin
374
  begin
343
    {$REGION 'Level format 1.2'}
375
    {$REGION 'Level format 1.2'}
344
    for curline := 1 to sl.Count-1 do
376
    for curline := 1 to sl.Count-1 do
345
    begin
377
    begin
346
      // 1234567890123456789012345678901234567890
-
 
347
      // 123456 123456 123456 123456 123456 ; Kommentar
-
 
348
      if (sl.Strings[curline].Trim = '') or
378
      sLine := sl.Strings[curline].Trim;
349
         (Copy(sl.Strings[curline], 1, 1) = ';') then
379
      if (sLine = '') or (Copy(sLine, 1, 1) = ';') then continue;
350
        // Do nothing
380
      ary := SplitString(CollapseSpaces(sLine), ' ');
351
      else if Copy(sl.Strings[curline], 1, 6).TrimRight = 'Width' then
381
      if ary[0] = 'Width' then // do not localize
352
      begin
382
      begin
353
        LevelEditorLength := StrToInt(TrimRight(Copy(sl.Strings[curline], 8, 6)))
383
        LevelEditorLength := StrToInt(ary[1]);
-
 
384
        if (Length(ary) > 2) and (Copy(ary[2], 1, 1) <> ';') then
-
 
385
          raise Exception.CreateFmt('Zeile %d ist ungültig (Zusatzinfo am Ende)', [curline+1]);
354
      end
386
      end
355
      else if Copy(sl.Strings[curline], 1, 6).TrimRight = 'Name' then
387
      else if ary[0] = 'Name' then // do not localize
356
      begin
388
      begin
357
        LevelName := TrimRight(Copy(sl.Strings[curline], 8, Length(sl.Strings[curline])))
389
        LevelName := Copy(sLine, Length(ary[0])+2, Length(sLine));
358
      end
390
      end
359
      else if Copy(sl.Strings[curline], 1, 6).TrimRight = 'Author' then
391
      else if ary[0] = 'Author' then // do not localize
360
      begin
392
      begin
361
        LevelAuthor := TrimRight(Copy(sl.Strings[curline], 8, Length(sl.Strings[curline])))
393
        LevelAuthor := Copy(sLine, Length(ary[0])+2, Length(sLine));
362
      end
394
      end
363
      else if Copy(sl.Strings[curline], 1, 6).TrimRight = 'Enemy' then
395
      else if ary[0] = 'Enemy' then // do not localize
364
      begin
396
      begin
365
        tmpEnemy := TEnemyType(strtoint(TrimRight(Copy(sl.Strings[curline], 8, 6))));
397
        tmpEnemy := TEnemyType(strtoint(ary[1]));
366
        tmpX     := strtoint(TrimRight(Copy(sl.Strings[curline], 15, 6)));
398
        tmpX     := strtoint(ary[2]);
367
        tmpY     := strtoint(TrimRight(Copy(sl.Strings[curline], 22, 6)));
399
        tmpY     := strtoint(ary[3]);
368
        tmpLifes := strtoint(TrimRight(Copy(sl.Strings[curline], 29, 6)));
400
        tmpLifes := strtoint(ary[4]);
369
        tmpRest  := Copy(sl.Strings[curline], 36, Length(sl.Strings[curline])-36+1);
-
 
370
        if (Copy(tmpRest, 1, 1) <> ';') and (Trim(tmpRest) <> '') then
401
        if (Length(ary) > 5) and (Copy(ary[5], 1, 1) <> ';') then
371
          raise Exception.CreateFmt('Zeile %d ist ungültig (Zusatzinfo am Ende)', [curline+1]);
402
          raise Exception.CreateFmt('Zeile %d ist ungültig (Zusatzinfo am Ende)', [curline+1]);
372
        AddEnemy(tmpX, tmpY, tmpEnemy, tmpLifes);
403
        AddEnemy(tmpX, tmpY, tmpEnemy, tmpLifes);
373
      end;
404
      end;
374
    end;
405
    end;
375
    {$ENDREGION}
406
    {$ENDREGION}
Line 389... Line 420...
389
  temp: string;
420
  temp: string;
390
  m: array[1..6] of tstrings;
421
  m: array[1..6] of tstrings;
391
begin
422
begin
392
  sl := TStringList.Create;
423
  sl := TStringList.Create;
393
  try
424
  try
394
    if EndsText('A1.lev', filename) then
425
    if EndsText('A1.lev', filename) then // do not localize
395
    begin
426
    begin
396
      {$REGION 'Backwards compatibility level format 0.2 (split into 5-6 files; convert to 0.3)'}
427
      {$REGION 'Backwards compatibility level format 0.2 (split into 5-6 files; convert to 0.3)'}
397
      m[1] := TStringList.create;
428
      m[1] := TStringList.create;
398
      m[2] := TStringList.create;
429
      m[2] := TStringList.create;
399
      m[3] := TStringList.create;
430
      m[3] := TStringList.create;
Line 408... Line 439...
408
            m[i].loadfromfile(filename);
439
            m[i].loadfromfile(filename);
409
        end;
440
        end;
410
        m[1].strings[0] := '-624';
441
        m[1].strings[0] := '-624';
411
        if m[6].Text = '' then m[6].Text := '30000';
442
        if m[6].Text = '' then m[6].Text := '30000';
412
 
443
 
413
        sl.Add('; SpaceMission 0.3');
444
        sl.Add('; SpaceMission 0.3'); // do not localize
414
        sl.Add(temp);
445
        sl.Add(temp);
415
        for j := 0 to m[1].count-2 do
446
        for j := 0 to m[1].count-2 do
416
        begin
447
        begin
417
          for i := 0 to m[1].count-2 do
448
          for i := 0 to m[1].count-2 do
418
          begin
449
          begin
Line 460... Line 491...
460
procedure TLevelData.SaveToStrings(sl: TStrings);
491
procedure TLevelData.SaveToStrings(sl: TStrings);
461
var
492
var
462
  i: integer;
493
  i: integer;
463
begin
494
begin
464
  sl.Clear;
495
  sl.Clear;
465
  sl.Add('[SpaceMission Level, Format 1.2]');
496
  sl.Add('['+OID_LEVSAV_VER12+']');
466
  if LevelName   <> '' then sl.Add('Name   ' + LevelName);
497
  if LevelName   <> '' then sl.Add('Name   ' + LevelName); // do not localize
467
  if LevelAuthor <> '' then sl.Add('Author ' + LevelAuthor);
498
  if LevelAuthor <> '' then sl.Add('Author ' + LevelAuthor); // do not localize
468
  sl.Add('Width  ' + IntToStr(LevelEditorLength));
499
  sl.Add('Width  ' + IntToStr(LevelEditorLength)); // do not localize
469
  SortEnemies;
500
  SortEnemies;
470
  sl.Add(';      Type   XCoord YCoord Lives');
501
  sl.Add(';      Type   XCoord YCoord Lives');
471
  for i := 0 to Length(EnemyAdventTable)-1 do
502
  for i := 0 to Length(EnemyAdventTable)-1 do
472
  begin
503
  begin
473
    sl.Add(
504
    sl.Add(Trim(
474
      'Enemy'.PadRight(6, ' ')+
505
      'Enemy'.PadRight(6, ' ')+ // do not localize
475
      ' '+
506
      ' '+
476
      IntToStr(Ord(EnemyAdventTable[i].enemyType)).PadRight(6, ' ')+
507
      IntToStr(Ord(EnemyAdventTable[i].enemyType)).PadRight(6, ' ')+
477
      ' '+
508
      ' '+
478
      IntToStr(EnemyAdventTable[i].x).PadRight(6, ' ')+
509
      IntToStr(EnemyAdventTable[i].x).PadRight(6, ' ')+
479
      ' '+
510
      ' '+
480
      IntToStr(EnemyAdventTable[i].y).PadRight(6, ' ')+
511
      IntToStr(EnemyAdventTable[i].y).PadRight(6, ' ')+
481
      ' '+
512
      ' '+
482
      IntToStr(EnemyAdventTable[i].lifes).PadRight(6, ' ')+
513
      IntToStr(EnemyAdventTable[i].lifes).PadRight(6, ' ')+
483
      ' '
514
      ' '
484
    );
515
    ));
485
  end;
516
  end;
486
end;
517
end;
487
 
518
 
488
procedure TLevelData.SaveToFile(filename: string);
519
procedure TLevelData.SaveToFile(filename: string);
489
var
520
var
Line 565... Line 596...
565
var
596
var
566
  sl2: TStringList;
597
  sl2: TStringList;
567
begin
598
begin
568
  sl2 := TStringList.Create;
599
  sl2 := TStringList.Create;
569
  try
600
  try
570
    sl.Add('[SpaceMission Savegame, Format 1.2]');
601
    sl.Add('['+OID_LEVSAV_VER12+']');
571
    sl.Add('Score  ' + IntToStr(Score));
602
    sl.Add('Score  ' + IntToStr(Score)); // do not localize
572
    sl.Add('Lives  ' + IntToStr(Life));
603
    sl.Add('Lives  ' + IntToStr(Life)); // do not localize
573
    sl.Add('Level  ' + IntToStr(Level));
604
    sl.Add('Level  ' + IntToStr(Level)); // do not localize
574
    sl.Add('Mode   ' + IntToStr(Ord(GameMode)));
605
    sl.Add('Mode   ' + IntToStr(Ord(GameMode))); // do not localize
575
    LevelData.SaveToStrings(sl2);
606
    LevelData.SaveToStrings(sl2);
576
    sl2.Delete(0); // Signature
607
    sl2.Delete(0); // Delete additional level signature
577
    sl.AddStrings(sl2);
608
    sl.AddStrings(sl2);
578
  finally
609
  finally
579
    FreeAndNil(sl2);
610
    FreeAndNil(sl2);
580
  end;
611
  end;
581
end;
612
end;
582
 
613
 
583
procedure TSaveData.LoadFromStrings(sl: TStrings);
614
procedure TSaveData.LoadFromStrings(sl: TStrings);
584
var
615
var
585
  curline: Integer;
616
  curline: Integer;
-
 
617
  ary: TStringDynArray;
-
 
618
  sLine: string;
586
begin
619
begin
587
  if (sl.Strings[0] = '; SpaceMission 1.0') and
620
  if (sl.Strings[0] = '; SpaceMission 1.0') and // do not localize
588
     (sl.Strings[1] = '; SAV-File') then
621
     (sl.Strings[1] = '; SAV-File') then // do not localize
589
  begin
622
  begin
590
    Score    := StrToInt(sl.Strings[2]);
623
    Score    := StrToInt(sl.Strings[2]);
591
    Life     := StrToInt(sl.Strings[3]);
624
    Life     := StrToInt(sl.Strings[3]);
592
    Level    := StrToInt(sl.Strings[4]);
625
    Level    := StrToInt(sl.Strings[4]);
593
    GameMode := TGameMode(StrToInt(sl.Strings[5]));
626
    GameMode := TGameMode(StrToInt(sl.Strings[5]));
594
    if Assigned(LevelData) then FreeAndNil(LevelData);
627
    if Assigned(LevelData) then FreeAndNil(LevelData);
595
  end
628
  end
596
  else if SameText(sl.Strings[0], '[SpaceMission Savegame, Format 1.2]') then
629
  else if SameText(sl.Strings[0], '['+OID_LEVSAV_VER12+']') then
597
  begin
630
  begin
598
    Score    := 0;
631
    Score    := 0;
599
    Life     := 0;
632
    Life     := 0;
600
    Level    := 0;
633
    Level    := 0;
601
    GameMode := gmUnknown;
634
    GameMode := gmUnknown;
602
    for curline := 1 to sl.Count-1 do
635
    for curline := 1 to sl.Count-1 do
603
    begin
636
    begin
604
      // 1234567890123456789012345678901234567890
-
 
605
      // 123456 123456 123456 123456 123456 ; Kommentar
-
 
606
      if (sl.Strings[curline].Trim = '') or
637
      sLine := sl.Strings[curline].Trim;
607
         (Copy(sl.Strings[curline], 1, 1) = ';') then
638
      if (sLine = '') or (Copy(sLine, 1, 1) = ';') then continue;
608
        // Do nothing
639
      ary := SplitString(CollapseSpaces(sLine), ' ');
609
      else if Copy(sl.Strings[curline], 1, 6).TrimRight = 'Score' then
640
      if ary[0] = 'Score' then // do not localize
610
      begin
641
      begin
611
        Score := StrToInt(TrimRight(Copy(sl.Strings[curline], 8, 6)))
642
        Score := StrToInt(ary[1]);
-
 
643
        if (Length(ary) > 2) and (Copy(ary[2], 1, 1) <> ';') then
-
 
644
          raise Exception.CreateFmt('Zeile %d ist ungültig (Zusatzinfo am Ende)', [curline+1]);
612
      end
645
      end
613
      else if Copy(sl.Strings[curline], 1, 6).TrimRight = 'Lives' then
646
      else if ary[0] = 'Lives' then // do not localize
614
      begin
647
      begin
615
        Life := StrToInt(TrimRight(Copy(sl.Strings[curline], 8, 6)))
648
        Life := StrToInt(ary[1]);
-
 
649
        if (Length(ary) > 2) and (Copy(ary[2], 1, 1) <> ';') then
-
 
650
          raise Exception.CreateFmt('Zeile %d ist ungültig (Zusatzinfo am Ende)', [curline+1]);
616
      end
651
      end
617
      else if Copy(sl.Strings[curline], 1, 6).TrimRight = 'Level' then
652
      else if ary[0] = 'Level' then // do not localize
618
      begin
653
      begin
619
        Level := StrToInt(TrimRight(Copy(sl.Strings[curline], 8, 6)))
654
        Level := StrToInt(ary[1]);
-
 
655
        if (Length(ary) > 2) and (Copy(ary[2], 1, 1) <> ';') then
-
 
656
          raise Exception.CreateFmt('Zeile %d ist ungültig (Zusatzinfo am Ende)', [curline+1]);
620
      end
657
      end
621
      else if Copy(sl.Strings[curline], 1, 6).TrimRight = 'Mode' then
658
      else if ary[0] = 'Mode' then // do not localize
622
      begin
659
      begin
623
        GameMode := TGameMode(StrToInt(TrimRight(Copy(sl.Strings[curline], 8, 6))))
660
        GameMode := TGameMode(StrToInt(ary[1]));
-
 
661
        if (Length(ary) > 2) and (Copy(ary[2], 1, 1) <> ';') then
-
 
662
          raise Exception.CreateFmt('Zeile %d ist ungültig (Zusatzinfo am Ende)', [curline+1]);
624
      end;
663
      end;
625
    end;
664
    end;
626
    if Assigned(LevelData) then FreeAndNil(LevelData);
665
    if Assigned(LevelData) then FreeAndNil(LevelData);
627
    LevelData := TLevelData.Create;
666
    LevelData := TLevelData.Create;
628
    LevelData.RasterErzwingen := false;
667
    LevelData.RasterErzwingen := false;