unit yatc_gameoptions;
{YATC - Unit gameoptions
Autor : Tobias Mark aka Colenzo (tobiasmark@gmx.de)

Formular zum einstellen der Spieloptionen -
Feldgröße, Schwierigkeitsgrad, Script

speichert diese eigenschaften zum teil

Version
0.1 - 4.12.05 : - Erste version
0.2 - 19.3.06 : - Einstellungen werden Gespeichert in options.xml
                - unterordner für scripts und einstellungen angelegt
}
interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, Mask, JvExMask, JvSpin,yatc_global, JvSimpleXml;

type
  ToptionForm = class(TForm)
    feldx_edit: TJvSpinEdit;
    feldy_edit: TJvSpinEdit;
    Label1: TLabel;
    Label2: TLabel;
    Label3: TLabel;
    okButton: TButton;
    cancelButton: TButton;
    script_select: TComboBox;
    Label4: TLabel;
    modus_select: TComboBox;
    Label5: TLabel;
    previewSelect: TCheckBox;
    Label6: TLabel;
    syncFulldownSelect: TCheckBox;
    Reset_Button: TButton;
    procedure okButtonClick(Sender: TObject);
    procedure cancelButtonClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure Reset_ButtonClick(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
    script : integer;     //script nummer       0 = kein Skript oder fehler
    mode : Rgamemode;     //schwierigkeitsgrade
    cubecount : integer;   //würfel anzahl
    blockpreview : boolean;  //Vorschau Funktion?
    syncfulldown : boolean; //Mehrspieler gleichzeitig fulldown taste?
    procedure makeVisible;  //Zeigt den Dialog an
    procedure LoadScript;   //Skript Laden (intern)
    procedure updateStatus;  //Schreibt Status Labels im Hauptformular
  end;

var
  optionForm: ToptionForm;

implementation

uses yatc_main,yatc_Debug,JclFileUtils;

{$R *.dfm}

//Eigenschaften eintragen und anzeigen, für den fall das sie vom letzten mal nicht gespeichert worden
procedure ToptionForm.makeVisible;

begin
  feldx_edit.value := form1.player1.field.sizeX+1;
  feldy_edit.value := form1.player1.field.sizeY+1;
  modus_select.itemindex := Integer(mode);
  script_select.ItemIndex := script;
  previewSelect.checked := blockpreview;
  syncfulldownSelect.Checked := syncFulldown;
  self.Visible := true;
  form1.Enabled := false;
end;


//geändert einstellungen vornhehmen
procedure ToptionForm.okButtonClick(Sender: TObject);

var msg : boolean;

begin  //Setzt eigenschaften
  if RGameMode(modus_select.ItemIndex) <> mode then
  begin
    mode := RGameMode(modus_select.itemindex);
    case mode of
    desay : form1.menuEsay.Checked := true;
    dmedium : form1.menuMedium.Checked := true;
    dhard :  form1.menuHard.Checked := true;
    end;
  end;

  if ((feldx_edit.Value-1) <> form1.player1.field.sizeX) or ((feldy_edit.Value-1) <> form1.player1.field.sizeY) then
  begin
    msg := false;
    case mode of    //Minimale Feldgröße für Modus einhalten
    desay : begin //minium für felder ist 5
              form1.player1.preview.setSize(3,3);
              form1.player2.preview.setSize(3,3);
            end;
    dmedium : begin    //feld größe prüfen & Nachkorigieren wenn korrigiert dann Melden
                form1.player1.preview.setSize(4,4);
                form1.player2.preview.setSize(4,4);
                if feldx_edit.value < 8 then begin msg := true; feldx_edit.value := 8; end;
                if feldy_edit.value < 8 then begin msg := true; feldy_edit.value := 8; end;
                if msg = true then showmessage('Minimale Feldgröße für Schwierigkeitsgrad Mittel ist 8x8');
              end;
    dhard : begin
              form1.player1.preview.setSize(5,5);
              form1.player2.preview.setSize(5,5);
              if feldx_edit.value < 12 then begin msg := true; feldx_edit.value := 12; end;
              if feldy_edit.value < 12 then begin msg := true; feldy_edit.value := 12; end;
              if msg = true then showmessage('Minimale Feldgröße für Schwierigkeitsgrad Schwer ist 12x12');
            end;
    end;
    form1.new_buttonclick(sender);
    form1.player1.field.setSize(round(feldx_edit.value-1),round(feldy_edit.value-1));

    form1.player1.field.camera.Position.z := (form1.player1.field.sizeX*form1.player1.field.sizeY)/((form1.player1.field.sizeX+form1.player1.field.sizeY)*0.4); //Kamera nach schätzwert ausrichten
    form1.kamera_edit.Value := form1.player1.field.camera.Position.z;

    form1.player2.field.setSize(round(feldx_edit.value-1),round(feldy_edit.value-1));
    form1.player2.field.camera.Position.z := (form1.player2.field.sizeX*form1.player2.field.sizeY)/((form1.player2.field.sizeX+form1.player2.field.sizeY)*0.4); //Kamera nach schätzwert ausrichten
    form1.second_kamera_edit.Value := form1.player2.field.camera.Position.z;
  end;

  if blockpreview <> previewSelect.Checked then
  begin
    blockpreview := previewSelect.Checked;
    if blockpreview = false then  //wurde auf false geändert event. alte vorschau Löschen
    begin
      form1.player1.preview.clear;
      form1.player1.nextcubenumber := -1;
      form1.player2.preview.clear;
      form1.player2.nextcubenumber := -1;
    end;
  end;

  if script <> script_select.ItemIndex then
  begin
    LoadScript;
  end;

  syncfulldown := syncfulldownselect.Checked;
  updateStatus;
  visible := false;
  form1.new_buttonclick(sender);
  form1.Enabled := true;
end;

//abbrechen
procedure ToptionForm.cancelButtonClick(Sender: TObject);

begin
  visible := false;
  form1.Enabled := true;
  form1.SetFocus;
end;

procedure ToptionForm.FormCreate(Sender: TObject);

var  xml_file : TJvSimpleXml;   //XML System
     node1 : TJvSimpleXMLElem;  //help zum durchhangel durch Struktur

begin
  //Standardoptionen
  script := 0;
  blockpreview := true;
  syncfulldown := false;
  cubecount := cubecount_const;
  mode := desay;
  //Standard einstellungen vornehmen
  Reset_ButtonClick(sender);

  //Script Liste holen
  buildfilelist(ExtractFilePath(Application.ExeName)+'\scripts\*.yatc',faAnyfile,script_select.Items);

  node1 := nil;
  xml_file  := Tjvsimplexml.create(self); //Xml dokument erstellen
  xml_file.options := [sxoAutoCreate]; //autocreate für notfälle um fehler zu vermeiden bei zugriff auf nicht existierendes
  try
    xml_file.LoadFromFile(options_file);    //laden aus datei
    if xml_file.root.name = 'options' then //richtige datei?
    begin
      //Gameplay
      node1 := xml_file.root.items.itemnamed['gameplay'];
      //keine if abfrage obs funktioniert hat -> geht dann in execept
      feldx_edit.Value := strtoint(node1.Items.ItemNamed['fieldx'].value);
      feldy_edit.Value := strtoint(node1.Items.ItemNamed['fieldy'].Value);
      previewselect.Checked := strtobool(node1.Items.ItemNamed['preview'].Value);
      modus_select.ItemIndex := strtoint(node1.Items.ItemNamed['mode'].Value);
      //Script - wird nicht verwendet da sich die liste ändern kann
      //node1 := xml_file.Root.Items.ItemNamed['scripts'];
      //Multiplayer
      node1 := xml_file.Root.Items.ItemNamed['multiplayer'];
      syncFulldownSelect.Checked := strtobool(node1.Items.ItemNamed['syncfulldown'].Value);
      //Grafik
      node1 := xml_file.Root.Items.itemnamed['graphics'];
    end;
  except
    Showmessage('Fehler beim Laden der Options Datei!');
  end;

  //eingelessen einstellungen anwenden
  okButtonClick(sender);
  //Kamera einstellung erst nach der standard berechnung laden ;)
  try
    if node1 <> nil then
    begin
      form1.kamera_edit.value := strtoint(node1.Items.ItemNamed['camera1'].Value);
      form1.player1.field.camera.position.z := strtoint(node1.Items.ItemNamed['camera1'].Value);
      form1.second_kamera_edit.value := strtoint(node1.Items.ItemNamed['camera2'].Value);
      form1.player2.field.camera.position.z := strtoint(node1.Items.ItemNamed['camera2'].Value);
    end;
  except
    //nix
  end;
  xml_file.Free;  //xml zeugs freigeben

  //wegen lade rheinfolge probleme hier hilfsmethode
  form1.FormCreateafter(sender);
end;

procedure ToptionForm.LoadScript;     //Kompiliert das Szenario Skript und führt den Haupteil aus (init-teil)

procedure OutputMessages;       //übernommen aus beispiel, gibt die fehlermeldungen in das debug feld aus
  var
    l: Longint;
  begin
    for l := 0 to form1.scriptengine.CompilerMessageCount - 1 do
    begin
      debugForm.script_debug.Lines.Add('Compiler: '+ form1.scriptengine.CompilerErrorToStr(l));
    end;
  end;

begin
  if script_select.ItemIndex <> 0 then
  begin              //wenn nicht 'Normal' dann script Laden
    form1.scriptengine.Script.LoadFromFile(script_select.Items[script_select.itemindex]);
  end
  else
  begin     //kein script laden, eventuelle von vorher zurückstellen
    form1.scriptengine.Script.Clear;
    form1.scriptengine.Script.Add('program Normal; begin end.');
    cubecount := cubecount_const;
    feldx_edit.enabled := true;
    feldy_edit.enabled := true;
    modus_select.Enabled := true;
  end;
  debugForm.script_debug.Lines.Clear;    //debug meldung
  debugForm.script_debug.Lines.Add('Compiling '+ script_select.Items[script_select.itemindex]);
  if form1.scriptengine.Compile then
  begin               //Kompilieren
    OutputMessages;
    debugForm.script_debug.Lines.Add('Compiled succesfully');
    if not form1.scriptengine.Execute then //Initialisierungs Methode ablaufen lassen
    begin
      debugForm.script_debug.Lines.Add(form1.scriptengine.ExecErrorToString +' at '+Inttostr(form1.scriptengine.ExecErrorProcNo)+'.'+Inttostr(form1.scriptengine.ExecErrorByteCodePosition));
      showmessage('Fehler beim ausführen von '+ script_select.Items[script_select.itemindex]);
      script := 0;
    end
    else begin
      debugForm.script_debug.Lines.Add('Succesfully executed');
      script := script_select.itemindex;
    end;
  end else
  begin
    OutputMessages;
    debugForm.script_debug.Lines.Add('Compiling failed');
    showmessage('Fehler beim Laden von '+ script_select.Items[script_select.itemindex]);
    script := 0;
  end;
end;

procedure ToptionForm.UpdateStatus;

begin
  //Anzeigen aktuallisieren
  form1.script_label.caption := script_select.Items[script];
  case mode of
    desay : form1.mode_label.Caption := 'Leicht';
    dmedium : form1.mode_label.Caption := 'Mittel';
    dhard : form1.mode_label.Caption := 'Schwer';
  end;
  form1.size_label.caption := inttostr(form1.player1.field.sizeX+1) + 'x' + inttostr(form1.player1.field.sizeY+1);
  case form1.playerMode of
    ksingle : form1.multi_label.Caption := ''; //nix
    ktwo : form1.multi_label.Caption := '2 Spieler';
    kmulti : form1.multi_label.Caption := 'Mehrspieler';
  end;
end;


procedure ToptionForm.FormDestroy(Sender: TObject);

var node : TJvSimpleXMLElem; //help
    xml_file : TJvSimpleXml;

begin
  //speichern der Options
  xml_file  := Tjvsimplexml.create(self);  //erstellen XML daten
  xml_file.options := [];
  xml_file.Root.Name := 'options';
  xml_file.Root.Items.Add('Description','YATC '+version+' Options File');
  node := xml_file.Root.Items.Add('gameplay');
  node.Items.Add('fieldx',inttostr(form1.player1.field.sizeX+1));
  node.Items.Add('fieldy',inttostr(form1.player1.field.sizeY+1));
  node.Items.Add('preview',booltostr(blockpreview));
  node.Items.Add('mode',Integer(mode));
  node := xml_file.Root.Items.Add('graphics');
  node.Items.Add('camera1',floattostr(form1.kamera_edit.value));
  node.Items.Add('camera2',floattostr(form1.second_kamera_edit.value));
  node := xml_file.Root.Items.Add('script');
  node := xml_file.Root.Items.Add('multiplayer');
  node.Items.Add('syncfulldown',booltostr(syncfulldown));
  xml_file.SaveToFile(options_file);    //Speichern in datei
  xml_file.free;      // xml objekt freigeben
end;

procedure ToptionForm.Reset_ButtonClick(Sender: TObject);

begin
  //Standard Werte
  feldx_edit.Value := 12;
  feldy_edit.Value := 15;
  previewSelect.Checked := true;
  syncFulldownSelect.Checked := false;
  script_select.ItemIndex := 0;
  modus_select.ItemIndex := 0;
end;

end.
