unit uMulpatcher;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes,    Graphics, Controls, Forms,
  Dialogs, rmNotebook2, StdCtrls, ExtCtrls, uConfig, uAnimations,
  GR32_Image, GR32, StrLib, Menus, rmBrowseFor, uVerdata, uUtilities, uGump,
  uArt, uTextures, uRadarcol, uHues, uHueForm, ComCtrls, GR32_Layers, Math,
  uLight, uTiledata, uGaugeForm, uAnim2, uAnim3, uAnimdata, uAboutForm,
  uStaticChooseForm, uMulti, uSound, MMSystem, uStatic, uSEditorForm,
  uDiffForm, uMap, rmGauge, uMulCrypt, uAnim4, uAnim5;

type    TClilocEntry = Class
                public
                        Id : LongWord;
                        Name : String;
                        constructor Create( Id : LongWord; Name : String );
                        destructor Free;
        end;

type
  TMainForm = class(TForm)
    tabControl: TrmTabbedNoteBookControl;
    tabSettings: TrmNotebookPage;
    gbAnimations: TGroupBox;
    ePathAnimIdx: TLabeledEdit;
    ePathAnimMul: TLabeledEdit;
    btnAnimLoad: TButton;
    btnBrowseAnimIdx: TButton;
    btnBrowseAnimMul: TButton;
    tabAnimations: TrmNotebookPage;
    lbAnimations: TListBox;
    iAnimations: TImage32;
    cbAnimations: TComboBox;
    popAnimations: TPopupMenu;
    SavetoDirectory1: TMenuItem;
    SavetoFile1: TMenuItem;
    SavetoFile2: TMenuItem;
    LoadfromFile1: TMenuItem;
    cbPalette: TCheckBox;
    gbVerdata: TGroupBox;
    ePathVerdata: TLabeledEdit;
    btnBrowseVerdata: TButton;
    btnVerdataLoad: TButton;
    Version: TLabel;
    tabGumpAnim: TrmNotebookPage;
    lbGumpAnim: TListBox;
    cbGumpAnim: TComboBox;
    iGumpAnim: TImage32;
    gbGumps: TGroupBox;
    ePathGumpIdx: TLabeledEdit;
    ePathGumpMul: TLabeledEdit;
    btnGumpLoad: TButton;
    btnGumpSave: TButton;
    btnBrowseGumpIdx: TButton;
    btnBrowseGumpMul: TButton;
    popGumpAnim: TPopupMenu;
    Saveto1: TMenuItem;
    Loadfrom1: TMenuItem;
    Delete1: TMenuItem;
    tabGumpNonAnim: TrmNotebookPage;
    lbGumpNonAnim: TListBox;
    iGumpNonAnim: TImage32;
    cbGumpNonAnim: TComboBox;
    popGumpNonAnim: TPopupMenu;
    MenuItem1: TMenuItem;
    MenuItem2: TMenuItem;
    MenuItem3: TMenuItem;
    tabArtMap: TrmNotebookPage;
    tabArtStatics: TrmNotebookPage;
    gbArt: TGroupBox;
    ePathArtIdx: TLabeledEdit;
    ePathArtMul: TLabeledEdit;
    btnArtLoad: TButton;
    btnArtSave: TButton;
    btnBrowseArtIdx: TButton;
    btnBrowseArtMul: TButton;
    lbArtMap: TListBox;
    iArtMap: TImage32;
    cbArtMap: TComboBox;
    popArtMap: TPopupMenu;
    iArtStatic: TImage32;
    cbArtStatic: TComboBox;
    lbArtStatic: TListBox;
    popArtStatic: TPopupMenu;
    SavetoBitmap1: TMenuItem;
    LoadfromBitmap1: TMenuItem;
    Delete2: TMenuItem;
    SavetoBitmap2: TMenuItem;
    LoadfromBitmap2: TMenuItem;
    Delete3: TMenuItem;
    gbTextures: TGroupBox;
    ePathTexIdx: TLabeledEdit;
    ePathTexMul: TLabeledEdit;
    btnTexLoad: TButton;
    btnTexSave: TButton;
    btnBrowseTexIdx: TButton;
    btnBrowseTexMul: TButton;
    tabTextures: TrmNotebookPage;
    lbTex: TListBox;
    iTex: TImage32;
    cbTex: TComboBox;
    popTex: TPopupMenu;
    SavetoBitmap3: TMenuItem;
    LoadfromBitmap3: TMenuItem;
    Delete4: TMenuItem;
    LoadfromBitmaptoVerdata1: TMenuItem;
    btnVerdataSave: TButton;
    LoadfromBitmaptoVerdata2: TMenuItem;
    LoadfromBitmaptoVerdata3: TMenuItem;
    LoadfromBitmaptoVerdata4: TMenuItem;
    LoadfromBitmaptoVerdata5: TMenuItem;
    gbRadarcol: TGroupBox;
    ePathRadarCol: TLabeledEdit;
    btnBrowseRadarCol: TButton;
    btnLoadRadarCol: TButton;
    btnSaveRadarCol: TButton;
    iArtMapRadar: TImage32;
    eArtMapRadarBlue: TLabeledEdit;
    eArtMapRadarGreen: TLabeledEdit;
    eArtMapRadarRed: TLabeledEdit;
    eArtMapRadarFrom: TLabeledEdit;
    eArtMapRadarTo: TLabeledEdit;
    btnArtMapRadarAverage: TButton;
    eArtStaticRadarBlue: TLabeledEdit;
    iArtStaticRadar: TImage32;
    eArtStaticRadarGreen: TLabeledEdit;
    eArtStaticRadarRed: TLabeledEdit;
    eArtStaticRadarFrom: TLabeledEdit;
    eArtStaticRadarTo: TLabeledEdit;
    btnArtStaticRadarAverage: TButton;
    tabHues: TrmNotebookPage;
    iHue: TImage32;
    eHueName: TLabeledEdit;
    iHueImage: TImage32;
    lbHue: TListBox;
    tbHue: TTrackBar;
    btnHueForm: TButton;
    popHue: TPopupMenu;
    est1: TMenuItem;
    ShowGump1: TMenuItem;
    ShowAnimation1: TMenuItem;
    btnHueSpread: TButton;
    lbHue2: TListBox;
    iHue2: TImage32;
    tbHue2: TTrackBar;
    eHue2Name: TLabeledEdit;
    btnHueLoad: TButton;
    btnHueCopy: TButton;
    LoadfromDirectorytoVerdata1: TMenuItem;
    LoadfromFiletoVerdata1: TMenuItem;
    Copy1: TMenuItem;
    gbLight: TGroupBox;
    ePathLightIdx: TLabeledEdit;
    ePathLightMul: TLabeledEdit;
    btnLightLoad: TButton;
    btnLightSave: TButton;
    btnBrowseLightIdx: TButton;
    btnBrowseLightMul: TButton;
    tabLight: TrmNotebookPage;
    lbLight: TListBox;
    iLight: TImage32;
    popLight: TPopupMenu;
    SavetoBitmap4: TMenuItem;
    LoadfromBitmap4: TMenuItem;
    gbTiledata: TGroupBox;
    ePathTiledata: TLabeledEdit;
    btnBrowseTiledata: TButton;
    btnTiledataLoad: TButton;
    btnTiledataSave: TButton;
    tabTiledataMap: TrmNotebookPage;
    tabTiledataStatics: TrmNotebookPage;
    lbTiledataMap: TListBox;
    eTMName: TLabeledEdit;
    eTMTexId: TLabeledEdit;
    cbTMImpassable: TCheckBox;
    cbTMDamaging: TCheckBox;
    cbTMWall: TCheckBox;
    cbTMLiquid: TCheckBox;
    cbTMUnknown3: TCheckBox;
    btnTMSave: TButton;
    btnTMLoad: TButton;
    lbTiledataStatic: TListBox;
    eTSName: TLabeledEdit;
    eTSWeight: TLabeledEdit;
    eTSHeight: TLabeledEdit;
    eTSQuality: TLabeledEdit;
    eTSQuantity: TLabeledEdit;
    eTSHue: TLabeledEdit;
    eTSAnimId: TLabeledEdit;
    eTSUnknown1: TLabeledEdit;
    eTSUnknown2: TLabeledEdit;
    eTSUnknown3: TLabeledEdit;
    eTSUnknown4: TLabeledEdit;
    eTSUnknown5: TLabeledEdit;
    cbTSBackground: TCheckBox;
    cbTSWeapon: TCheckBox;
    cbTSTransparent: TCheckBox;
    cbTSTranslucent: TCheckBox;
    cbTSWall: TCheckBox;
    cbTSDamaging: TCheckBox;
    cbTSImpassable: TCheckBox;
    cbTSLiquid: TCheckBox;
    cbTSAn: TCheckBox;
    cbTSA: TCheckBox;
    cbTSNoshoot: TCheckBox;
    cbTSWindow: TCheckBox;
    cbTSGeneric: TCheckBox;
    cbTSBridge: TCheckBox;
    cbTSSurface: TCheckBox;
    cbTSUnknown1: TCheckBox;
    cbTSLightsource: TCheckBox;
    cbTSWearable: TCheckBox;
    cBTSContainer: TCheckBox;
    cbTSMap: TCheckBox;
    cbTSUnknown2: TCheckBox;
    cbTSPartialhue: TCheckBox;
    cbTSFoliage: TCheckBox;
    cbTSMongen: TCheckBox;
    cbTSStairright: TCheckBox;
    cbTSStairback: TCheckBox;
    cbTSDoor: TCheckBox;
    cbTSRoof: TCheckBox;
    cbTSArmor: TCheckBox;
    cbTSUnknown3: TCheckBox;
    cbTSNodiagonal: TCheckBox;
    cbTSAnimation: TCheckBox;
    btnTSSave: TButton;
    btnTSLoad: TButton;
    btnArtStaticExtractHoles: TButton;
    tabAnimdata: TrmNotebookPage;
    tabFeatures: TrmNotebookPage;
    gbAutopatch: TGroupBox;
    ePathAutopatch: TLabeledEdit;
    cbAutopatch: TComboBox;
    btnAutopatchStart: TButton;
    gbExtract: TGroupBox;
    cbExtract: TComboBox;
    btnExtractStart: TButton;
    btnBrowseAutopatch: TButton;
    Delete5: TMenuItem;
    lAnimExists: TLabel;
    cbShowImage: TCheckBox;
    tabAnim2: TrmNotebookPage;
    tabAnim3: TrmNotebookPage;
    gbAnim2: TGroupBox;
    ePathAnim2Idx: TLabeledEdit;
    ePathAnim2Mul: TLabeledEdit;
    btnAnim2Load: TButton;
    btnBrowseAnim2Idx: TButton;
    btnBrowseAnim2Mul: TButton;
    lbAnim2: TListBox;
    iAnim2: TImage32;
    cbAnim2: TComboBox;
    gbAnim3: TGroupBox;
    ePathAnim3Idx: TLabeledEdit;
    ePathAnim3Mul: TLabeledEdit;
    btnAnim3Load: TButton;
    btnBrowseAnim3Idx: TButton;
    btnBrowseAnim3Mul: TButton;
    lbAnim3: TListBox;
    iAnim3: TImage32;
    cbAnim3: TComboBox;
    popAnim2: TPopupMenu;
    SaveAnimtoDirectory1: TMenuItem;
    SaveAnimtoFile1: TMenuItem;
    popAnim3: TPopupMenu;
    SaveAnimtoDirectory2: TMenuItem;
    SaveAnimtoFile2: TMenuItem;
    gbAnimdata: TGroupBox;
    ePathAnimdata: TLabeledEdit;
    btnBrowseAnimdata: TButton;
    btnAnimdataLoad: TButton;
    btnAnimdataSave: TButton;
    lbAnimdata: TListBox;
    gbHues: TGroupBox;
    ePathHues: TLabeledEdit;
    btnBrowseHues: TButton;
    btnHuesLoad: TButton;
    btnHuesSave: TButton;
    cbAnimdata: TComboBox;
    iAnimdata: TImage32;
    eAnimdataFrame: TLabeledEdit;
    eAnimdataFrameCount: TLabeledEdit;
    eAnimdataFrameRelativ: TLabeledEdit;
    eAnimdataFrameStart: TLabeledEdit;
    eAnimdataFrameInterval: TLabeledEdit;
    iAnimdataAnim: TImage32;
    btnAnimdataStart: TButton;
    btnAnimdataStop: TButton;
    cbAnimdataRepeat: TCheckBox;
    cbAnimdataFrameNumber: TComboBox;
    lAnimdata: TLabel;
    TimerAnimdata: TTimer;
    btnAbout: TButton;
    btnChooseStatic: TButton;
    cbWin98: TCheckBox;
    gbReIndex: TGroupBox;
    cbReIndex: TComboBox;
    btnReIndex: TButton;
    eAnimSearch: TLabeledEdit;
    btnAnimSearch: TButton;
    btnAnim2Search: TButton;
    eAnim2Search: TLabeledEdit;
    btnAnim3Search: TButton;
    eAnim3Search: TLabeledEdit;
    btnAnimdataSearch: TButton;
    eAnimdataSearch: TLabeledEdit;
    eArtMapSearch: TLabeledEdit;
    btnArtMapSearch: TButton;
    btnArtStaticSearch: TButton;
    eArtStaticSearch: TLabeledEdit;
    eGumpAnimSearch: TLabeledEdit;
    btnGumpAnimSearch: TButton;
    eGumpNonAnimSearch: TLabeledEdit;
    btnGumpNonAnimSearch: TButton;
    eTexSearch: TLabeledEdit;
    btnTexSearch: TButton;
    eTMSearch: TLabeledEdit;
    btnTMSearch: TButton;
    eTSSearch: TLabeledEdit;
    btnTSSearch: TButton;
    tabMulti: TrmNotebookPage;
    iTiledataMap: TImage32;
    iTiledataStatic: TImage32;
    tabSound: TrmNotebookPage;
    gbSound: TGroupBox;
    ePathSoundIdx: TLabeledEdit;
    ePathSoundMul: TLabeledEdit;
    btnSoundLoad: TButton;
    btnSoundSave: TButton;
    btnBrowseSoundIdx: TButton;
    btnBrowseSoundMul: TButton;
    lbSound: TListBox;
    cbSound: TComboBox;
    popSound: TPopupMenu;
    SavetoFile3: TMenuItem;
    LoadfromFile2: TMenuItem;
    Delete6: TMenuItem;
    PlaySound1: TMenuItem;
    eSoundSearch: TLabeledEdit;
    btnSoundSearch: TButton;
    lbMulti: TListBox;
    cbMulti: TComboBox;
    btnMultiSearch: TButton;
    eMultiSearch: TLabeledEdit;
    gbMultis: TGroupBox;
    ePathMultiIdx: TLabeledEdit;
    ePathMultiMul: TLabeledEdit;
    btnMultiLoad: TButton;
    btnMultiSave: TButton;
    btnBrowseMultiIdx: TButton;
    btnBrowseMultiMul: TButton;
    sbMulti: TScrollBox;
    iMulti: TImage32;
    popMulti: TPopupMenu;
    SavetoWsc1: TMenuItem;
    SavetoWsc2: TMenuItem;
    LoadfromSphere51a1: TMenuItem;
    LoadfromWsc1: TMenuItem;
    Delete7: TMenuItem;
    gbStatics: TGroupBox;
    ePathStaticIdx: TLabeledEdit;
    ePathStaticMul: TLabeledEdit;
    btnStaticLoad: TButton;
    btnStaticSave: TButton;
    btnBrowseStaticIdx: TButton;
    btnBrowseStaticMul: TButton;
    btnActivateEditor: TButton;
    lSound: TLabel;
    btnStatDiffTool: TButton;
    SaveToTextfile1: TMenuItem;
    LoadfromTextfile1: TMenuItem;
    ShowDetails1: TMenuItem;
    gbMap: TGroupBox;
    ePathMap: TLabeledEdit;
    btnBrowseMap: TButton;
    btnMapLoad: TButton;
    gbScripts: TGroupBox;
    btnCreateScripts: TButton;
    cbScripts: TComboBox;
    eFromID: TLabeledEdit;
    eToID: TLabeledEdit;
    eStandartDescription: TLabeledEdit;
    SetTag1: TMenuItem;
    cbLowMemory: TCheckBox;
    TimerLoad: TTimer;
    btnCountTex: TButton;
    gbMapIdChange: TGroupBox;
    eMapId: TLabeledEdit;
    btnChooseMapFile: TButton;
    btnStartMapIdChange: TButton;
    btnCreateStaticMap: TButton;
    GroupBox1: TGroupBox;
    Label2: TLabel;
    eX2: TLabeledEdit;
    eY1: TLabeledEdit;
    eY2: TLabeledEdit;
    eX1: TLabeledEdit;
    eTargX1: TLabeledEdit;
    eTargY1: TLabeledEdit;
    gMap: TrmGauge;
    btnMapCopy: TButton;
    GroupBox2: TGroupBox;
    btnStartStaticDelete: TButton;
    btnBrowseStaticIdxDelete: TButton;
    eStaticIdxDeletePath: TLabeledEdit;
    eStaticMulDeletePath: TLabeledEdit;
    btnBrowseStaticMulDelete: TButton;
    btnSearchID: TButton;
    eMapCopyFrom: TLabeledEdit;
    btnMCBrowseFrom: TButton;
    eMapCopyTo: TLabeledEdit;
    Button1: TButton;
    eMCSrcBreite: TLabeledEdit;
    eMCSrcHoehe: TLabeledEdit;
    eMCTrgBreite: TLabeledEdit;
    eMCTrgHoehe: TLabeledEdit;
    btnExtractFromFile: TButton;
    SaveTo2: TMenuItem;
    LoadfromUOATextfile1: TMenuItem;
    tabPatch: TrmNotebookPage;
    gP: TrmGauge;
    gbCreatePatch: TGroupBox;
    gbChangeHeights: TGroupBox;
    cbPMap: TCheckBox;
    cbPStatics: TCheckBox;
    cbPArt: TCheckBox;
    cbPTex: TCheckBox;
    gbGeneral: TGroupBox;
    cbChooseMap: TComboBox;
    ePWidth: TLabeledEdit;
    ePHeight: TLabeledEdit;
    ePY1: TLabeledEdit;
    ePX1: TLabeledEdit;
    ePX2: TLabeledEdit;
    ePY2: TLabeledEdit;
    lPMap: TLabel;
    ePDir: TLabeledEdit;
    btnPBrowse: TButton;
    btnPStart: TButton;
    eChangeHoehe: TLabeledEdit;
    btnStartHeight: TButton;
    cbCHMap: TCheckBox;
    cbCHStatics: TCheckBox;
    glApplyPatch: TGroupBox;
    cbPBackup: TCheckBox;
    btnStartApplyPatch: TButton;
    Button2: TButton;
    GroupBox3: TGroupBox;
    eMSIdx1: TLabeledEdit;
    eMSMul1: TLabeledEdit;
    eMSIdx2: TLabeledEdit;
    eMSMul2: TLabeledEdit;
    Button3: TButton;
    Button4: TButton;
    Button5: TButton;
    Button6: TButton;
    btnMSRun: TButton;
    GroupBox4: TGroupBox;
    eCutFileName: TLabeledEdit;
    Button7: TButton;
    Button8: TButton;
    eCutToSize: TLabeledEdit;
    Button9: TButton;
    LoadfromDirectory1: TMenuItem;
    Button10: TButton;
    GroupBox5: TGroupBox;
    btnCreateEmpty: TButton;
    cbCreateEmpty: TComboBox;
    tabSedin: TrmNotebookPage;
    Label1: TLabel;
    eSedinPathGump: TLabeledEdit;
    eSedinPathArt: TLabeledEdit;
    eSedinGumpId: TLabeledEdit;
    eSedinArtId: TLabeledEdit;
    eSedinAnimId: TLabeledEdit;
    cbSedinWearable: TCheckBox;
    Label3: TLabel;
    Label4: TLabel;
    cbSedinLayer: TComboBox;
    cbSedinWeapon: TCheckBox;
    cbSedinArmor: TCheckBox;
    cbSedinPartialHue: TCheckBox;
    cbSedinLightSource: TCheckBox;
    eSedinWeight: TLabeledEdit;
    cbSedinPath: TButton;
    cbSedinClear: TButton;
    btnSedinBrowseGump: TButton;
    btnSedinBrowseArt: TButton;
    eSedinName: TLabeledEdit;
    GroupBox6: TGroupBox;
    Button11: TButton;
    lWorldRadarMap: TLabel;
    Button12: TButton;
    cbME: TCheckBox;
    GroupBox7: TGroupBox;
    eCPAFromID: TLabeledEdit;
    eCPAToID: TLabeledEdit;
    btnCPAStart: TButton;
    Button13: TButton;
    Button14: TButton;
    eSedinPathGumpW: TLabeledEdit;
    btnSedinBrowseGumpW: TButton;
    btnMergeCliloc: TButton;
    Button15: TButton;
    Button16: TButton;
    Button17: TButton;
    GroupBox8: TGroupBox;
    ArtDeleteIdFirst: TLabeledEdit;
    ArtDeleteIdLast: TLabeledEdit;
    btnArtDeleteIds: TButton;
    Label5: TLabel;
    Button18: TButton;
    tabAnim4: TrmNotebookPage;
    tabAnim5: TrmNotebookPage;
    lbAnim4: TListBox;
    iAnim4: TImage32;
    cbAnim4: TComboBox;
    eAnim4Search: TLabeledEdit;
    btnAnim4Search: TButton;
    lbAnim5: TListBox;
    iAnim5: TImage32;
    cbAnim5: TComboBox;
    eAnim5Search: TLabeledEdit;
    btnAnim5Search: TButton;
    popAnim4: TPopupMenu;
    MenuItem4: TMenuItem;
    MenuItem5: TMenuItem;
    popAnim5: TPopupMenu;
    MenuItem6: TMenuItem;
    MenuItem7: TMenuItem;
    gbAnim4: TGroupBox;
    ePathAnim4Idx: TLabeledEdit;
    ePathAnim4Mul: TLabeledEdit;
    btnAnim4Load: TButton;
    btnBrowseAnim4Idx: TButton;
    btnBrowseAnim4Mul: TButton;
    gbAnim5: TGroupBox;
    ePathAnim5Idx: TLabeledEdit;
    ePathAnim5Mul: TLabeledEdit;
    btnAnim5Load: TButton;
    btnBrowseAnim5Idx: TButton;
    btnBrowseAnim5Mul: TButton;
    MarkPixels: TGroupBox;
    eColorMarkPixels: TLabeledEdit;
    Button19: TButton;
    Button20: TButton;
    eMapWidth: TLabeledEdit;
    eMapHeight: TLabeledEdit;
    iAnimGump: TImage32;
    procedure btnBrowseAnimIdxClick(Sender: TObject);
    procedure btnBrowseAnimMulClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure btnAnimLoadClick(Sender: TObject);
    procedure cbAnimationsChange(Sender: TObject);
    procedure lbAnimationsDrawItem(Control: TWinControl; Index: Integer;
      Rect: TRect; State: TOwnerDrawState);
    procedure lbAnimationsClick(Sender: TObject);
    procedure lbAnimationsContextPopup(Sender: TObject; MousePos: TPoint;
      var Handled: Boolean);
    procedure SavetoDirectory1Click(Sender: TObject);
    procedure SavetoFile1Click(Sender: TObject);
    procedure SavetoFile2Click(Sender: TObject);
    procedure LoadfromFile1Click(Sender: TObject);
    procedure btnBrowseVerdataClick(Sender: TObject);
    procedure btnVerdataLoadClick(Sender: TObject);
    procedure btnBrowseGumpIdxClick(Sender: TObject);
    procedure btnBrowseGumpMulClick(Sender: TObject);
    procedure btnGumpLoadClick(Sender: TObject);
    procedure cbGumpAnimChange(Sender: TObject);
    procedure lbGumpAnimDrawItem(Control: TWinControl; Index: Integer;
      Rect: TRect; State: TOwnerDrawState);
    procedure lbGumpAnimClick(Sender: TObject);
    procedure Saveto1Click(Sender: TObject);
    procedure lbGumpAnimContextPopup(Sender: TObject; MousePos: TPoint;
      var Handled: Boolean);
    procedure Loadfrom1Click(Sender: TObject);
    procedure Delete1Click(Sender: TObject);
    procedure cbGumpNonAnimChange(Sender: TObject);
    procedure lbGumpNonAnimClick(Sender: TObject);
    procedure lbGumpNonAnimDrawItem(Control: TWinControl; Index: Integer;
      Rect: TRect; State: TOwnerDrawState);
    procedure MenuItem1Click(Sender: TObject);
    procedure MenuItem2Click(Sender: TObject);
    procedure MenuItem3Click(Sender: TObject);
    procedure lbGumpNonAnimContextPopup(Sender: TObject; MousePos: TPoint;
      var Handled: Boolean);
    procedure btnArtLoadClick(Sender: TObject);
    procedure btnArtSaveClick(Sender: TObject);
    procedure btnBrowseArtIdxClick(Sender: TObject);
    procedure btnBrowseArtMulClick(Sender: TObject);
    procedure cbArtMapChange(Sender: TObject);
    procedure lbArtMapClick(Sender: TObject);
    procedure lbArtMapDrawItem(Control: TWinControl; Index: Integer;
      Rect: TRect; State: TOwnerDrawState);
    procedure lbArtMapContextPopup(Sender: TObject; MousePos: TPoint;
      var Handled: Boolean);
    procedure cbArtStaticChange(Sender: TObject);
    procedure lbArtStaticClick(Sender: TObject);
    procedure lbArtStaticDrawItem(Control: TWinControl; Index: Integer;
      Rect: TRect; State: TOwnerDrawState);
    procedure lbArtStaticContextPopup(Sender: TObject; MousePos: TPoint;
      var Handled: Boolean);
    procedure SavetoBitmap1Click(Sender: TObject);
    procedure LoadfromBitmap1Click(Sender: TObject);
    procedure Delete2Click(Sender: TObject);
    procedure SavetoBitmap2Click(Sender: TObject);
    procedure LoadfromBitmap2Click(Sender: TObject);
    procedure Delete3Click(Sender: TObject);
    procedure btnBrowseTexIdxClick(Sender: TObject);
    procedure btnBrowseTexMulClick(Sender: TObject);
    procedure btnTexLoadClick(Sender: TObject);
    procedure btnGumpSaveClick(Sender: TObject);
    procedure btnTexSaveClick(Sender: TObject);
    procedure lbTexClick(Sender: TObject);
    procedure lbTexDrawItem(Control: TWinControl; Index: Integer;
      Rect: TRect; State: TOwnerDrawState);
    procedure cbTexChange(Sender: TObject);
    procedure lbTexContextPopup(Sender: TObject; MousePos: TPoint;
      var Handled: Boolean);
    procedure SavetoBitmap3Click(Sender: TObject);
    procedure LoadfromBitmap3Click(Sender: TObject);
    procedure Delete4Click(Sender: TObject);
    procedure LoadfromBitmaptoVerdata1Click(Sender: TObject);
    procedure btnVerdataSaveClick(Sender: TObject);
    procedure LoadfromBitmaptoVerdata2Click(Sender: TObject);
    procedure LoadfromBitmaptoVerdata3Click(Sender: TObject);
    procedure LoadfromBitmaptoVerdata4Click(Sender: TObject);
    procedure LoadfromBitmaptoVerdata5Click(Sender: TObject);
    procedure btnBrowseRadarColClick(Sender: TObject);
    procedure btnLoadRadarColClick(Sender: TObject);
    procedure btnSaveRadarColClick(Sender: TObject);
    procedure eArtMapRadarBlueKeyDown(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    procedure eArtMapRadarGreenKeyDown(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    procedure eArtMapRadarRedKeyDown(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    procedure btnArtMapRadarAverageClick(Sender: TObject);
    procedure eArtStaticRadarBlueKeyDown(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    procedure eArtStaticRadarGreenKeyDown(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    procedure eArtStaticRadarRedKeyDown(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    procedure btnArtStaticRadarAverageClick(Sender: TObject);
    procedure btnBrowseHuesClick(Sender: TObject);
    procedure btnHuesLoadClick(Sender: TObject);
    procedure btnHuesSaveClick(Sender: TObject);
    procedure lbHueDrawItem(Control: TWinControl; Index: Integer;
      Rect: TRect; State: TOwnerDrawState);
    procedure tbHueChange(Sender: TObject);
    procedure btnHueFormClick(Sender: TObject);
    procedure lbHueClick(Sender: TObject);
    procedure ShowAnimation1Click(Sender: TObject);
    procedure est1Click(Sender: TObject);
    procedure ShowGump1Click(Sender: TObject);
    procedure iHueMouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer; Layer: TCustomLayer);
    procedure iHueMouseUp(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer; Layer: TCustomLayer);
    procedure iHueMouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer; Layer: TCustomLayer);
    procedure btnHueSpreadClick(Sender: TObject);
    procedure lbHue2DrawItem(Control: TWinControl; Index: Integer;
      Rect: TRect; State: TOwnerDrawState);
    procedure lbHue2Click(Sender: TObject);
    procedure tbHue2Change(Sender: TObject);
    procedure btnHueLoadClick(Sender: TObject);
    procedure btnHueCopyClick(Sender: TObject);
    procedure eHueNameKeyDown(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    procedure LoadfromDirectorytoVerdata1Click(Sender: TObject);
    procedure LoadfromFiletoVerdata1Click(Sender: TObject);
    procedure Copy1Click(Sender: TObject);
    procedure btnBrowseLightIdxClick(Sender: TObject);
    procedure btnBrowseLightMulClick(Sender: TObject);
    procedure btnLightSaveClick(Sender: TObject);
    procedure btnLightLoadClick(Sender: TObject);
    procedure lbLightDrawItem(Control: TWinControl; Index: Integer;
      Rect: TRect; State: TOwnerDrawState);
    procedure lbLightClick(Sender: TObject);
    procedure lbLightContextPopup(Sender: TObject; MousePos: TPoint;
      var Handled: Boolean);
    procedure SavetoBitmap4Click(Sender: TObject);
    procedure LoadfromBitmap4Click(Sender: TObject);
    procedure btnBrowseTiledataClick(Sender: TObject);
    procedure btnTiledataLoadClick(Sender: TObject);
    procedure btnTiledataSaveClick(Sender: TObject);
    procedure lbTiledataMapClick(Sender: TObject);
    procedure eTMNameChange(Sender: TObject);
    procedure eTMTexIdChange(Sender: TObject);
    procedure cbTMDamagingClick(Sender: TObject);
    procedure cbTMLiquidClick(Sender: TObject);
    procedure cbTMImpassableClick(Sender: TObject);
    procedure cbTMWallClick(Sender: TObject);
    procedure cbTMUnknown3Click(Sender: TObject);
    procedure btnTMSaveClick(Sender: TObject);
    procedure btnTMLoadClick(Sender: TObject);
    procedure lbTiledataStaticClick(Sender: TObject);
    procedure eTSNameChange(Sender: TObject);
    procedure eTSAnimIdChange(Sender: TObject);
    procedure eTSWeightChange(Sender: TObject);
    procedure eTSHeightChange(Sender: TObject);
    procedure eTSQualityChange(Sender: TObject);
    procedure eTSQuantityChange(Sender: TObject);
    procedure eTSHueChange(Sender: TObject);
    procedure eTSUnknown1Change(Sender: TObject);
    procedure eTSUnknown3Change(Sender: TObject);
    procedure eTSUnknown4Change(Sender: TObject);
    procedure eTSUnknown5Change(Sender: TObject);
    procedure eTSUnknown2Change(Sender: TObject);
    procedure cbTSBackgroundClick(Sender: TObject);
    procedure cbTSWeaponClick(Sender: TObject);
    procedure cbTSTransparentClick(Sender: TObject);
    procedure cbTSTranslucentClick(Sender: TObject);
    procedure cbTSWallClick(Sender: TObject);
    procedure cbTSDamagingClick(Sender: TObject);
    procedure cbTSImpassableClick(Sender: TObject);
    procedure cbTSLiquidClick(Sender: TObject);
    procedure cbTSUnknown1Click(Sender: TObject);
    procedure cbTSSurfaceClick(Sender: TObject);
    procedure cbTSBridgeClick(Sender: TObject);
    procedure cbTSGenericClick(Sender: TObject);
    procedure cbTSWindowClick(Sender: TObject);
    procedure cbTSNoshootClick(Sender: TObject);
    procedure cbTSAClick(Sender: TObject);
    procedure cbTSAnClick(Sender: TObject);
    procedure cbTSMongenClick(Sender: TObject);
    procedure cbTSFoliageClick(Sender: TObject);
    procedure cbTSPartialhueClick(Sender: TObject);
    procedure cbTSUnknown2Click(Sender: TObject);
    procedure cbTSMapClick(Sender: TObject);
    procedure cBTSContainerClick(Sender: TObject);
    procedure cbTSWearableClick(Sender: TObject);
    procedure cbTSLightsourceClick(Sender: TObject);
    procedure cbTSAnimationClick(Sender: TObject);
    procedure cbTSNodiagonalClick(Sender: TObject);
    procedure cbTSUnknown3Click(Sender: TObject);
    procedure cbTSArmorClick(Sender: TObject);
    procedure cbTSRoofClick(Sender: TObject);
    procedure cbTSDoorClick(Sender: TObject);
    procedure cbTSStairbackClick(Sender: TObject);
    procedure cbTSStairrightClick(Sender: TObject);
    procedure btnTSSaveClick(Sender: TObject);
    procedure btnTSLoadClick(Sender: TObject);
    procedure btnArtStaticExtractHolesClick(Sender: TObject);
    procedure btnBrowseAutopatchClick(Sender: TObject);
    procedure btnAutopatchStartClick(Sender: TObject);
    procedure btnExtractStartClick(Sender: TObject);
    procedure Delete5Click(Sender: TObject);
    procedure btnBrowseAnim2IdxClick(Sender: TObject);
    procedure btnBrowseAnim2MulClick(Sender: TObject);
    procedure btnAnim2LoadClick(Sender: TObject);
    procedure cbAnim2Change(Sender: TObject);
    procedure lbAnim2DrawItem(Control: TWinControl; Index: Integer;
      Rect: TRect; State: TOwnerDrawState);
    procedure lbAnim2Click(Sender: TObject);
    procedure btnBrowseAnim3IdxClick(Sender: TObject);
    procedure btnBrowseAnim3MulClick(Sender: TObject);
    procedure btnAnim3LoadClick(Sender: TObject);
    procedure cbAnim3Change(Sender: TObject);
    procedure lbAnim3DrawItem(Control: TWinControl; Index: Integer;
      Rect: TRect; State: TOwnerDrawState);
    procedure lbAnim3Click(Sender: TObject);
    procedure SaveAnimtoDirectory1Click(Sender: TObject);
    procedure SaveAnimtoFile1Click(Sender: TObject);
    procedure lbAnim2ContextPopup(Sender: TObject; MousePos: TPoint;
      var Handled: Boolean);
    procedure lbAnim3ContextPopup(Sender: TObject; MousePos: TPoint;
      var Handled: Boolean);
    procedure SaveAnimtoDirectory2Click(Sender: TObject);
    procedure SaveAnimtoFile2Click(Sender: TObject);
    procedure btnBrowseAnimdataClick(Sender: TObject);
    procedure btnAnimdataLoadClick(Sender: TObject);
    procedure btnAnimdataSaveClick(Sender: TObject);
    procedure lbAnimdataDrawItem(Control: TWinControl; Index: Integer;
      Rect: TRect; State: TOwnerDrawState);
    procedure cbAnimdataChange(Sender: TObject);
    procedure lbAnimdataClick(Sender: TObject);
    procedure cbAnimdataFrameNumberChange(Sender: TObject);
    procedure btnAnimdataStartClick(Sender: TObject);
    procedure btnAnimdataStopClick(Sender: TObject);
    procedure TimerAnimdataTimer(Sender: TObject);
    procedure eAnimdataFrameCountChange(Sender: TObject);
    procedure eAnimdataFrameStartChange(Sender: TObject);
    procedure eAnimdataFrameIntervalChange(Sender: TObject);
    procedure eAnimdataFrameRelativChange(Sender: TObject);
    procedure eAnimdataFrameChange(Sender: TObject);
    procedure btnAboutClick(Sender: TObject);
    procedure btnChooseStaticClick(Sender: TObject);
    procedure cbWin98Click(Sender: TObject);
    procedure btnReIndexClick(Sender: TObject);
    procedure btnAnimSearchClick(Sender: TObject);
    procedure eAnimSearchKeyDown(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    procedure btnAnim2SearchClick(Sender: TObject);
    procedure eAnim2SearchKeyDown(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    procedure btnAnim3SearchClick(Sender: TObject);
    procedure eAnim3SearchKeyDown(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    procedure btnAnimdataSearchClick(Sender: TObject);
    procedure eAnimdataSearchKeyDown(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    procedure btnArtMapSearchClick(Sender: TObject);
    procedure eArtMapSearchKeyDown(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    procedure btnArtStaticSearchClick(Sender: TObject);
    procedure eArtStaticSearchKeyDown(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    procedure btnGumpAnimSearchClick(Sender: TObject);
    procedure eGumpAnimSearchKeyDown(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    procedure btnGumpNonAnimSearchClick(Sender: TObject);
    procedure eGumpNonAnimSearchKeyDown(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    procedure btnTexSearchClick(Sender: TObject);
    procedure eTexSearchKeyDown(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    procedure btnTMSearchClick(Sender: TObject);
    procedure eTMSearchKeyDown(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    procedure btnTSSearchClick(Sender: TObject);
    procedure eTSSearchKeyDown(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    procedure btnBrowseSoundIdxClick(Sender: TObject);
    procedure btnBrowseSoundMulClick(Sender: TObject);
    procedure btnSoundSaveClick(Sender: TObject);
    procedure lbSoundDrawItem(Control: TWinControl; Index: Integer;
      Rect: TRect; State: TOwnerDrawState);
    procedure cbSoundChange(Sender: TObject);
    procedure btnSoundLoadClick(Sender: TObject);
    procedure lbSoundContextPopup(Sender: TObject; MousePos: TPoint;
      var Handled: Boolean);
    procedure PlaySound1Click(Sender: TObject);
    procedure SavetoFile3Click(Sender: TObject);
    procedure Delete6Click(Sender: TObject);
    procedure LoadfromFile2Click(Sender: TObject);
    procedure btnSoundSearchClick(Sender: TObject);
    procedure eSoundSearchKeyDown(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    procedure lbMultiDrawItem(Control: TWinControl; Index: Integer;
      Rect: TRect; State: TOwnerDrawState);
    procedure cbMultiChange(Sender: TObject);
    procedure btnMultiSearchClick(Sender: TObject);
    procedure lbMultiClick(Sender: TObject);
    procedure eMultiSearchKeyDown(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    procedure btnBrowseMultiIdxClick(Sender: TObject);
    procedure btnBrowseMultiMulClick(Sender: TObject);
    procedure btnMultiSaveClick(Sender: TObject);
    procedure btnMultiLoadClick(Sender: TObject);
    procedure lbMultiContextPopup(Sender: TObject; MousePos: TPoint;
      var Handled: Boolean);
    procedure SavetoWsc1Click(Sender: TObject);
    procedure SavetoWsc2Click(Sender: TObject);
    procedure LoadfromSphere51a1Click(Sender: TObject);
    procedure LoadfromWsc1Click(Sender: TObject);
    procedure Delete7Click(Sender: TObject);
    procedure btnBrowseStaticIdxClick(Sender: TObject);
    procedure btnBrowseStaticMulClick(Sender: TObject);
    procedure btnStaticSaveClick(Sender: TObject);
    procedure btnStaticLoadClick(Sender: TObject);
    procedure btnActivateEditorClick(Sender: TObject);
    procedure lbSoundClick(Sender: TObject);
    procedure btnStatDiffToolClick(Sender: TObject);
    procedure SaveToTextfile1Click(Sender: TObject);
    procedure LoadfromTextfile1Click(Sender: TObject);
    procedure ShowDetails1Click(Sender: TObject);
    procedure btnBrowseMapClick(Sender: TObject);
    procedure btnMapLoadClick(Sender: TObject);
    procedure lbTiledataMapDblClick(Sender: TObject);
    procedure btnCreateScriptsClick(Sender: TObject);
    procedure SetTag1Click(Sender: TObject);
    procedure cbLowMemoryClick(Sender: TObject);
    procedure TimerLoadTimer(Sender: TObject);
    procedure btnCountTexClick(Sender: TObject);
    procedure btnChooseMapFileClick(Sender: TObject);
    procedure btnStartMapIdChangeClick(Sender: TObject);
    procedure btnCreateStaticMapClick(Sender: TObject);
    procedure btnMapCopyClick(Sender: TObject);
    procedure btnBrowseStaticIdxDeleteClick(Sender: TObject);
    procedure btnBrowseStaticMulDeleteClick(Sender: TObject);
    procedure btnStartStaticDeleteClick(Sender: TObject);
    procedure btnSearchIDClick(Sender: TObject);
    procedure btnMCBrowseFromClick(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure eMapCopyFromChange(Sender: TObject);
    procedure eMapCopyToChange(Sender: TObject);
    procedure eX1Change(Sender: TObject);
    procedure eY1Change(Sender: TObject);
    procedure eX2Change(Sender: TObject);
    procedure eY2Change(Sender: TObject);
    procedure eMCSrcBreiteChange(Sender: TObject);
    procedure eMCSrcHoeheChange(Sender: TObject);
    procedure eTargX1Change(Sender: TObject);
    procedure eTargY1Change(Sender: TObject);
    procedure eMCTrgBreiteChange(Sender: TObject);
    procedure eMCTrgHoeheChange(Sender: TObject);
    procedure btnExtractFromFileClick(Sender: TObject);
    procedure SaveTo2Click(Sender: TObject);
    procedure LoadfromUOATextfile1Click(Sender: TObject);
    procedure btnPBrowseClick(Sender: TObject);
    procedure btnPStartClick(Sender: TObject);
    procedure btnStartHeightClick(Sender: TObject);
    procedure btnStartApplyPatchClick(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
    procedure Button4Click(Sender: TObject);
    procedure Button6Click(Sender: TObject);
    procedure Button5Click(Sender: TObject);
    procedure btnMSRunClick(Sender: TObject);
    procedure Button7Click(Sender: TObject);
    procedure Button8Click(Sender: TObject);
    procedure Button9Click(Sender: TObject);
    procedure LoadfromDirectory1Click(Sender: TObject);
    procedure Button10Click(Sender: TObject);
    procedure btnCreateEmptyClick(Sender: TObject);
    procedure btnSedinBrowseGumpClick(Sender: TObject);
    procedure btnSedinBrowseArtClick(Sender: TObject);
    procedure cbSedinPathClick(Sender: TObject);
    procedure cbSedinClearClick(Sender: TObject);
    procedure Button11Click(Sender: TObject);
    procedure Button12Click(Sender: TObject);
    procedure cbMEClick(Sender: TObject);
    procedure btnCPAStartClick(Sender: TObject);
    procedure Button13Click(Sender: TObject);
    procedure Button14Click(Sender: TObject);
    procedure btnSedinBrowseGumpWClick(Sender: TObject);
    procedure btnMergeClilocClick(Sender: TObject);
    procedure Button15Click(Sender: TObject);
    procedure Button16Click(Sender: TObject);
    procedure Button17Click(Sender: TObject);
    procedure btnArtDeleteIdsClick(Sender: TObject);
    procedure Button18Click(Sender: TObject);
    procedure btnAnim4SearchClick(Sender: TObject);
    procedure cbAnim4Change(Sender: TObject);
    procedure eAnim4SearchKeyDown(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    procedure lbAnim4Click(Sender: TObject);
    procedure lbAnim4ContextPopup(Sender: TObject; MousePos: TPoint;
      var Handled: Boolean);
    procedure lbAnim4DrawItem(Control: TWinControl; Index: Integer;
      Rect: TRect; State: TOwnerDrawState);
    procedure MenuItem4Click(Sender: TObject);
    procedure MenuItem5Click(Sender: TObject);
    procedure MenuItem6Click(Sender: TObject);
    procedure MenuItem7Click(Sender: TObject);
    procedure btnAnim5SearchClick(Sender: TObject);
    procedure cbAnim5Change(Sender: TObject);
    procedure eAnim5SearchKeyDown(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    procedure lbAnim5Click(Sender: TObject);
    procedure lbAnim5ContextPopup(Sender: TObject; MousePos: TPoint;
      var Handled: Boolean);
    procedure lbAnim5DrawItem(Control: TWinControl; Index: Integer;
      Rect: TRect; State: TOwnerDrawState);
    procedure btnBrowseAnim4IdxClick(Sender: TObject);
    procedure btnBrowseAnim4MulClick(Sender: TObject);
    procedure btnAnim4LoadClick(Sender: TObject);
    procedure btnBrowseAnim5IdxClick(Sender: TObject);
    procedure btnBrowseAnim5MulClick(Sender: TObject);
    procedure btnAnim5LoadClick(Sender: TObject);
    procedure Button19Click(Sender: TObject);
    procedure eColorMarkPixelsChange(Sender: TObject);
    procedure Button20Click(Sender: TObject);
    procedure eMapWidthChange(Sender: TObject);
    procedure eMapHeightChange(Sender: TObject);
  private
    { Private declarations }
    procedure LoadPaths;
    function BrowseFile( Filename : String ) : String;
    function SaveFile( Filename : String ) : String;
    procedure InitAnimations(Sender: TObject);
    procedure InitAnim2(Sender: TObject);
    procedure InitAnim3(Sender: TObject);
    procedure InitAnim4(Sender: TObject);
    procedure InitAnim5(Sender: TObject);
    procedure InitGumps(Sender: TObject );
    procedure InitArt(Sender: TObject );
    procedure InitTex(Sender: TObject );
    procedure InitRadar( Sender: TObject );
    procedure InitHue( Sender: TObject );
    procedure InitLight( Sender : TObject );
    procedure InitTiledata( Sender : TObject );
    procedure InitAnimdata( Sender : TObject );
    procedure InitSound( Sender : TObject );
    procedure InitMulti( Sender : TObject );
    procedure ArtMapColorChange( Sender : TObject );
    procedure ArtStaticColorChange( Sender : TObject );
    procedure PaintHueImage( Sender : TObject );
    procedure SetTileMap( Sender : TObject );
    procedure SetTileStatic( Sender : TObject );
    function AddFlag( Flag : Integer; Checked : Boolean ) : Integer;
    function FormatId( Id : Integer; Dezimal : Boolean ) : String;
    procedure AnimdataChanged(Sender: TObject);
    function Search( lb : TListBox; Sender : TObject; SearchString : String ) : Integer;
    procedure UpdatePatchMaps;
  public
    HueTyp : Integer;
    HueId : Integer;
    HueStart, HueEnd : Integer;
    HueDown : Boolean;
    TileChange : Boolean;
    AnimdataChange : Boolean;
    LastSearchIndex, LastSearchType : Integer;
    LowMemory : Boolean;
    MulCrypt : TMulCrypt;
    { Public declarations }
  end;

var
  MainForm: TMainForm;

implementation

type    TIndexRecord = packed record
                Offset: Integer;
                Length: Integer;
                Extra: Integer
        end;
{$R *.dfm}

procedure TMainForm.LoadPaths;
begin
        ePathAnimIdx.Text := Config.GetString( 'AnimIdx' );
        ePathAnimMul.Text := Config.GetString( 'AnimMul' );
        ePathAnim2Idx.Text := Config.GetString( 'Anim2Idx' );
        ePathAnim2Mul.Text := Config.GetString( 'Anim2Mul' );
        ePathAnim3Idx.Text := Config.GetString( 'Anim3Idx' );
        ePathAnim3Mul.Text := Config.GetString( 'Anim3Mul' );
        ePathAnim4Idx.Text := Config.GetString( 'Anim4Idx' );
        ePathAnim4Mul.Text := Config.GetString( 'Anim4Mul' );
        ePathAnim5Idx.Text := Config.GetString( 'Anim5Idx' );
        ePathAnim5Mul.Text := Config.GetString( 'Anim5Mul' );
        ePathVerdata.Text := Config.GetString( 'Verdata' );
        ePathGumpIdx.Text := Config.GetString( 'GumpIdx' );
        ePathGumpMul.Text := Config.GetString( 'GumpMul' );
        ePathArtIdx.Text := Config.GetString( 'ArtIdx' );
        ePathArtMul.Text := Config.GetString( 'ArtMul' );
        ePathTexIdx.Text := Config.GetString( 'TexIdx' );
        ePathTexMul.Text := Config.GetString( 'TexMul' );
        ePathRadarCol.Text := Config.GetString( 'RadarCol' );
        ePathHues.Text := Config.GetString( 'Hues' );
        ePathLightIdx.Text := Config.GetString( 'LightIdx' );
        ePathLightMul.Text := Config.GetString( 'LightMul' );
        ePathTiledata.Text := Config.GetString( 'Tiledata' );
        ePathAnimdata.Text := Config.GetString( 'Animdata' );
        ePathSoundIdx.Text := Config.GetString( 'SoundIdx' );
        ePathSoundMul.Text := Config.GetString( 'SoundMul' );
        ePathMultiIdx.Text := Config.GetString( 'MultiIdx' );
        ePathMultiMul.Text := Config.GetString( 'MultiMul' );
        ePathStaticIdx.Text := Config.GetString( 'StaticIdx' );
        ePathStaticMul.Text := Config.GetString( 'StaticMul' );
        ePathMap.Text := Config.GetString( 'Map' );
        cbWin98.Checked := Config.GetBool( 'Win98' );
        LowMemory := Config.GetBool( 'LowMemory' );
        cbLowMemory.Checked := LowMemory;

        eMapCopyFrom.Text := Config.GetString( 'MCFrom' );
        eMapCopyTo.Text := Config.GetString( 'MCTo' );
        eX1.Text := Config.GetString( 'MCX1' );
        eY1.Text := Config.GetString( 'MCY1' );
        eX2.Text := Config.GetString( 'MCX2' );
        eY2.Text := Config.GetString( 'MCY2' );
        eMCSrcBreite.Text := Config.GetString( 'MCSrcWidth' );
        eMCSrcHoehe.Text := Config.GetString( 'MCSrcHeight' );
        eTargX1.Text := Config.GetString( 'MCTargX1' );
        eTargY1.Text := Config.GetString( 'MCTargY1' );
        eMCTrgBreite.Text := Config.GetString( 'MCTrgWidth' );
        eMCTrgHoehe.Text := Config.GetString( 'MCTrgHeight' );

        if Config.GetString( 'ColorMarkPixels' ) = '' then
                Config.SetString( 'ColorMarkPixels', '0xFF00FF' );
        eColorMarkPixels.Text := Config.GetString( 'ColorMarkPixels' );

        eMapHeight.Text := Config.GetString( 'MapHeight' );
        eMapWidth.Text := Config.GetString( 'MapWidth' );
end;

function TMainForm.BrowseFile( Filename : String ) : String;
var     OpenDialog : TOpenDialog;
begin
        OpenDialog := TOpenDialog.Create( nil );
        OpenDialog.Filter := Filename + '|' + Filename;

        if not OpenDialog.Execute then begin
                OpenDialog.Free;
                Result := '';
                exit;
        end;

        if not FileExists(OpenDialog.FileName) then begin
                Application.MessageBox( 'Diese Datei ist nicht existent. Bitte wählen sie einen gültigen Dateinamen.', 'Datei nicht gefunden', MB_OK+MB_ICONERROR );
                OpenDialog.Free;
                Result := '';
                Exit;
        end;

        Result := OpenDialog.FileName;
        OpenDialog.Free;
end;

procedure TMainForm.InitAnimations( Sender : TObject );
begin
        if ( ePathAnimIdx.Text <> '' ) and ( ePathAnimMul.Text <> '' ) then
                Animation.Load( ePathAnimIdx.Text, ePathAnimMul.Text );

        cbAnimations.Clear;
        cbAnimations.Items.Add( 'All Slots' );
        cbAnimations.Items.Add( 'Empty Slots' );
        cbAnimations.Items.Add( 'Full Slots' );

        cbAnimations.ItemIndex := 0;
        cbAnimationsChange( Sender );
end;

procedure TMainForm.cbAnimationsChange(Sender: TObject);
var     i : integer;
        zeile, state : String;
begin
        lbAnimations.Clear;
        lbAnimations.Items.BeginUpdate;
        for i := 0 to Animation.CountAllAnims-1 do begin
                if i < 200 then
                        zeile := 'H'
                else if i < 400 then
                        zeile := 'L'
                else
                        zeile := 'P';
                zeile := zeile + ': ' + Format( '0x%x', [ i ] );

                state := cbAnimations.Items[ cbAnimations.ItemIndex ];
                if state = 'All Slots' then
                        lbAnimations.Items.Add( zeile )
                else if ( state = 'Empty Slots' ) and ( not Animation.AnimExists( i ) ) and ( not Verdata.Exists( typ_anim, i ) ) then
                        lbAnimations.Items.Add( zeile )
                else if ( state = 'Full Slots' ) and ( ( Animation.AnimExists( i ) ) or ( Verdata.Exists( typ_anim, i ) ) ) then
                        lbAnimations.Items.Add( zeile );
        end;
        lbAnimations.Items.EndUpdate;
end;

procedure TMainForm.btnBrowseAnimIdxClick(Sender: TObject);
var     NewFile : String;
begin
        NewFile := BrowseFile( 'Anim.idx' );
        if NewFile <> '' then begin
                Config.SetString( 'AnimIdx', Newfile );
                ePathAnimIdx.Text := NewFile;
        end;
end;

procedure TMainForm.btnBrowseAnimMulClick(Sender: TObject);
var     NewFile : String;
begin
        NewFile := BrowseFile( 'Anim.mul' );
        if NewFile <> '' then begin
                Config.SetString( 'AnimMul', Newfile );
                ePathAnimMul.Text := NewFile;
        end;
end;

procedure TMainForm.FormCreate(Sender: TObject);
begin
        MulCrypt := nil;

        LoadPaths;
        tabControl.ActivePage := tabArtMap;
        tabControl.ActivePage := tabSettings;
        tabControl.Update;

        EPDir.Text := Config.GetString( 'PatchDir' );
        UpdatePatchMaps;

        LastSearchIndex := -1;
        LastSearchType := -1;
        Randomize;

        if ParamCount > 0 then begin
                if ParamStr( 1 ) = '--Worldeditor' then begin
                        TimerLoad.Tag := 1;
                        TimerLoad.Enabled := True;
                end;
        end;
end;

procedure TMainForm.btnAnimLoadClick(Sender: TObject);
begin
        InitAnimations( Sender );
        showmessage( 'New Version does not load Anim.mul into Memory anymore, but writes directly into Anim.mul File. So make a backup before.' );
end;

function TMainForm.SaveFile( Filename : String ) : String;
var     SaveDialog : TSaveDialog;
begin
        SaveDialog := TSaveDialog.Create( nil );
        SaveDialog.Filter := Filename + '|' + Filename;

        if not SaveDialog.Execute then begin
                SaveDialog.Free;
                Result := '';
                exit;
        end;

        Result := SaveDialog.FileName;
        SaveDialog.Free;
end;

procedure TMainForm.lbAnimationsDrawItem(Control: TWinControl;
  Index: Integer; Rect: TRect; State: TOwnerDrawState);
var     Id : integer;
        Liste : TStringList;
begin
        lbAnimations.Canvas.Brush.Style := bsSolid;
        lbAnimations.Canvas.Brush.Color := clWhite;

        if ( odselected in state ) then begin
                lbAnimations.Canvas.Brush.Color := clNavy;
        end;
        lbAnimations.Canvas.FillRect( rect );

        Liste := TStringList.Create;
        StrLib.Split( lbAnimations.Items[ Index ], ' ', Liste );
        Id := strtoint( Liste.Strings[ 1 ] );
        Liste.Free;

        if Animation.AnimExists( Id ) then
                lbAnimations.Canvas.Font.Color := clBlack
        else
                lbAnimations.Canvas.Font.Color := clRed;

        if Verdata.Exists( typ_anim, Id ) then
                lbAnimations.Canvas.Font.Color := clGreen;

        lbAnimations.Canvas.Brush.Style := bsClear;
        if ( odselected in state ) then begin
                lbAnimations.Canvas.Font.Color := clWhite;
        end;

        lbAnimations.Canvas.TextOut( 10, (-lbAnimations.TopIndex+Index)*lbAnimations.ItemHeight, lbAnimations.Items[ Index ] );
end;

procedure TMainForm.lbAnimationsClick(Sender: TObject);
var     Bitmap : TBitmap32;
        Id : integer;
        Liste : TStringList;
begin
        Liste := TStringList.Create;
        StrLib.Split( lbAnimations.Items[ lbAnimations.ItemIndex ], ' ', Liste );
        Id := strtoint( Liste.Strings[ 1 ] );
        Liste.Free;

        if not Animation.AnimExists( Id ) and not Verdata.Exists( typ_anim, Id ) then begin
                iAnimations.Bitmap.SetSize( 360, 360 );
                iAnimations.Bitmap.Clear( Color32( iAnimations.Color ) );
                exit;
        end;

        if cbShowImage.Checked then begin
                if Verdata.Exists( typ_anim, Id ) then
                        Bitmap := Verdata.SaveFirstAnimPicture( Id )
                else
                        Bitmap := Animation.SaveFirstPicture( Id );
                iAnimations.Bitmap.SetSize( 360, 360 );
                iAnimations.Bitmap.Clear( Color32( iAnimations.Color ) );

                iAnimations.Bitmap.Draw( ( 360 - Bitmap.Width ) div 2, ( 360 - Bitmap.Height ) div 2, Bitmap );
                Bitmap.Free;
        end;

        if Gump.loaded and Gump.GumpExists( Id+50000 ) then begin
                Bitmap := Gump.GetGump( Id+50000 );
                iAnimGump.Bitmap.SetSize( 233, 233 );
                iAnimGump.Bitmap.Clear( Color32( iAnimGump.Color ) );

                iAnimGump.Bitmap.Draw( ( 233 - Bitmap.Width ) div 2, ( 233 - Bitmap.Height ) div 2, Bitmap );
                Bitmap.Free;
        end;
end;

procedure TMainForm.lbAnimationsContextPopup(Sender: TObject;
  MousePos: TPoint; var Handled: Boolean);
begin
        if lbAnimations.ItemIndex = -1 then
                exit;
        popAnimations.Popup( MousePos.X+MainForm.Left, MousePos.Y+MainForm.Top );
end;

procedure TMainForm.SavetoDirectory1Click(Sender: TObject);
var     SaveDialog : TrmBrowseForFolder;
        Id : integer;
        Liste : TStringList;
begin
        Liste := TStringList.Create;
        StrLib.Split( lbAnimations.Items[ lbAnimations.ItemIndex ], ' ', Liste );
        Id := strtoint( Liste.Strings[ 1 ] );
        Liste.Free;

        if ( not Animation.AnimExists( Id ) ) and ( not Verdata.Exists( typ_anim, Id ) ) then
                exit;

        SaveDialog := TrmBrowseForFolder.create( nil );
        SaveDialog.Title := 'Wohin soll die Animation gespeichert werden?';

        if not SaveDialog.Execute then begin
                SaveDialog.Free;
                exit;
        end;

        if Verdata.Exists( typ_anim, Id ) then
                Verdata.SaveAnimToDirectory( Id, SaveDialog.Folder )
        else
                Animation.SaveAnimToDirectory( Id, SaveDialog.Folder );
        SaveDialog.Free;
end;

procedure TMainForm.SavetoFile1Click(Sender: TObject);
var     LoadDialog : TrmBrowseForFolder;
        Id : integer;
        Liste : TStringList;
begin
        LoadDialog := TrmBrowseForFolder.create( nil );
        LoadDialog.Title := 'Woher soll die Animation geladen werden?';

        if not LoadDialog.Execute then begin
                LoadDialog.Free;
                exit;
        end;

        Liste := TStringList.Create;
        StrLib.Split( lbAnimations.Items[ lbAnimations.ItemIndex ], ' ', Liste );
        Id := strtoint( Liste.Strings[ 1 ] );
        Liste.Free;

        Animation.LoadAnimFromDirectory( Id, LoadDialog.Folder, cbPalette.Checked );
        LoadDialog.Free;
        lbAnimationsClick( Sender );
end;

procedure TMainForm.SavetoFile2Click(Sender: TObject);
var     SaveDialog : TSaveDialog;
        Id : integer;
        Liste : TStringList;
begin
        Liste := TStringList.Create;
        StrLib.Split( lbAnimations.Items[ lbAnimations.ItemIndex ], ' ', Liste );
        Id := strtoint( Liste.Strings[ 1 ] );
        Liste.Free;

        if ( not Animation.AnimExists( Id ) ) and ( not Verdata.Exists( typ_anim, Id ) ) then
                exit;

        SaveDialog := TSaveDialog.Create( nil );
        SaveDialog.DefaultExt := 'vd';
        SaveDialog.Filter := '*.vd|*.vd';
        SaveDialog.FileName := Format( '0x%x.vd', [Id] );

        if not SaveDialog.Execute then begin
                SaveDialog.Free;
                exit;
        end;

        if Verdata.Exists( typ_anim, Id ) then
                Verdata.SaveAnimToFile( Id, SaveDialog.FileName )
        else
                Animation.SaveAnimToFile( Id, SaveDialog.FileName );
        SaveDialog.Free;
end;

procedure TMainForm.LoadfromFile1Click(Sender: TObject);
var     OpenDialog : TOpenDialog;
        Id : integer;
        Liste : TStringList;
begin
        OpenDialog := TOpenDialog.Create( nil );
        OpenDialog.Filter := '*.vd|*.vd';

        if not OpenDialog.Execute then begin
                OpenDialog.Free;
                exit;
        end;

        Liste := TStringList.Create;
        StrLib.Split( lbAnimations.Items[ lbAnimations.ItemIndex ], ' ', Liste );
        Id := strtoint( Liste.Strings[ 1 ] );
        Liste.Free;

        Animation.LoadAnimFromFile( Id, OpenDialog.FileName );
        lbAnimationsClick( Sender );
        OpenDialog.Free;
end;

procedure TMainForm.btnBrowseVerdataClick(Sender: TObject);
var     NewFile : String;
begin
        NewFile := BrowseFile( 'Verdata.mul' );
        if NewFile <> '' then begin
                Config.SetString( 'Verdata', Newfile );
                ePathVerdata.Text := NewFile;
        end;
end;

procedure TMainForm.btnVerdataLoadClick(Sender: TObject);
begin
        if ePathVerdata.Text <> '' then begin
                Verdata.Load( ePathVerdata.Text );
                cbAnimations.Repaint;
                cbGumpAnim.Repaint;
                cbGumpNonAnim.Repaint;
                cbArtMap.Repaint;
                cbArtStatic.Repaint;
                cbTex.Repaint;
        end;
end;

procedure TMainForm.btnBrowseGumpIdxClick(Sender: TObject);
var     NewFile : String;
begin
        NewFile := BrowseFile( 'Gumpidx.mul' );
        if NewFile <> '' then begin
                Config.SetString( 'GumpIdx', Newfile );
                ePathGumpIdx.Text := NewFile;
        end;
end;

procedure TMainForm.btnBrowseGumpMulClick(Sender: TObject);
var     NewFile : String;
begin
        NewFile := BrowseFile( 'Gumpart.mul' );
        if NewFile <> '' then begin
                Config.SetString( 'GumpMul', Newfile );
                ePathGumpMul.Text := NewFile;
        end;
end;

procedure TMainForm.InitGumps( Sender: TObject );
begin
        if ( ePathGumpIdx.Text <> '' ) and ( ePathGumpMul.Text <> '' ) then
                Gump.Load( ePathGumpIdx.Text, ePathGumpMul.Text );

        cbGumpAnim.Clear;
        cbGumpAnim.Items.Add( 'All Slots' );
        cbGumpAnim.Items.Add( 'Empty Slots' );
        cbGumpAnim.Items.Add( 'Full Slots' );

        cbGumpAnim.ItemIndex := 0;
        cbGumpAnimChange( Sender );

        cbGumpNonAnim.Clear;
        cbGumpNonAnim.Items.Add( 'All Slots' );
        cbGumpNonAnim.Items.Add( 'Empty Slots' );
        cbGumpNonAnim.Items.Add( 'Full Slots' );

        cbGumpNonAnim.ItemIndex := 0;
        cbGumpNonAnimChange( Sender );
end;

procedure TMainForm.btnGumpLoadClick(Sender: TObject);
begin
        InitGumps( Sender );
end;

procedure TMainForm.cbGumpAnimChange(Sender: TObject);
var     i : integer;
        zeile, state : String;
begin
        lbGumpAnim.Clear;
        lbGumpAnim.Items.BeginUpdate;
        for i := $C350 to $EEFF do begin
                zeile := Format( '0x%x', [ i ] );

                state := cbGumpAnim.Items[ cbGumpAnim.ItemIndex ];
                if state = 'All Slots' then
                        lbGumpAnim.Items.Add( zeile )
                else if ( state = 'Empty Slots' ) and ( not Gump.GumpExists( i ) ) then
                        lbGumpAnim.Items.Add( zeile )
                else if ( state = 'Full Slots' ) and ( Gump.GumpExists( i ) ) then
                        lbGumpAnim.Items.Add( zeile );
        end;
        lbGumpAnim.Items.EndUpdate;
end;

procedure TMainForm.lbGumpAnimDrawItem(Control: TWinControl;
  Index: Integer; Rect: TRect; State: TOwnerDrawState);
var     Id : integer;
begin
        lbGumpAnim.Canvas.Brush.Style := bsSolid;
        lbGumpAnim.Canvas.Brush.Color := clWhite;

        if ( odselected in state ) then begin
                lbGumpAnim.Canvas.Brush.Color := clNavy;
        end;
        lbGumpAnim.Canvas.FillRect( rect );

        Id := strtoint( lbGumpAnim.Items[ Index ] );

        if Gump.GumpExists( Id ) then
                lbGumpAnim.Canvas.Font.Color := clBlack
        else
                lbGumpAnim.Canvas.Font.Color := clRed;

        if Verdata.Exists( typ_gumpart, Id ) then
                lbGumpAnim.Canvas.Font.Color := clGreen;

        lbGumpAnim.Canvas.Brush.Style := bsClear;
        if ( odselected in state ) then begin
                lbGumpAnim.Canvas.Font.Color := clWhite;
        end;

        lbGumpAnim.Canvas.TextOut( 10, (-lbGumpAnim.TopIndex+Index)*lbGumpAnim.ItemHeight, lbGumpAnim.Items[ Index ] );
end;

procedure TMainForm.lbGumpAnimClick(Sender: TObject);
var     Bitmap : TBitmap32;
        Id, AnimId : integer;
begin
        Id := strtoint( lbGumpAnim.Items[ lbGumpAnim.ItemIndex ] );

        AnimId := Id - 50000;
        if Animation.Loaded then begin
                if Animation.AnimExists( AnimId ) then begin
                        lAnimExists.Caption := Format( 'Animation exists: 0x%x', [ AnimId ] );
                end
                else
                        lAnimExists.Caption := Format( 'Animation 0x%x does not exists.', [ AnimId ] );
        end
        else
                lAnimExists.Caption := Format( 'Animation Id: 0x%x', [ AnimId ] );

        if not Gump.GumpExists( Id ) and not Verdata.Exists( typ_gumpart, Id ) then begin
                iGumpAnim.Bitmap.SetSize( 360, 360 );
                iGumpAnim.Bitmap.Clear( Color32( iGumpAnim.Color ) );
                exit;
        end;

        if Verdata.Exists( typ_gumpart, Id ) then
                Bitmap := Verdata.SaveGump( Id )
        else
                Bitmap := Gump.GetGump( Id );
        iGumpAnim.Bitmap.SetSize( 360, 360 );
        iGumpAnim.Bitmap.Clear( Color32( iGumpAnim.Color ) );

        iGumpAnim.Bitmap.Draw( ( 360 - Bitmap.Width ) div 2, ( 360 - Bitmap.Height ) div 2, Bitmap );
        Bitmap.Free;
end;

procedure TMainForm.Saveto1Click(Sender: TObject);
var     SaveDialog : TSaveDialog;
        Id : Integer;
        Bitmap : TBitmap32;
begin
        Id := strtoint( lbGumpAnim.Items[ lbGumpAnim.ItemIndex ] );

        SaveDialog := TSaveDialog.Create( nil );
        SaveDialog.Filter := '*.bmp|*.bmp';
        SaveDialog.DefaultExt := 'bmp';
        SaveDialog.FileName := Format( '0x%x.bmp', [Id] );

        if not SaveDialog.Execute then begin
                SaveDialog.Free;
                exit;
        end;

        if not Gump.GumpExists( Id ) and not Verdata.Exists( typ_gumpart, Id ) then begin
                SaveDialog.Free;
                exit;
        end;

        Bitmap := Gump.GetGump( Id );
        Bitmap.SaveToFile( SaveDialog.FileName );
        Bitmap.Free;
        SaveDialog.Free;
end;

procedure TMainForm.lbGumpAnimContextPopup(Sender: TObject;
  MousePos: TPoint; var Handled: Boolean);
begin
        if lbGumpAnim.ItemIndex = -1 then
                exit;
        popGumpAnim.Popup( MousePos.X+MainForm.Left, MousePos.Y+MainForm.Top );
end;

procedure TMainForm.Loadfrom1Click(Sender: TObject);
var     OpenDialog : TOpenDialog;
        Id : Integer;
begin
        OpenDialog := TOpenDialog.Create( nil );
        OpenDialog.Filter := '*.bmp|*.bmp';

        if not OpenDialog.Execute then begin
                OpenDialog.Free;
                exit;
        end;

        Id := strtoint( lbGumpAnim.Items[ lbGumpAnim.ItemIndex ] );
        Gump.LoadGump( Id, OpenDialog.FileName );

        lbGumpAnimClick( Sender );
        OpenDialog.Free;
end;

procedure TMainForm.Delete1Click(Sender: TObject);
var     Id : Integer;
begin
        Id := strtoint( lbGumpAnim.Items[ lbGumpAnim.ItemIndex ] );
        if Verdata.Exists( typ_gumpart, Id ) then
                Verdata.Delete( typ_gumpart, Id )
        else
                Gump.Delete( Id );
        lbGumpAnimClick( Sender );
end;

procedure TMainForm.cbGumpNonAnimChange(Sender: TObject);
var     i, Max : integer;
        zeile, state : String;
begin
        lbGumpNonAnim.Clear;
        lbGumpNonAnim.Items.BeginUpdate;

        state := cbGumpNonAnim.Items[ cbGumpNonAnim.ItemIndex ];

        if ( cbWin98.Checked ) and ( state <> 'Full Slots' ) then
                Max := $6FFF
        else
                Max := $C349;

        for i := $0 to Max do begin
                zeile := Format( '0x%x', [ i ] );
                if state = 'All Slots' then
                        lbGumpNonAnim.Items.Add( zeile )
                else if ( state = 'Empty Slots' ) and ( not Gump.GumpExists( i ) ) then
                        lbGumpNonAnim.Items.Add( zeile )
                else if ( state = 'Full Slots' ) and ( Gump.GumpExists( i ) ) then
                        lbGumpNonAnim.Items.Add( zeile );
        end;
        lbGumpNonAnim.Items.EndUpdate;
end;

procedure TMainForm.lbGumpNonAnimClick(Sender: TObject);
var     Bitmap : TBitmap32;
        Id : integer;
begin
        Id := strtoint( lbGumpNonAnim.Items[ lbGumpNonAnim.ItemIndex ] );

        if not Gump.GumpExists( Id ) and not Verdata.Exists( typ_gumpart, Id ) then begin
                iGumpNonAnim.Bitmap.SetSize( 360, 360 );
                iGumpNonAnim.Bitmap.Clear( Color32( iGumpNonAnim.Color ) );
                exit;
        end;

        if Verdata.Exists( typ_gumpart, Id ) then
                Bitmap := Verdata.SaveGump( Id )
        else
                Bitmap := Gump.GetGump( Id );
        iGumpNonAnim.Bitmap.SetSize( 360, 360 );
        iGumpNonAnim.Bitmap.Clear( Color32( iGumpNonAnim.Color ) );

        iGumpNonAnim.Bitmap.Draw( ( 360 - Bitmap.Width ) div 2, ( 360 - Bitmap.Height ) div 2, Bitmap );
        Bitmap.Free;
end;

procedure TMainForm.lbGumpNonAnimDrawItem(Control: TWinControl;
  Index: Integer; Rect: TRect; State: TOwnerDrawState);
var     Id : integer;
begin
        lbGumpNonAnim.Canvas.Brush.Style := bsSolid;
        lbGumpNonAnim.Canvas.Brush.Color := clWhite;

        if ( odselected in state ) then begin
                lbGumpNonAnim.Canvas.Brush.Color := clNavy;
        end;
        lbGumpNonAnim.Canvas.FillRect( rect );

        Id := strtoint( lbGumpNonAnim.Items[ Index ] );

        if Gump.GumpExists( Id ) then
                lbGumpNonAnim.Canvas.Font.Color := clBlack
        else
                lbGumpNonAnim.Canvas.Font.Color := clRed;

        if Verdata.Exists( typ_gumpart, Id ) then
                lbGumpNonAnim.Canvas.Font.Color := clGreen;

        lbGumpNonAnim.Canvas.Brush.Style := bsClear;
        if ( odselected in state ) then begin
                lbGumpNonAnim.Canvas.Font.Color := clWhite;
        end;

        lbGumpNonAnim.Canvas.TextOut( 10, (-lbGumpNonAnim.TopIndex+Index)*lbGumpNonAnim.ItemHeight, lbGumpNonAnim.Items[ Index ] );
end;

procedure TMainForm.MenuItem1Click(Sender: TObject);
var     SaveDialog : TSaveDialog;
        Id : Integer;
        Bitmap : TBitmap32;
begin
        Id := strtoint( lbGumpNonAnim.Items[ lbGumpNonAnim.ItemIndex ] );

        SaveDialog := TSaveDialog.Create( nil );
        SaveDialog.Filter := '*.bmp|*.bmp';
        SaveDialog.DefaultExt := 'bmp';
        SaveDialog.FileName := Format( '0x%x.bmp', [Id] );

        if not SaveDialog.Execute then begin
                SaveDialog.Free;
                exit;
        end;

        if not Gump.GumpExists( Id ) and not Verdata.Exists( typ_gumpart, Id ) then begin
                SaveDialog.Free;
                exit;
        end;

        Bitmap := Gump.GetGump( Id );
        Bitmap.SaveToFile( SaveDialog.FileName );
        Bitmap.Free;
        SaveDialog.Free;
end;

procedure TMainForm.MenuItem2Click(Sender: TObject);
var     OpenDialog : TOpenDialog;
        Id : Integer;
begin
        OpenDialog := TOpenDialog.Create( nil );
        OpenDialog.Filter := '*.bmp|*.bmp';

        if not OpenDialog.Execute then begin
                OpenDialog.Free;
                exit;
        end;

        Id := strtoint( lbGumpNonAnim.Items[ lbGumpNonAnim.ItemIndex ] );
        Gump.LoadGump( Id, OpenDialog.FileName );

        lbGumpNonAnimClick( Sender );
        OpenDialog.Free;
end;

procedure TMainForm.MenuItem3Click(Sender: TObject);
var     Id : Integer;
begin
        Id := strtoint( lbGumpNonAnim.Items[ lbGumpNonAnim.ItemIndex ] );
        if Verdata.Exists( typ_gumpart, Id ) then
                Verdata.Delete( typ_gumpart, Id )
        else
                Gump.Delete( Id );
        lbGumpNonAnimClick( Sender );
end;

procedure TMainForm.lbGumpNonAnimContextPopup(Sender: TObject;
  MousePos: TPoint; var Handled: Boolean);
begin
        if lbGumpNonAnim.ItemIndex = -1 then
                exit;
        popGumpNonAnim.Popup( MousePos.X+MainForm.Left, MousePos.Y+MainForm.Top );
end;

procedure TMainForm.InitArt( Sender: TObject );
begin
        if ( ePathArtIdx.Text <> '' ) and ( ePathArtMul.Text <> '' ) then
                Art.Load( ePathArtIdx.Text, ePathArtMul.Text );

        cbArtMap.Clear;
        cbArtMap.Items.Add( 'All Slots' );
        cbArtMap.Items.Add( 'Empty Slots' );
        cbArtMap.Items.Add( 'Full Slots' );

        cbArtMap.ItemIndex := 0;
        cbArtMapChange( Sender );

        cbArtStatic.Clear;
        cbArtStatic.Items.Add( 'All Slots' );
        cbArtStatic.Items.Add( 'Empty Slots' );
        cbArtStatic.Items.Add( 'Full Slots' );

        cbArtStatic.ItemIndex := 0;
        cbArtStaticChange( Sender );
end;

procedure TMainForm.btnArtLoadClick(Sender: TObject);
begin
        InitArt( Sender );
end;

procedure TMainForm.btnArtSaveClick(Sender: TObject);
var     idxPath, mulPath : String;
begin
        idxPath := SaveFile( 'Artidx.mul' );
        mulPath := SaveFile( 'Art.mul' );

        if ( idxPath <> '' ) and ( mulPath <> '' ) then begin
                Art.Save( idxPath, mulPath );
        end;
end;

procedure TMainForm.btnBrowseArtIdxClick(Sender: TObject);
var     NewFile : String;
begin
        NewFile := BrowseFile( 'Artidx.mul' );
        if NewFile <> '' then begin
                Config.SetString( 'ArtIdx', Newfile );
                ePathArtIdx.Text := NewFile;
        end;
end;

procedure TMainForm.btnBrowseArtMulClick(Sender: TObject);
var     NewFile : String;
begin
        NewFile := BrowseFile( 'Art.mul' );
        if NewFile <> '' then begin
                Config.SetString( 'ArtMul', Newfile );
                ePathArtMul.Text := NewFile;
        end;
end;

procedure TMainForm.cbArtMapChange(Sender: TObject);
var     i : integer;
        zeile, state : String;
begin
        lbArtMap.Clear;
        lbArtMap.Items.BeginUpdate;
        for i := 0 to $FFFF do begin
                zeile := Format( '0x%x', [ i ] );

                state := cbArtMap.Items[ cbArtMap.ItemIndex ];
                if state = 'All Slots' then
                        lbArtMap.Items.Add( zeile )
                else if ( state = 'Empty Slots' ) and ( not Art.MapExists( i ) ) then
                        lbArtMap.Items.Add( zeile )
                else if ( state = 'Full Slots' ) and ( Art.MapExists( i ) ) then
                        lbArtMap.Items.Add( zeile );
        end;
        lbArtMap.Items.EndUpdate;
end;

procedure TMainForm.lbArtMapClick(Sender: TObject);
var     Bitmap : TBitmap32;
        Id : integer;
begin
        Id := strtoint( lbArtMap.Items[ lbArtMap.ItemIndex ] );

        if not Art.MapExists( Id ) and not Verdata.Exists( typ_art, Id ) then begin
                iArtMap.Bitmap.SetSize( 360, 360 );
                iArtMap.Bitmap.Clear( Color32( iArtMap.Color ) );
                exit;
        end;

        if Verdata.Exists( typ_art, Id ) then
                Bitmap := Verdata.SaveMapArt( Id )
        else
                Bitmap := Art.GetMapTile( Id );
        iArtMap.Bitmap.SetSize( 360, 360 );
        iArtMap.Bitmap.Clear( Color32( iArtMap.Color ) );

        iArtMap.Bitmap.Draw( 0, 0, Bitmap );
        Bitmap.Free;

        iArtMapRadar.Bitmap.SetSize( 50, 50 );
        iArtMapRadar.Bitmap.Clear( Color32( Radarcol.GetColor( Id ) ) );
        eArtMapRadarBlue.Text := inttostr( Radarcol.GetBlue( Id ) );
        eArtMapRadarGreen.Text := inttostr( Radarcol.GetGreen( Id ) );
        eArtMapRadarRed.Text := inttostr( Radarcol.GetRed( Id ) );
end;

procedure TMainForm.lbArtMapDrawItem(Control: TWinControl; Index: Integer;
  Rect: TRect; State: TOwnerDrawState);
var     Id : integer;
begin
        lbArtMap.Canvas.Brush.Style := bsSolid;
        lbArtMap.Canvas.Brush.Color := clWhite;

        if ( odselected in state ) then begin
                lbArtMap.Canvas.Brush.Color := clNavy;
        end;
        lbArtMap.Canvas.FillRect( rect );

        Id := strtoint( lbArtMap.Items[ Index ] );

        if Art.MapExists( Id ) then
                lbArtMap.Canvas.Font.Color := clBlack
        else
                lbArtMap.Canvas.Font.Color := clRed;

        if Verdata.Exists( typ_art, Id ) then
                lbArtMap.Canvas.Font.Color := clGreen;

        lbArtMap.Canvas.Brush.Style := bsClear;
        if ( odselected in state ) then begin
                lbArtMap.Canvas.Font.Color := clWhite;
        end;

        lbArtMap.Canvas.TextOut( 10, (-lbArtMap.TopIndex+Index)*lbArtMap.ItemHeight, lbArtMap.Items[ Index ] );
end;

procedure TMainForm.lbArtMapContextPopup(Sender: TObject; MousePos: TPoint;
  var Handled: Boolean);
begin
        if lbArtMap.ItemIndex = -1 then
                exit;
        popArtMap.Popup( MousePos.X+MainForm.Left, MousePos.Y+MainForm.Top );
end;

procedure TMainForm.cbArtStaticChange(Sender: TObject);
var     i : integer;
        zeile, state : String;
begin
        lbArtStatic.Clear;
        lbArtStatic.Items.BeginUpdate;
        for i := 0 to Art.GetStaticCount-1 do begin
                zeile := Format( '0x%x', [ i ] );

                state := cbArtStatic.Items[ cbArtStatic.ItemIndex ];
                if state = 'All Slots' then
                        lbArtStatic.Items.Add( zeile )
                else if ( state = 'Empty Slots' ) and ( not Art.StaticExists( i ) ) then
                        lbArtStatic.Items.Add( zeile )
                else if ( state = 'Full Slots' ) and ( Art.StaticExists( i ) ) then
                        lbArtStatic.Items.Add( zeile );
        end;
        lbArtStatic.Items.EndUpdate;
end;

procedure TMainForm.lbArtStaticClick(Sender: TObject);
var     Bitmap : TBitmap32;
        Id : integer;
begin
        Id := strtoint( lbArtStatic.Items[ lbArtStatic.ItemIndex ] );

        if not Art.StaticExists( Id ) and not Verdata.Exists( typ_art, Id+$4000 ) then begin
                iArtStatic.Bitmap.SetSize( 360, 360 );
                iArtStatic.Bitmap.Clear( Color32( iArtStatic.Color ) );
                exit;
        end;

        if Verdata.Exists( typ_art, Id+$4000 ) then
                Bitmap := Verdata.SaveStaticArt( Id )
        else
                Bitmap := Art.GetStaticTile( Id );
        iArtStatic.Bitmap.SetSize( 360, 360 );
        iArtStatic.Bitmap.Clear( Color32( iArtStatic.Color ) );

        iArtStatic.Bitmap.Draw( ( 360 - Bitmap.Width ) div 2, ( 360 - Bitmap.Height ) div 2, Bitmap );
        Bitmap.Free;

        iArtStaticRadar.Bitmap.SetSize( 50, 50 );
        iArtStaticRadar.Bitmap.Clear( Radarcol.GetColor( Id+$4000 ) );
        eArtStaticRadarBlue.Text := inttostr( Radarcol.GetBlue( Id+$4000 ) );
        eArtStaticRadarGreen.Text := inttostr( Radarcol.GetGreen( Id+$4000 ) );
        eArtStaticRadarRed.Text := inttostr( Radarcol.GetRed( Id+$4000 ) );
end;

procedure TMainForm.lbArtStaticDrawItem(Control: TWinControl;
  Index: Integer; Rect: TRect; State: TOwnerDrawState);
var     Id : integer;
begin
        lbArtStatic.Canvas.Brush.Style := bsSolid;
        lbArtStatic.Canvas.Brush.Color := clWhite;

        if ( odselected in state ) then begin
                lbArtStatic.Canvas.Brush.Color := clNavy;
        end;
        lbArtStatic.Canvas.FillRect( rect );

        Id := strtoint( lbArtStatic.Items[ Index ] );

        if Art.StaticExists( Id ) then
                lbArtStatic.Canvas.Font.Color := clBlack
        else
                lbArtStatic.Canvas.Font.Color := clRed;

        if Verdata.Exists( typ_art, Id+$4000 ) then
                lbArtStatic.Canvas.Font.Color := clGreen;

        lbArtStatic.Canvas.Brush.Style := bsClear;
        if ( odselected in state ) then begin
                lbArtStatic.Canvas.Font.Color := clWhite;
        end;

        lbArtStatic.Canvas.TextOut( 10, (-lbArtStatic.TopIndex+Index)*lbArtStatic.ItemHeight, lbArtStatic.Items[ Index ] );
end;

procedure TMainForm.lbArtStaticContextPopup(Sender: TObject;
  MousePos: TPoint; var Handled: Boolean);
begin
        if lbArtStatic.ItemIndex = -1 then
                exit;
        popArtStatic.Popup( MousePos.X+MainForm.Left, MousePos.Y+MainForm.Top );
end;

procedure TMainForm.SavetoBitmap1Click(Sender: TObject);
var     SaveDialog : TSaveDialog;
        Id : Integer;
        Bitmap : TBitmap32;
begin
        Id := strtoint( lbArtMap.Items[ lbArtMap.ItemIndex ] );

        SaveDialog := TSaveDialog.Create( nil );
        SaveDialog.Filter := '*.bmp|*.bmp';
        SaveDialog.DefaultExt := 'bmp';
        SaveDialog.FileName := Format( '0x%x.bmp', [Id] );

        if not SaveDialog.Execute then begin
                SaveDialog.Free;
                exit;
        end;

        if not Art.MapExists( Id ) and not Verdata.Exists( typ_art, Id ) then begin
                SaveDialog.Free;
                exit;
        end;

        Bitmap := Art.GetMapTile( Id );
        Bitmap.SaveToFile( SaveDialog.FileName );
        Bitmap.Free;
        SaveDialog.Free;
end;

procedure TMainForm.LoadfromBitmap1Click(Sender: TObject);
var     OpenDialog : TOpenDialog;
        Id : Integer;
begin
        OpenDialog := TOpenDialog.Create( nil );
        OpenDialog.Filter := '*.bmp|*.bmp';

        if not OpenDialog.Execute then begin
                OpenDialog.Free;
                exit;
        end;

        Id := strtoint( lbArtMap.Items[ lbArtMap.ItemIndex ] );
        Art.LoadMapTile( Id, OpenDialog.FileName );

        lbArtMapClick( Sender );
        OpenDialog.Free;
end;

procedure TMainForm.Delete2Click(Sender: TObject);
var     Id : integer;
begin
        Id := strtoint( lbArtMap.Items[ lbArtMap.ItemIndex ] );
        if Verdata.Exists( typ_art, Id ) then
                Verdata.Delete( typ_art, Id )
        else
                Art.DeleteMap( Id );
        lbArtMapClick( Sender );
end;

procedure TMainForm.SavetoBitmap2Click(Sender: TObject);
var     SaveDialog : TSaveDialog;
        Id : Integer;
        Bitmap : TBitmap32;
begin
        Id := strtoint( lbArtStatic.Items[ lbArtStatic.ItemIndex ] );

        SaveDialog := TSaveDialog.Create( nil );
        SaveDialog.Filter := '*.bmp|*.bmp';
        SaveDialog.DefaultExt := 'bmp';
        SaveDialog.FileName := Format( '0x%x.bmp', [Id] );

        if not SaveDialog.Execute then begin
                SaveDialog.Free;
                exit;
        end;

        if not Art.StaticExists( Id ) and not Verdata.Exists( typ_art, Id+$4000 ) then begin
                SaveDialog.Free;
                exit;
        end;

        Bitmap := Art.GetStaticTile( Id );
        Bitmap.SaveToFile( SaveDialog.FileName );
        Bitmap.Free;
        SaveDialog.Free;
end;

procedure TMainForm.LoadfromBitmap2Click(Sender: TObject);
var     OpenDialog : TOpenDialog;
        Id : Integer;
begin
        OpenDialog := TOpenDialog.Create( nil );
        OpenDialog.Filter := '*.bmp|*.bmp';

        if not OpenDialog.Execute then begin
                OpenDialog.Free;
                exit;
        end;

        Id := strtoint( lbArtStatic.Items[ lbArtStatic.ItemIndex ] );
        Art.LoadStaticTile( Id, OpenDialog.FileName );

        lbArtStaticClick( Sender );
        OpenDialog.Free;
end;

procedure TMainForm.Delete3Click(Sender: TObject);
var     Id : integer;
begin
        Id := strtoint( lbArtStatic.Items[ lbArtStatic.ItemIndex ] );
        if Verdata.Exists( typ_art, Id+$4000 ) then
                Verdata.Delete( typ_art, Id+$4000 )
        else
                Art.DeleteStatic( Id );
        lbArtStaticClick( Sender );
end;

procedure TMainForm.btnBrowseTexIdxClick(Sender: TObject);
var     NewFile : String;
begin
        NewFile := BrowseFile( 'Texidx.mul' );
        if NewFile <> '' then begin
                Config.SetString( 'TexIdx', Newfile );
                ePathTexIdx.Text := NewFile;
        end;
end;

procedure TMainForm.btnBrowseTexMulClick(Sender: TObject);
var     NewFile : String;
begin
        NewFile := BrowseFile( 'Texmaps.mul' );
        if NewFile <> '' then begin
                Config.SetString( 'TexMul', Newfile );
                ePathTexMul.Text := NewFile;
        end;
end;

procedure TMainForm.btnTexLoadClick(Sender: TObject);
begin
        InitTex( Sender );
end;

procedure TMainForm.btnGumpSaveClick(Sender: TObject);
var     idxPath, mulPath : String;
begin
        idxPath := SaveFile( 'Gumpidx.mul' );
        mulPath := SaveFile( 'Gumpart.mul' );

        if ( idxPath <> '' ) and ( mulPath <> '' ) then begin
                Gump.Save( idxPath, mulPath );
        end;
end;

procedure TMainForm.btnTexSaveClick(Sender: TObject);
var     idxPath, mulPath : String;
begin
        idxPath := SaveFile( 'Texidx.mul' );
        mulPath := SaveFile( 'Texmaps.mul' );

        if ( idxPath <> '' ) and ( mulPath <> '' ) then begin
                Textures.Save( idxPath, mulPath );
        end;
end;

procedure TMainForm.InitTex( Sender: TObject );
begin
        if ( ePathTexIdx.Text <> '' ) and ( ePathTexMul.Text <> '' ) then
                Textures.Load( ePathTexIdx.Text, ePathTexMul.Text );

        cbTex.Clear;
        cbTex.Items.Add( 'All Slots' );
        cbTex.Items.Add( 'Empty Slots' );
        cbTex.Items.Add( 'Full Slots' );

        cbTex.ItemIndex := 0;
        cbTexChange( Sender );
end;

procedure TMainForm.lbTexClick(Sender: TObject);
var     Bitmap : TBitmap32;
        Id : integer;
begin
        Id := strtoint( lbTex.Items[ lbTex.ItemIndex ] );

        if not Textures.Exists( Id ) and not Verdata.Exists( typ_texmaps, Id ) then begin
                iTex.Bitmap.SetSize( 360, 360 );
                iTex.Bitmap.Clear( Color32( iTex.Color ) );
                exit;
        end;

        if Verdata.Exists( typ_texmaps, Id ) then
                Bitmap := Verdata.SaveTex( Id )
        else
                Bitmap := Textures.GetTex( Id );
        iTex.Bitmap.SetSize( 360, 360 );
        iTex.Bitmap.Clear( Color32( iTex.Color ) );

        iTex.Bitmap.Draw( ( 360 - Bitmap.Width ) div 2, ( 360 - Bitmap.Height ) div 2, Bitmap );
        Bitmap.Free;
end;

procedure TMainForm.lbTexDrawItem(Control: TWinControl; Index: Integer;
  Rect: TRect; State: TOwnerDrawState);
var     Id : integer;
begin
        lbTex.Canvas.Brush.Style := bsSolid;
        lbTex.Canvas.Brush.Color := clWhite;

        if ( odselected in state ) then begin
                lbTex.Canvas.Brush.Color := clNavy;
        end;
        lbTex.Canvas.FillRect( rect );

        Id := strtoint( lbTex.Items[ Index ] );

        if Textures.Exists( Id ) then
                lbTex.Canvas.Font.Color := clBlack
        else
                lbTex.Canvas.Font.Color := clRed;

        if Verdata.Exists( typ_texmaps, Id ) then
                lbTex.Canvas.Font.Color := clGreen;

        lbTex.Canvas.Brush.Style := bsClear;
        if ( odselected in state ) then begin
                lbTex.Canvas.Font.Color := clWhite;
        end;

        lbTex.Canvas.TextOut( 10, (-lbTex.TopIndex+Index)*lbTex.ItemHeight, lbTex.Items[ Index ] );
end;

procedure TMainForm.cbTexChange(Sender: TObject);
var     i : integer;
        zeile, state : String;
begin
        lbTex.Clear;
        lbTex.Items.BeginUpdate;
        for i := $0 to $FFFF do begin
                zeile := Format( '0x%x', [ i ] );

                state := cbTex.Items[ cbTex.ItemIndex ];
                if state = 'All Slots' then
                        lbTex.Items.Add( zeile )
                else if ( state = 'Empty Slots' ) and ( not Textures.Exists( i ) ) then
                        lbTex.Items.Add( zeile )
                else if ( state = 'Full Slots' ) and ( Textures.Exists( i ) ) then
                        lbTex.Items.Add( zeile );
        end;
        lbTex.Items.EndUpdate;
end;

procedure TMainForm.lbTexContextPopup(Sender: TObject; MousePos: TPoint;
  var Handled: Boolean);
begin
        if lbTex.ItemIndex = -1 then
                exit;
        popTex.Popup( MousePos.X+MainForm.Left, MousePos.Y+MainForm.Top );
end;

procedure TMainForm.SavetoBitmap3Click(Sender: TObject);
var     SaveDialog : TSaveDialog;
        Id : Integer;
        Bitmap : TBitmap32;
begin
        Id := strtoint( lbTex.Items[ lbTex.ItemIndex ] );

        SaveDialog := TSaveDialog.Create( nil );
        SaveDialog.Filter := '*.bmp|*.bmp';
        SaveDialog.DefaultExt := 'bmp';
        SaveDialog.FileName := Format( '0x%x.bmp', [Id] );

        if not SaveDialog.Execute then begin
                SaveDialog.Free;
                exit;
        end;

        if not Textures.Exists( Id ) and not Verdata.Exists( typ_texmaps, Id ) then begin
                SaveDialog.Free;
                exit;
        end;

        Bitmap := Textures.GetTex( Id );
        Bitmap.SaveToFile( SaveDialog.FileName );
        Bitmap.Free;
        SaveDialog.Free;
end;

procedure TMainForm.LoadfromBitmap3Click(Sender: TObject);
var     OpenDialog : TOpenDialog;
        Id : Integer;
begin
        OpenDialog := TOpenDialog.Create( nil );
        OpenDialog.Filter := '*.bmp|*.bmp';

        if not OpenDialog.Execute then begin
                OpenDialog.Free;
                exit;
        end;

        Id := strtoint( lbTex.Items[ lbTex.ItemIndex ] );
        Textures.LoadTex( Id, OpenDialog.FileName );

        lbTexClick( Sender );
        OpenDialog.Free;
end;

procedure TMainForm.Delete4Click(Sender: TObject);
var     Id : integer;
begin
        Id := strtoint( lbTex.Items[ lbTex.ItemIndex ] );

        if Verdata.Exists( typ_texmaps, Id ) then
                Verdata.Delete( typ_texmaps, Id )
        else
                Textures.Delete( Id );
        lbTexClick( Sender );
end;

procedure TMainForm.LoadfromBitmaptoVerdata1Click(Sender: TObject);
var     OpenDialog : TOpenDialog;
        Id : Integer;
begin
        OpenDialog := TOpenDialog.Create( nil );
        OpenDialog.Filter := '*.bmp|*.bmp';

        if not OpenDialog.Execute then begin
                OpenDialog.Free;
                exit;
        end;

        Id := strtoint( lbArtStatic.Items[ lbArtStatic.ItemIndex ] );
        Verdata.LoadStaticArt( Id, OpenDialog.FileName );

        lbArtStaticClick( Sender );
        OpenDialog.Free;
end;

procedure TMainForm.btnVerdataSaveClick(Sender: TObject);
var     Path : String;
begin
        Path := SaveFile( 'Verdata.mul' );

        if ( Path <> '' ) then begin
                Verdata.Save( Path );
        end;
end;

procedure TMainForm.LoadfromBitmaptoVerdata2Click(Sender: TObject);
var     OpenDialog : TOpenDialog;
        Id : Integer;
begin
        OpenDialog := TOpenDialog.Create( nil );
        OpenDialog.Filter := '*.bmp|*.bmp';

        if not OpenDialog.Execute then begin
                OpenDialog.Free;
                exit;
        end;

        Id := strtoint( lbArtMap.Items[ lbArtMap.ItemIndex ] );
        Verdata.LoadMapArt( Id, OpenDialog.FileName );

        lbArtMapClick( Sender );
        OpenDialog.Free;
end;

procedure TMainForm.LoadfromBitmaptoVerdata3Click(Sender: TObject);
var     OpenDialog : TOpenDialog;
        Id : Integer;
begin
        OpenDialog := TOpenDialog.Create( nil );
        OpenDialog.Filter := '*.bmp|*.bmp';

        if not OpenDialog.Execute then begin
                OpenDialog.Free;
                exit;
        end;

        Id := strtoint( lbTex.Items[ lbTex.ItemIndex ] );
        Verdata.LoadTex( Id, OpenDialog.FileName );

        lbTexClick( Sender );
        OpenDialog.Free;
end;

procedure TMainForm.LoadfromBitmaptoVerdata4Click(Sender: TObject);
var     OpenDialog : TOpenDialog;
        Id : Integer;
begin
        OpenDialog := TOpenDialog.Create( nil );
        OpenDialog.Filter := '*.bmp|*.bmp';

        if not OpenDialog.Execute then begin
                OpenDialog.Free;
                exit;
        end;

        Id := strtoint( lbGumpAnim.Items[ lbGumpAnim.ItemIndex ] );
        Verdata.LoadGump( Id, OpenDialog.FileName );

        lbGumpAnimClick( Sender );
        OpenDialog.Free;
end;

procedure TMainForm.LoadfromBitmaptoVerdata5Click(Sender: TObject);
var     OpenDialog : TOpenDialog;
        Id : Integer;
begin
        OpenDialog := TOpenDialog.Create( nil );
        OpenDialog.Filter := '*.bmp|*.bmp';

        if not OpenDialog.Execute then begin
                OpenDialog.Free;
                exit;
        end;

        Id := strtoint( lbGumpNonAnim.Items[ lbGumpNonAnim.ItemIndex ] );
        Verdata.LoadGump( Id, OpenDialog.FileName );

        lbGumpNonAnimClick( Sender );
        OpenDialog.Free;
end;

procedure TMainForm.btnBrowseRadarColClick(Sender: TObject);
var     NewFile : String;
begin
        NewFile := BrowseFile( 'Radarcol.mul' );
        if NewFile <> '' then begin
                Config.SetString( 'RadarCol', Newfile );
                ePathRadarCol.Text := NewFile;
        end;
end;

procedure TMainForm.btnLoadRadarColClick(Sender: TObject);
begin
        if ePathRadarCol.Text <> '' then begin
                Radarcol.Load( ePathRadarCol.Text );
                InitRadar( Sender );
        end;
end;

procedure TMainForm.btnSaveRadarColClick(Sender: TObject);
var     Path : String;
begin
        Path := SaveFile( 'Radarcol.mul' );

        if ( Path <> '' ) then begin
                Radarcol.Save( Path );
        end;
end;

procedure TMainForm.InitRadar( Sender : TObject );
begin
        iArtMapRadar.Visible := true;
        eArtMapRadarBlue.Visible := true;
        eArtMapRadarGreen.Visible := true;
        eArtMapRadarRed.Visible := true;
        eArtMapRadarFrom.Visible := true;
        eArtMapRadarTo.Visible := true;
        btnArtMapRadarAverage.Visible := true;

        iArtStaticRadar.Visible := true;
        eArtStaticRadarBlue.Visible := true;
        eArtStaticRadarGreen.Visible := true;
        eArtStaticRadarRed.Visible := true;
        eArtStaticRadarFrom.Visible := true;
        eArtStaticRadarTo.Visible := true;
        btnArtStaticRadarAverage.Visible := true;
end;

procedure TMainForm.ArtMapColorChange( Sender : TObject );
var     Color : integer;
        Blue, Red, Green : Integer;
        Id : Integer;
begin
        if lbArtMap.ItemIndex = -1 then exit;
        Red := strtoint( eArtMapRadarRed.Text );
        Green := strtoint( eArtMapRadarGreen.Text );
        Blue := strtoint( eArtMapRadarBlue.Text );

        Color := Color32( Blue, Green, Red );

        Id := strtoint( lbArtMap.Items[ lbArtMap.ItemIndex ] );
        Radarcol.SetColor( Id, Color );
        lbArtMapClick( Sender );
end;

procedure TMainForm.eArtMapRadarBlueKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
        if Key = VK_Return then
                ArtMapColorChange( Sender );
end;

procedure TMainForm.eArtMapRadarGreenKeyDown(Sender: TObject;
  var Key: Word; Shift: TShiftState);
begin
        if Key = VK_Return then
                ArtMapColorChange( Sender );
end;

procedure TMainForm.eArtMapRadarRedKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
        if Key = VK_Return then
                ArtMapColorChange( Sender );
end;

procedure TMainForm.btnArtMapRadarAverageClick(Sender: TObject);
var     First, Last : Integer;
        Id : Integer;
        Color : integer;
begin
        if not Art.loaded then exit;
        First := Strtoint( eArtMapRadarFrom.Text );
        Last := Strtoint( eArtMapRadarTo.Text );

        for Id := First to Last do begin
                Color := WinColor( Art.GetAverageMapColor( Id ) );
                RadarCol.SetColor( Id, Color );
        end;

        if lbArtMap.ItemIndex <> -1 then
                lbArtMapClick( Sender );
end;

procedure TMainForm.ArtStaticColorChange( Sender : TObject );
var     Color : integer;
        Blue, Red, Green : Integer;
        Id : Integer;
begin
        if lbArtStatic.ItemIndex = -1 then exit;
        Red := strtoint( eArtStaticRadarRed.Text );
        Green := strtoint( eArtStaticRadarGreen.Text );
        Blue := strtoint( eArtStaticRadarBlue.Text );

        Color := Color32( Blue, Green, Red );

        Id := strtoint( lbArtStatic.Items[ lbArtStatic.ItemIndex ] );
        Radarcol.SetColor( Id+$4000, Color );
        lbArtStaticClick( Sender );
end;

procedure TMainForm.eArtStaticRadarBlueKeyDown(Sender: TObject;
  var Key: Word; Shift: TShiftState);
begin
        if Key = VK_Return then
                ArtStaticColorChange( Sender );
end;

procedure TMainForm.eArtStaticRadarGreenKeyDown(Sender: TObject;
  var Key: Word; Shift: TShiftState);
begin
        if Key = VK_Return then
                ArtStaticColorChange( Sender );
end;

procedure TMainForm.eArtStaticRadarRedKeyDown(Sender: TObject;
  var Key: Word; Shift: TShiftState);
begin
        if Key = VK_Return then
                ArtStaticColorChange( Sender );
end;

procedure TMainForm.btnArtStaticRadarAverageClick(Sender: TObject);
var     First, Last : Integer;
        Id : Integer;
        Color : integer;
begin
        if not Art.loaded then exit;
        First := Strtoint( eArtStaticRadarFrom.Text );
        Last := Strtoint( eArtStaticRadarTo.Text );

        for Id := First to Last do begin
                Color := WinColor( Art.GetAverageStaticColor( Id ) );
                RadarCol.SetColor( Id+$4000, Color );
        end;

        if lbArtStatic.ItemIndex <> -1 then
                lbArtStaticClick( Sender );
end;

procedure TMainForm.btnBrowseHuesClick(Sender: TObject);
var     NewFile : String;
begin
        NewFile := BrowseFile( 'Hues.mul' );
        if NewFile <> '' then begin
                Config.SetString( 'Hues', Newfile );
                ePathHues.Text := NewFile;
        end;
end;

procedure TMainForm.btnHuesLoadClick(Sender: TObject);
begin
        InitHue( Sender );
end;

procedure TMainForm.btnHuesSaveClick(Sender: TObject);
var     Path : String;
begin
        Path := SaveFile( 'Hues.mul' );

        if ( Path <> '' ) then begin
                Hues.Save( Path );
        end;
end;

procedure TMainForm.InitHue( Sender : TObject );
var     i : Integer;
begin
        if ePathHues.Text <> '' then begin
                Hues.Load( ePathHues.Text );
        end;

        lbHue.Items.BeginUpdate;
        for i := 0 to Hues.GetHueCount-1 do begin
                lbHue.Items.Add( Format( '0x%x', [i] ) );
        end;
        lbHue.Items.EndUpdate;
        HueStart := -1;
        HueEnd := -1;
end;

procedure TMainForm.lbHueDrawItem(Control: TWinControl; Index: Integer;
  Rect: TRect; State: TOwnerDrawState);
var     Id : integer;
begin
        lbHue.Canvas.Brush.Style := bsSolid;
        lbHue.Canvas.Brush.Color := clWhite;

        if ( odselected in state ) then begin
                lbHue.Canvas.Brush.Color := clNavy;
        end;
        lbHue.Canvas.FillRect( rect );

        Id := strtoint( lbHue.Items[ Index ] );

        lbHue.Canvas.Font.Color := WinColor( Color15to32( Hues.GetColor( Id, tbHue.Position ) ) );

        lbHue.Canvas.Brush.Style := bsClear;
        if ( odselected in state ) then begin
                lbHue.Canvas.Font.Color := clWhite;
        end;

        lbHue.Canvas.TextOut( 10, (-lbHue.TopIndex+Index)*lbHue.ItemHeight, lbHue.Items[ Index ] );
end;

procedure TMainForm.tbHueChange(Sender: TObject);
begin
        lbHue.Repaint;
end;

procedure TMainForm.btnHueFormClick(Sender: TObject);
begin
        HueForm.Activate;
end;

procedure TMainForm.lbHueClick(Sender: TObject);
var     Id, i : Integer;
begin
        Id := strtoint( lbHue.Items[ lbHue.ItemIndex ] );
        iHue.Bitmap.Width := 75;
        iHue.Bitmap.Height := 353;
        iHue.Bitmap.Clear( Color32( iHue.Color ) );
        iHue.Bitmap.FillRect( 0, 0, 60, 353, clBlack32 );
        for i := 0 to 31 do begin
                iHue.Bitmap.FillRect( 1, 1+i*11, 59, 1+i*11+10, Color15to32( Hues.GetColor( Id, i ) ) );
                if ( i >= HueStart ) and ( i <= HueEnd ) then begin
                        iHue.Bitmap.FillRect( 61, 1+i*11, 74, 1+i*11+10, clBlue32 );
                end;
        end;
        eHueName.Text := Hues.GetName( Id );
        PaintHueImage( Sender );
end;

procedure TMainForm.ShowAnimation1Click(Sender: TObject);
var     Id : Integer;
begin
        if not Animation.Loaded then
                exit;
        Id := strtoint( InputBox( 'ID', 'Gebt eine ID an.', Format( '0x%x', [Config.GetInteger( 'HueAnimId' )] ) ) );

        if not Animation.AnimExists( Id ) and not Verdata.Exists( typ_anim, Id ) then begin
                exit;
        end;

        HueTyp := typ_anim;
        HueId := Id;

        PaintHueImage( Sender );
        Config.SetInteger( 'HueAnimId', HueId );
end;

procedure TMainForm.est1Click(Sender: TObject);
var     Id : Integer;
begin
        if not Art.Loaded then
                exit;
        Id := strtoint( InputBox( 'ID', 'Gebt eine ID an.', Format( '0x%x', [Config.GetInteger( 'HueArtId' )] ) ) );

        if not Art.StaticExists( Id ) and not Verdata.Exists( typ_art, Id+$4000 ) then begin
                exit;
        end;

        HueTyp := typ_art;
        HueId := Id;

        PaintHueImage( Sender );
        Config.SetInteger( 'HueArtId', HueId );
end;

procedure TMainForm.ShowGump1Click(Sender: TObject);
var     Id : Integer;
begin
        if not Gump.Loaded then
                exit;
        Id := strtoint( InputBox( 'ID', 'Gebt eine ID an.', Format( '0x%x', [Config.GetInteger( 'HueGumpId' )] ) ) );

        if not Gump.GumpExists( Id ) and not Verdata.Exists( typ_gumpart, Id+$4000 ) then begin
                exit;
        end;

        HueTyp := typ_gumpart;
        HueId := Id;

        PaintHueImage( Sender );
        Config.SetInteger( 'HueGumpId', HueId );
end;

procedure TMainForm.PaintHueImage( Sender : TObject );
var     Bitmap : TBitmap32;
        x, y : Integer;
        Index, ColorId : Integer;
        Color : TColor32;
        red : Byte;
begin
        if not Hues.loaded then
                exit;
        if lbHue.ItemIndex = -1 then
                exit;

        ColorId := strtoint( lbHue.Items[ lbHue.ItemIndex ] );

        if HueTyp = typ_anim then begin
                if Verdata.Exists( typ_anim, HueId ) then
                        Bitmap := Verdata.SaveFirstAnimPicture( HueId )
                else
                        Bitmap := Animation.SaveFirstPicture( HueId );

                for x := 0 to Bitmap.Width-1 do begin
                        for y := 0 to Bitmap.Height-1 do begin
                                Color := Bitmap.Pixel[ x, y ];
                                if Color <> 0 then begin
                                        red := Color shr 16;
                                        Index := red div 8;
                                        Color := Color15to32( Hues.GetColor( ColorId, Index ) );
                                        Bitmap.Pixel[ x, y ] := Color;
                                end;
                        end;
                end;
        end
        else if HueTyp = typ_art then begin
                if Verdata.Exists( typ_art, HueId ) then
                        Bitmap := Verdata.SaveStaticArt( HueId )
                else
                        Bitmap := Art.GetStaticTile( HueId );

                ColorId := strtoint( lbHue.Items[ lbHue.ItemIndex ] );
                for x := 0 to Bitmap.Width-1 do begin
                        for y := 0 to Bitmap.Height-1 do begin
                                Color := Bitmap.Pixel[ x, y ];
                                if Color <> 0 then begin
                                        red := Color shr 16;
                                        Index := red div 8;
                                        Color := Color15to32( Hues.GetColor( ColorId, Index ) );
                                        Bitmap.Pixel[ x, y ] := Color;
                                end;
                        end;
                end;
        end
        else if HueTyp = typ_gumpart then begin
                if Verdata.Exists( typ_gumpart, HueId ) then
                        Bitmap := Verdata.SaveGump( HueId )
                else
                        Bitmap := Gump.GetGump( HueId );

                ColorId := strtoint( lbHue.Items[ lbHue.ItemIndex ] );
                for x := 0 to Bitmap.Width-1 do begin
                        for y := 0 to Bitmap.Height-1 do begin
                                Color := Bitmap.Pixel[ x, y ];
                                if ( Color and $00FFFFFF ) <> 0 then begin
                                        red := Color shr 16;
                                        Index := red div 8;
                                        Color := Color15to32( Hues.GetColor( ColorId, Index ) );
                                        Bitmap.Pixel[ x, y ] := Color;
                                end;
                        end;
                end;
        end else
                exit;

        iHueImage.Bitmap.SetSize( 360, 360 );
        iHueImage.Bitmap.Clear( Color32( iHueImage.Color ) );

        iHueImage.Bitmap.Draw( 180 - ( Bitmap.Width div 2 ), 180 - ( Bitmap.Height div 2 ), Bitmap );
end;

procedure TMainForm.iHueMouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer; Layer: TCustomLayer);
var     Hoehe : Integer;
        ColorDialog : TColorDialog;
        ColorId : Integer;
begin
        Hoehe := (Y-1) div 11;
        if Button = mbRight then begin
                if not Hues.loaded then
                        exit;
                if lbHue.ItemIndex = -1 then
                        exit;

                ColorId := strtoint( lbHue.Items[ lbHue.ItemIndex ] );
                ColorDialog := TColorDialog.Create( nil );

                if not ColorDialog.Execute then begin
                        ColorDialog.Free;
                        exit;
                end;

                Hues.SetColor( ColorId, Hoehe, ColorDialog.Color );
        end else if Button = mbLeft then begin
                HueStart := Hoehe;
                HueEnd := Hoehe;
                HueDown := true;
        end;
        lbHueClick( Sender );
end;

procedure TMainForm.iHueMouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer; Layer: TCustomLayer);
var     Hoehe : Integer;
begin
        if not Hues.loaded then
                exit;
        if lbHue.ItemIndex = -1 then
                exit;
        if Button = mbLeft then begin
                Hoehe := (Y-1) div 11;
                HueStart := Min( HueStart, Hoehe );
                HueEnd := Max( HueEnd, Hoehe );
                lbHueClick( Sender );
                HueDown := false;
        end;
end;

procedure TMainForm.iHueMouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer; Layer: TCustomLayer);
var     Hoehe : Integer;
begin
        if not Hues.loaded then
                exit;
        if lbHue.ItemIndex = -1 then
                exit;
        if not HueDown then
                exit;
        Hoehe := (Y-1) div 11;
        if ( Hoehe <> HueStart ) and ( Hoehe <> HueEnd ) then begin
                HueStart := Min( HueStart, Hoehe );
                HueEnd := Max( HueEnd, Hoehe );
                lbHueClick( Sender );
        end;
end;

procedure TMainForm.btnHueSpreadClick(Sender: TObject);
var     Id : Integer;
begin
        if ( HueStart = -1 ) or ( HueEnd = -1 ) or ( lbHue.ItemIndex = -1 ) then
                exit;
        if abs( HueStart - HueEnd ) < 1 then
                exit;
        Id := strtoint( lbHue.Items[ lbHue.ItemIndex ] );
        Hues.Spread( HueStart, HueEnd, Id );
        lbHueClick( Sender );
end;

procedure TMainForm.lbHue2DrawItem(Control: TWinControl; Index: Integer;
  Rect: TRect; State: TOwnerDrawState);
var     Id : integer;
begin
        lbHue2.Canvas.Brush.Style := bsSolid;
        lbHue2.Canvas.Brush.Color := clWhite;

        if ( odselected in state ) then begin
                lbHue2.Canvas.Brush.Color := clNavy;
        end;
        lbHue2.Canvas.FillRect( rect );

        Id := strtoint( lbHue2.Items[ Index ] );

        lbHue2.Canvas.Font.Color := WinColor( Color15to32( Hues2.GetColor( Id, tbHue2.Position ) ) );

        lbHue2.Canvas.Brush.Style := bsClear;
        if ( odselected in state ) then begin
                lbHue2.Canvas.Font.Color := clWhite;
        end;

        lbHue2.Canvas.TextOut( 10, (-lbHue2.TopIndex+Index)*lbHue2.ItemHeight, lbHue2.Items[ Index ] );
end;

procedure TMainForm.lbHue2Click(Sender: TObject);
var     Id, i : Integer;
begin
        Id := strtoint( lbHue2.Items[ lbHue2.ItemIndex ] );
        iHue2.Bitmap.Width := 60;
        iHue2.Bitmap.Height := 353;
        iHue2.Bitmap.Clear( Color32( iHue2.Color ) );
        iHue2.Bitmap.FillRect( 0, 0, 60, 353, clBlack32 );
        for i := 0 to 31 do begin
                iHue2.Bitmap.FillRect( 1, 1+i*11, 59, 1+i*11+10, Color15to32( Hues2.GetColor( Id, i ) ) );
        end;
        eHue2Name.Text := Hues2.GetName( Id );
end;

procedure TMainForm.tbHue2Change(Sender: TObject);
begin
        lbHue2.Repaint;
end;

procedure TMainForm.btnHueLoadClick(Sender: TObject);
var     OpenDialog : TOpenDialog;
        i : Integer;
begin
        OpenDialog := TOpenDialog.Create( nil );
        OpenDialog.Filter := 'Hues.mul|Hues.mul';

        if not OpenDialog.Execute then begin
                OpenDialog.Free;
                exit;
        end;

        Hues2.Load( OpenDialog.FileName );
        lbHue2.Items.BeginUpdate;
        for i := 0 to Hues2.GetHueCount-1 do begin
                lbHue2.Items.Add( Format( '0x%x', [i] ) );
        end;
        lbHue2.Items.EndUpdate;
end;

procedure TMainForm.btnHueCopyClick(Sender: TObject);
var     Id, Id2, i : Integer;
begin
        if not Hues.loaded then
                exit;
        if lbHue.ItemIndex = -1 then
                exit;
        if not Hues2.loaded then
                exit;
        if lbHue2.ItemIndex = -1 then
                exit;
        Id := strtoint( lbHue.Items[ lbHue.ItemIndex ] );
        Id2 := strtoint( lbHue2.Items[ lbHue2.ItemIndex ] );

        for i := 0 to 31 do begin
                Hues.SetColor( Id, i, WinColor( Color15to32( Hues2.GetColor( Id2, i ) ) ) );
        end;
        lbHueClick( Sender );
end;

procedure TMainForm.eHueNameKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
var     Id : Integer;
begin
        if Key = VK_Return then begin
                if not Hues.loaded then
                        exit;
                if lbHue.ItemIndex = -1 then
                        exit;
                Id := strtoint( lbHue.Items[ lbHue.ItemIndex ] );
                Hues.SetName( Id, eHueName.Text );
        end;
end;

procedure TMainForm.LoadfromDirectorytoVerdata1Click(Sender: TObject);
var     LoadDialog : TrmBrowseForFolder;
        Id : integer;
        Liste : TStringList;
begin
        if not Verdata.loaded then exit;

        LoadDialog := TrmBrowseForFolder.create( nil );
        LoadDialog.Title := 'Woher soll die Animation geladen werden?';

        if not LoadDialog.Execute then begin
                LoadDialog.Free;
                exit;
        end;

        Liste := TStringList.Create;
        StrLib.Split( lbAnimations.Items[ lbAnimations.ItemIndex ], ' ', Liste );
        Id := strtoint( Liste.Strings[ 1 ] );
        Liste.Free;

        Verdata.LoadAnimFromDirectory( Id, LoadDialog.Folder, cbPalette.Checked );
        LoadDialog.Free;
        lbAnimationsClick( Sender );
end;

procedure TMainForm.LoadfromFiletoVerdata1Click(Sender: TObject);
var     OpenDialog : TOpenDialog;
        Id : integer;
        Liste : TStringList;
begin
        if not Verdata.loaded then exit;

        OpenDialog := TOpenDialog.Create( nil );
        OpenDialog.Filter := '*.vd|*.vd';

        if not OpenDialog.Execute then begin
                OpenDialog.Free;
                exit;
        end;

        Liste := TStringList.Create;
        StrLib.Split( lbAnimations.Items[ lbAnimations.ItemIndex ], ' ', Liste );
        Id := strtoint( Liste.Strings[ 1 ] );
        Liste.Free;

        Verdata.LoadAnimFromFile( Id, OpenDialog.FileName );
        lbAnimationsClick( Sender );
        OpenDialog.Free;
end;

procedure TMainForm.Copy1Click(Sender: TObject);
var     GumpId, TargetId, SourceId : Integer;
begin
        GumpId := strtoint( lbGumpAnim.Items[ lbGumpAnim.ItemIndex ] );

        SourceId := strtoint( InputBox( 'Source ID', 'Gib die ID der vorhandenen Animation an.', '0x0' ) );

        TargetId := GumpId - 50000;

        if ( ePathAnimIdx.Text = '' ) and not Animation.Loaded then
                exit;

        Animation.DupeAnim( SourceId, TargetId, ePathAnimIdx.Text );
end;

procedure TMainForm.btnBrowseLightIdxClick(Sender: TObject);
var     NewFile : String;
begin
        NewFile := BrowseFile( 'Lightidx.mul' );
        if NewFile <> '' then begin
                Config.SetString( 'LightIdx', Newfile );
                ePathLightIdx.Text := NewFile;
        end;
end;

procedure TMainForm.btnBrowseLightMulClick(Sender: TObject);
var     NewFile : String;
begin
        NewFile := BrowseFile( 'Light.mul' );
        if NewFile <> '' then begin
                Config.SetString( 'LightMul', Newfile );
                ePathLightMul.Text := NewFile;
        end;
end;

procedure TMainForm.btnLightSaveClick(Sender: TObject);
var     idxPath, mulPath : String;
begin
        idxPath := SaveFile( 'Lightidx.mul' );
        mulPath := SaveFile( 'Light.mul' );

        if ( idxPath <> '' ) and ( mulPath <> '' ) then begin
                Light.Save( idxPath, mulPath );
        end;
end;

procedure TMainForm.btnLightLoadClick(Sender: TObject);
begin
        InitLight( Sender );
end;

procedure TMainForm.InitLight( Sender : TObject );
var     i : Integer;
begin
        if ( ePathLightIdx.Text <> '' ) and ( ePathLightMul.Text <> '' ) then
                Light.Load( ePathLightIdx.Text, ePathLightMul.Text );

        lbLight.Clear;
        lbLight.Items.BeginUpdate;
        for i := 0 to Light.Count-1 do begin
                lbLight.Items.Add( Format( '%d', [i] ) );
        end;
        lbLight.Items.EndUpdate;
end;

procedure TMainForm.lbLightDrawItem(Control: TWinControl; Index: Integer;
  Rect: TRect; State: TOwnerDrawState);
var     Id : integer;
begin
        lbLight.Canvas.Brush.Style := bsSolid;
        lbLight.Canvas.Brush.Color := clWhite;

        if ( odselected in state ) then begin
                lbLight.Canvas.Brush.Color := clNavy;
        end;
        lbLight.Canvas.FillRect( rect );

        Id := strtoint( lbLight.Items[ Index ] );

        if Light.Exists( Id ) then
                lbLight.Canvas.Font.Color := clBlack
        else
                lbLight.Canvas.Font.Color := clRed;

        lbLight.Canvas.Brush.Style := bsClear;
        if ( odselected in state ) then begin
                lbLight.Canvas.Font.Color := clWhite;
        end;

        lbLight.Canvas.TextOut( 10, (-lbLight.TopIndex+Index)*lbLight.ItemHeight, lbLight.Items[ Index ] );
end;

procedure TMainForm.lbLightClick(Sender: TObject);
var     Bitmap : TBitmap32;
        Id : integer;
begin
        Id := strtoint( lbLight.Items[ lbLight.ItemIndex ] );

        if not Light.Exists( Id ) then begin
                iLight.Bitmap.SetSize( 630, 450 );
                iLight.Bitmap.Clear( Color32( iLight.Color ) );
                exit;
        end;

        Bitmap := Light.GetLight( Id );
        iLight.Bitmap.SetSize( 630, 450 );
        iLight.Bitmap.Clear( Color32( iLight.Color ) );

        iLight.Bitmap.Draw( 0, 0, Bitmap );
        Bitmap.Free;
end;

procedure TMainForm.lbLightContextPopup(Sender: TObject; MousePos: TPoint;
  var Handled: Boolean);
begin
        if lbLight.ItemIndex = -1 then
                exit;
        popLight.Popup( MousePos.X+MainForm.Left, MousePos.Y+MainForm.Top );
end;

procedure TMainForm.SavetoBitmap4Click(Sender: TObject);
var     SaveDialog : TSaveDialog;
        Id : Integer;
        Bitmap : TBitmap32;
begin
        Id := strtoint( lbLight.Items[ lbLight.ItemIndex ] );

        SaveDialog := TSaveDialog.Create( nil );
        SaveDialog.Filter := '*.bmp|*.bmp';
        SaveDialog.DefaultExt := 'bmp';
        SaveDialog.FileName := Format( '0x%x.bmp', [Id] );

        if not SaveDialog.Execute then begin
                SaveDialog.Free;
                exit;
        end;

        if not Light.Exists( Id ) then begin
                SaveDialog.Free;
                exit;
        end;

        Bitmap := Light.GetLight( Id );
        Bitmap.SaveToFile( SaveDialog.FileName );
        Bitmap.Free;
        SaveDialog.Free;
end;

procedure TMainForm.LoadfromBitmap4Click(Sender: TObject);
var     OpenDialog : TOpenDialog;
        Id : Integer;
begin
        OpenDialog := TOpenDialog.Create( nil );
        OpenDialog.Filter := '*.bmp|*.bmp';

        if not OpenDialog.Execute then begin
                OpenDialog.Free;
                exit;
        end;

        Id := strtoint( lbLight.Items[ lbLight.ItemIndex ] );
        Light.LoadLight( Id, OpenDialog.FileName );

        lbLightClick( Sender );
        OpenDialog.Free;
end;

procedure TMainForm.btnBrowseTiledataClick(Sender: TObject);
var     NewFile : String;
begin
        NewFile := BrowseFile( 'Tiledata.mul' );
        if NewFile <> '' then begin
                Config.SetString( 'Tiledata', Newfile );
                ePathTiledata.Text := NewFile;
        end;
end;


procedure TMainForm.btnTiledataLoadClick(Sender: TObject);
begin
        InitTiledata( Sender );
end;

procedure TMainForm.btnTiledataSaveClick(Sender: TObject);
var     Path : String;
begin
        Path := SaveFile( 'Tiledata.mul' );

        if ( Path <> '' ) then begin
                Tiledata.Save( Path );
        end;
end;

procedure TMainForm.InitTiledata( Sender : TObject );
var     i : Integer;
        Name : String;
begin
        TileChange := True;
        if ( ePathTiledata.Text <> '' ) then
                Tiledata.Load( ePathTiledata.Text );

        lbTiledataMap.Clear;
        lbTiledataMap.Items.BeginUpdate;
        for i:=0 to $FFFF do begin
                Name := Tiledata.GetLandName( i );
                lbTiledataMap.Items.Add( Format( '0x%x %s', [ i, Name ] ) );
        end;
        lbTiledataMap.Items.EndUpdate;

        lbTiledataStatic.Clear;
        lbTiledataStatic.Items.BeginUpdate;
        for i:=0 to Tiledata.GetStaticTileCount-1 do begin
                Name := Tiledata.GetStaticName( i );
                lbTiledataStatic.Items.Add( Format( '0x%x %s', [ i, Name ] ) );
        end;
        lbTiledataStatic.Items.EndUpdate;

        TileChange := False;
end;

procedure TMainForm.lbTiledataMapClick(Sender: TObject);
var     Id, TexId : Integer;
        Liste : TStringList;
        Bitmap : TBitmap32;
begin
        TileChange := True;
        Liste := TStringList.Create;
        StrLib.Split( lbTiledataMap.Items[ lbTiledataMap.ItemIndex ], ' ', Liste );
        Id := strtoint( Liste.Strings[ 0 ] );
        Liste.Free;

        eTMName.Text := Tiledata.GetLandName( Id );
        TexId := Tiledata.GetLandTexId( Id );
        eTMTexId.Text := Format( '0x%x', [ TexId ] );

        cbTMDamaging.Checked := Tiledata.GetLandFlag( Id, dDAMAGING );
        cbTMImpassable.Checked := Tiledata.GetLandFlag( Id, dIMPASSABLE );
        cbTMLiquid.Checked := Tiledata.GetLandFlag( Id, dLIQUID );
        cbTMWall.Checked := Tiledata.GetLandFlag( Id, dWALL );
        cbTMUnknown3.Checked := Tiledata.GetLandFlag( Id, dUNKNOWN3 );
        TileChange := False;

        if Art.loaded and Art.MapExists( Id ) then begin
                iTiledataMap.Bitmap.SetSize( 44, 44 );
                iTiledataMap.Bitmap.Clear( Color32( iTiledataMap.Color ) );
                Bitmap := Art.GetMapTile( Id );
                iTiledataMap.Bitmap.Draw( 0, 0, Bitmap );
        end;
end;

procedure TMainForm.SetTileMap( Sender : TObject );
var     LandTile : TLandTileRecord;
        Id : Integer;
        Liste : TStringList;
begin
        if lbTiledataMap.ItemIndex = -1 then
                exit;

        Liste := TStringList.Create;
        StrLib.Split( lbTiledataMap.Items[ lbTiledataMap.ItemIndex ], ' ', Liste );
        Id := strtoint( Liste.Strings[ 0 ] );
        Liste.Free;

        LandTile.Flags := 0;
        LandTile.Flags := LandTile.Flags + AddFlag( dDAMAGING, cbTMDamaging.Checked );
        LandTile.Flags := LandTile.Flags + AddFlag( dIMPASSABLE, cbTMImpassable.Checked );
        LandTile.Flags := LandTile.Flags + AddFlag( dLIQUID, cbTMLiquid.Checked );
        LandTile.Flags := LandTile.Flags + AddFlag( dWALL, cbTMWall.Checked );
        LandTile.Flags := LandTile.Flags + AddFlag( dUNKNOWN3, cbTMUnknown3.Checked );

        StrPCopy( LandTile.Name, eTMName.Text );
        LandTile.TexID := strtoint( eTMTexId.Text );
        Tiledata.SetLandTile( Id, LandTile );

        lbTiledataMap.Items[ lbTiledataMap.ItemIndex ] := Format( '0x%x %s', [ Id, eTMName.Text ] );
        lbTiledataMapClick( Sender );
end;

function TMainForm.AddFlag( Flag : Integer; Checked : Boolean ) : Integer;
begin
        if Checked then
                Result := Flag
        else
                Result := 0;
end;

procedure TMainForm.eTMNameChange(Sender: TObject);
begin
        if not TileChange then SetTileMap( Sender );
end;

procedure TMainForm.eTMTexIdChange(Sender: TObject);
begin
        if not TileChange then SetTileMap( Sender );
end;

procedure TMainForm.cbTMDamagingClick(Sender: TObject);
begin
        if not TileChange then SetTileMap( Sender );
end;

procedure TMainForm.cbTMLiquidClick(Sender: TObject);
begin
        if not TileChange then SetTileMap( Sender );
end;

procedure TMainForm.cbTMImpassableClick(Sender: TObject);
begin
        if not TileChange then SetTileMap( Sender );
end;

procedure TMainForm.cbTMWallClick(Sender: TObject);
begin
        if not TileChange then SetTileMap( Sender );
end;

procedure TMainForm.cbTMUnknown3Click(Sender: TObject);
begin
        if not TileChange then SetTileMap( Sender );
end;

procedure TMainForm.btnTMSaveClick(Sender: TObject);
var     SaveDialog : TSaveDialog;
begin
        if not Tiledata.Loaded then exit;

        SaveDialog := TSaveDialog.Create( nil );
        SaveDialog.Filter := '*.txt|*.txt';
        SaveDialog.DefaultExt := 'txt';
        SaveDialog.FileName := 'TileMap.txt';

        if not SaveDialog.Execute then begin
                SaveDialog.Free;
                exit;
        end;

        Tiledata.SaveMapToFile( SaveDialog.FileName );
        SaveDialog.Free;
end;

procedure TMainForm.btnTMLoadClick(Sender: TObject);
var     OpenDialog : TOpenDialog;
        i : Integer;
        Name : String;
begin
        if not Tiledata.Loaded then exit;

        OpenDialog := TOpenDialog.Create( nil );
        OpenDialog.Filter := '*.txt|*.txt';

        if not OpenDialog.Execute then begin
                OpenDialog.Free;
                exit;
        end;

        if not FileExists( OpenDialog.FileName ) then begin
                OpenDialog.Free;
                exit;
        end;

        Tiledata.LoadMapFromFile( OpenDialog.FileName );
        OpenDialog.Free;

        TileChange := True;
        lbTiledataMap.Clear;
        lbTiledataMap.Items.BeginUpdate;
        for i:=0 to $FFFF do begin
                Name := Tiledata.GetLandName( i );
                lbTiledataMap.Items.Add( Format( '0x%x %s', [ i, Name ] ) );
        end;
        lbTiledataMap.Items.EndUpdate;

        TileChange := False;
end;

procedure TMainForm.lbTiledataStaticClick(Sender: TObject);
var     Id, ArtId : Integer;
        Liste : TStringList;
        Bitmap : TBitmap32;
begin
        TileChange := True;
        Liste := TStringList.Create;
        StrLib.Split( lbTiledataStatic.Items[ lbTiledataStatic.ItemIndex ], ' ', Liste );
        Id := strtoint( Liste.Strings[ 0 ] );
        Liste.Free;

        eTSName.Text := Tiledata.GetStaticName( Id );
        eTSAnimId.Text := Format( '0x%x', [ Tiledata.GetStaticAnimId( Id ) ] );
        eTSHeight.Text := inttostr( Tiledata.GetStaticHeight( Id ) );
        eTSHue.Text := inttostr( Tiledata.GetStaticHue( Id ) );
        eTSQuality.Text := inttostr( Tiledata.GetStaticQuality( Id ) );
        eTSQuantity.Text := inttostr( Tiledata.GetStaticQuantity( Id ) );
        eTSWeight.Text := inttostr( Tiledata.GetStaticWeight( Id ) );

        eTSUnknown1.Text := inttostr( Tiledata.GetStaticUnknown1( Id ) );
        eTSUnknown2.Text := inttostr( Tiledata.GetStaticUnknown2( Id ) );
        eTSUnknown3.Text := inttostr( Tiledata.GetStaticUnknown3( Id ) );
        eTSUnknown4.Text := inttostr( Tiledata.GetStaticUnknown4( Id ) );
        eTSUnknown5.Text := inttostr( Tiledata.GetStaticUnknown5( Id ) );

        cbTSBackground.Checked := Tiledata.GetStaticFlag( Id, dBACKGROUND );
        cbTSWeapon.Checked := Tiledata.GetStaticFlag( Id, dWEAPON );
        cbTSTransparent.Checked := Tiledata.GetStaticFlag( Id, dTRANSPARENT );
        cbTSTranslucent.Checked := Tiledata.GetStaticFlag( Id, dTRANSLUCENT );
        cbTSWall.Checked := Tiledata.GetStaticFlag( Id, dWALL );
        cbTSDamaging.Checked := Tiledata.GetStaticFlag( Id, dDAMAGING );
        cbTSImpassable.Checked := Tiledata.GetStaticFlag( Id, dIMPASSABLE );
        cbTSLiquid.Checked := Tiledata.GetStaticFlag( Id, dLIQUID );

        cbTSUnknown1.Checked := Tiledata.GetStaticFlag( Id, dUNKNOWN1 );
        cbTSSurface.Checked := Tiledata.GetStaticFlag( Id, dSURFACE );
        cbTSBridge.Checked := Tiledata.GetStaticFlag( Id, dBRIDGE );
        cbTSGeneric.Checked := Tiledata.GetStaticFlag( Id, dGENERIC );
        cbTSWindow.Checked := Tiledata.GetStaticFlag( Id, dWINDOW );
        cbTSNoshoot.Checked := Tiledata.GetStaticFlag( Id, dNOSHOOT );
        cbTSA.Checked := Tiledata.GetStaticFlag( Id, dA );
        cbTSAn.Checked := Tiledata.GetStaticFlag( Id, dAN );

        cbTSMongen.Checked := Tiledata.GetStaticFlag( Id, dMONGEN );
        cbTSFoliage.Checked := Tiledata.GetStaticFlag( Id, dFOLIAGE );
        cbTSPartialhue.Checked := Tiledata.GetStaticFlag( Id, dPARTIALHUE );
        cbTSUnknown2.Checked := Tiledata.GetStaticFlag( Id, dUNKNOWN2 );
        cbTSMap.Checked := Tiledata.GetStaticFlag( Id, dMAP );
        cbTSContainer.Checked := Tiledata.GetStaticFlag( Id, dCONTAINER );
        cbTSWearable.Checked := Tiledata.GetStaticFlag( Id, dWEARABLE );
        cbTSLightsource.Checked := Tiledata.GetStaticFlag( Id, dLIGHTSOURCE );

        cbTSAnimation.Checked := Tiledata.GetStaticFlag( Id, dANIMATION );
        cbTSNodiagonal.Checked := Tiledata.GetStaticFlag( Id, dNODIAGONAL );
        cbTSUnknown3.Checked := Tiledata.GetStaticFlag( Id, dUNKNOWN3 );
        cbTSArmor.Checked := Tiledata.GetStaticFlag( Id, dARMOR );
        cbTSRoof.Checked := Tiledata.GetStaticFlag( Id, dROOF );
        cbTSDoor.Checked := Tiledata.GetStaticFlag( Id, dDOOR );
        cbTSStairback.Checked := Tiledata.GetStaticFlag( Id, dSTAIRBACK );
        cbTSStairright.Checked := Tiledata.GetStaticFlag( Id, dSTAIRRIGHT );

        TileChange := False;

        ArtId := Id;
        if ( Art.loaded and Art.StaticExists( ArtId ) ) or ( Verdata.Exists( typ_art, Id+$4000 ) ) then begin
                iTiledataStatic.Bitmap.SetSize( 150, 150 );
                iTiledataStatic.Bitmap.Clear( Color32( iTiledataStatic.Color ) );
                if Verdata.Exists( typ_art, Id+$4000 ) then
                        Bitmap := Verdata.SaveStaticArt( ArtId )
                else
                        Bitmap := Art.GetStaticTile( ArtId );
                iTiledataStatic.Bitmap.Draw( ( 150 - Bitmap.Width ) div 2, ( 150 - Bitmap.Height ) div 2, Bitmap );
        end;

        if Animation.Loaded then begin
                if Tiledata.GetStaticAnimId( Id ) <> 0 then begin
                        if Animation.AnimExists( Tiledata.GetStaticAnimId( Id ) ) then begin
                                Label5.Caption := 'Anim exists';
                        end
                        else begin
                                Label5.Caption := 'Anim does not exist';
                        end;
                end
                else begin
                        Label5.Caption := '';
                end
        end
        else begin
                Label5.Caption := '';
        end;
end;

procedure TMainForm.SetTileStatic( Sender : TObject );
var     StaticTile : TStaticTileRecord;
        Id : Integer;
        Liste : TStringList;
begin
        if lbTiledataStatic.ItemIndex = -1 then
                exit;

        Liste := TStringList.Create;
        StrLib.Split( lbTiledataStatic.Items[ lbTiledataStatic.ItemIndex ], ' ', Liste );
        Id := strtoint( Liste.Strings[ 0 ] );
        Liste.Free;

        StaticTile.Flags := 0;
        StaticTile.Flags := StaticTile.Flags + AddFlag( dBACKGROUND, cbTSBackground.Checked );
        StaticTile.Flags := StaticTile.Flags + AddFlag( dWEAPON, cbTSWeapon.Checked );
        StaticTile.Flags := StaticTile.Flags + AddFlag( dTRANSPARENT, cbTSTransparent.Checked );
        StaticTile.Flags := StaticTile.Flags + AddFlag( dTRANSLUCENT, cbTSTranslucent.Checked );
        StaticTile.Flags := StaticTile.Flags + AddFlag( dWALL, cbTSWall.Checked );
        StaticTile.Flags := StaticTile.Flags + AddFlag( dDAMAGING, cbTSDamaging.Checked );
        StaticTile.Flags := StaticTile.Flags + AddFlag( dIMPASSABLE, cbTSImpassable.Checked );
        StaticTile.Flags := StaticTile.Flags + AddFlag( dLIQUID, cbTSLiquid.Checked );

        StaticTile.Flags := StaticTile.Flags + AddFlag( dUNKNOWN1, cbTSUnknown1.Checked );
        StaticTile.Flags := StaticTile.Flags + AddFlag( dSURFACE, cbTSSurface.Checked );
        StaticTile.Flags := StaticTile.Flags + AddFlag( dBRIDGE, cbTSBridge.Checked );
        StaticTile.Flags := StaticTile.Flags + AddFlag( dGENERIC, cbTSGeneric.Checked );
        StaticTile.Flags := StaticTile.Flags + AddFlag( dWINDOW, cbTSWindow.Checked );
        StaticTile.Flags := StaticTile.Flags + AddFlag( dNOSHOOT, cbTSNoshoot.Checked );
        StaticTile.Flags := StaticTile.Flags + AddFlag( dA, cbTSA.Checked );
        StaticTile.Flags := StaticTile.Flags + AddFlag( dAN, cbTSAn.Checked );

        StaticTile.Flags := StaticTile.Flags + AddFlag( dMONGEN, cbTSMongen.Checked );
        StaticTile.Flags := StaticTile.Flags + AddFlag( dFOLIAGE, cbTSFoliage.Checked );
        StaticTile.Flags := StaticTile.Flags + AddFlag( dPARTIALHUE, cbTSPartialhue.Checked );
        StaticTile.Flags := StaticTile.Flags + AddFlag( dUNKNOWN2, cbTSUnknown2.Checked );
        StaticTile.Flags := StaticTile.Flags + AddFlag( dMAP, cbTSMap.Checked );
        StaticTile.Flags := StaticTile.Flags + AddFlag( dCONTAINER, cbTSContainer.Checked );
        StaticTile.Flags := StaticTile.Flags + AddFlag( dWEARABLE, cbTSWearable.Checked );
        StaticTile.Flags := StaticTile.Flags + AddFlag( dLIGHTSOURCE, cbTSLightsource.Checked );

        StaticTile.Flags := StaticTile.Flags + AddFlag( dANIMATION, cbTSAnimation.Checked );
        StaticTile.Flags := StaticTile.Flags + AddFlag( dNODIAGONAL, cbTSNodiagonal.Checked );
        StaticTile.Flags := StaticTile.Flags + AddFlag( dUNKNOWN3, cbTSUnknown3.Checked );
        StaticTile.Flags := StaticTile.Flags + AddFlag( dARMOR, cbTSArmor.Checked );
        StaticTile.Flags := StaticTile.Flags + AddFlag( dROOF, cbTSRoof.Checked );
        StaticTile.Flags := StaticTile.Flags + AddFlag( dDOOR, cbTSDoor.Checked );
        StaticTile.Flags := StaticTile.Flags + AddFlag( dSTAIRBACK, cbTSStairback.Checked );
        StaticTile.Flags := StaticTile.Flags + AddFlag( dSTAIRRIGHT, cbTSStairright.Checked );

        StrPCopy( StaticTile.Name, eTSName.Text );
        try
                StaticTile.Height := strtoint( eTSHeight.Text );
        except
                Statictile.Height := 0;
        end;
        try
                StaticTile.AnimID := strtoint( eTSAnimId.Text );
        except
                StaticTile.AnimID := 0;
        end;
        try
                StaticTile.Weight := strtoint( eTSWeight.Text );
        except
                StaticTile.Weight := 0;
        end;
        try
                StaticTile.Hue := strtoint( eTSHue.Text );
        except
                StaticTile.Hue := 0;
        end;
        try
                StaticTile.Quality := strtoint( eTSQuality.Text );
        except
                StaticTile.Quality := 0;
        end;
        try
                StaticTile.Quantity := strtoint( eTSQuantity.Text );
        except
                StaticTile.Quantity := 0;
        end;
        try
                StaticTile.Unknown1 := strtoint( eTSUnknown1.Text );
        except
                StaticTile.Unknown1 := 0;
        end;
        try
                StaticTile.Unknown2 := strtoint( eTSUnknown2.Text );
        except
                StaticTile.Unknown2 := 0;
        end;
        try
                StaticTile.Unknown3 := strtoint( eTSUnknown3.Text );
        except
                StaticTile.Unknown3 := 0;
        end;
        try
                StaticTile.Unknown4 := strtoint( eTSUnknown4.Text );
        except
                StaticTile.Unknown4 := 0;
        end;
        try
                StaticTile.Unknown5 := strtoint( eTSUnknown5.Text );
        except
                StaticTile.Unknown5 := 0;
        end;
        Tiledata.SetStaticTile( Id, StaticTile );

        lbTiledataStatic.Items[ lbTiledataStatic.ItemIndex ] := Format( '0x%x %s', [ Id, eTSName.Text ] );
        lbTiledataStaticClick( Sender );
end;

procedure TMainForm.eTSNameChange(Sender: TObject);
begin
        if not TileChange then SetTileStatic( Sender );
end;

procedure TMainForm.eTSAnimIdChange(Sender: TObject);
begin
        if not TileChange then SetTileStatic( Sender );
end;

procedure TMainForm.eTSWeightChange(Sender: TObject);
begin
        if not TileChange then SetTileStatic( Sender );
end;

procedure TMainForm.eTSHeightChange(Sender: TObject);
begin
        if not TileChange then SetTileStatic( Sender );
end;

procedure TMainForm.eTSQualityChange(Sender: TObject);
begin
        if not TileChange then SetTileStatic( Sender );
end;

procedure TMainForm.eTSQuantityChange(Sender: TObject);
begin
        if not TileChange then SetTileStatic( Sender );
end;

procedure TMainForm.eTSHueChange(Sender: TObject);
begin
        if not TileChange then SetTileStatic( Sender );
end;

procedure TMainForm.eTSUnknown1Change(Sender: TObject);
begin
        if not TileChange then SetTileStatic( Sender );
end;

procedure TMainForm.eTSUnknown2Change(Sender: TObject);
begin
        if not TileChange then SetTileStatic( Sender );
end;

procedure TMainForm.eTSUnknown3Change(Sender: TObject);
begin
        if not TileChange then SetTileStatic( Sender );
end;

procedure TMainForm.eTSUnknown4Change(Sender: TObject);
begin
        if not TileChange then SetTileStatic( Sender );
end;

procedure TMainForm.eTSUnknown5Change(Sender: TObject);
begin
        if not TileChange then SetTileStatic( Sender );
end;

procedure TMainForm.cbTSBackgroundClick(Sender: TObject);
begin
        if not TileChange then SetTileStatic( Sender );
end;

procedure TMainForm.cbTSWeaponClick(Sender: TObject);
begin
        if not TileChange then SetTileStatic( Sender );
end;

procedure TMainForm.cbTSTransparentClick(Sender: TObject);
begin
        if not TileChange then SetTileStatic( Sender );
end;

procedure TMainForm.cbTSTranslucentClick(Sender: TObject);
begin
        if not TileChange then SetTileStatic( Sender );
end;

procedure TMainForm.cbTSWallClick(Sender: TObject);
begin
        if not TileChange then SetTileStatic( Sender );
end;

procedure TMainForm.cbTSDamagingClick(Sender: TObject);
begin
        if not TileChange then SetTileStatic( Sender );
end;

procedure TMainForm.cbTSImpassableClick(Sender: TObject);
begin
        if not TileChange then SetTileStatic( Sender );
end;

procedure TMainForm.cbTSLiquidClick(Sender: TObject);
begin
        if not TileChange then SetTileStatic( Sender );
end;

procedure TMainForm.cbTSUnknown1Click(Sender: TObject);
begin
        if not TileChange then SetTileStatic( Sender );
end;

procedure TMainForm.cbTSSurfaceClick(Sender: TObject);
begin
        if not TileChange then SetTileStatic( Sender );
end;

procedure TMainForm.cbTSBridgeClick(Sender: TObject);
begin
        if not TileChange then SetTileStatic( Sender );
end;

procedure TMainForm.cbTSGenericClick(Sender: TObject);
begin
        if not TileChange then SetTileStatic( Sender );
end;

procedure TMainForm.cbTSWindowClick(Sender: TObject);
begin
        if not TileChange then SetTileStatic( Sender );
end;

procedure TMainForm.cbTSNoshootClick(Sender: TObject);
begin
        if not TileChange then SetTileStatic( Sender );
end;

procedure TMainForm.cbTSAClick(Sender: TObject);
begin
        if not TileChange then SetTileStatic( Sender );
end;

procedure TMainForm.cbTSAnClick(Sender: TObject);
begin
        if not TileChange then SetTileStatic( Sender );
end;

procedure TMainForm.cbTSMongenClick(Sender: TObject);
begin
        if not TileChange then SetTileStatic( Sender );
end;

procedure TMainForm.cbTSFoliageClick(Sender: TObject);
begin
        if not TileChange then SetTileStatic( Sender );
end;

procedure TMainForm.cbTSPartialhueClick(Sender: TObject);
begin
        if not TileChange then SetTileStatic( Sender );
end;

procedure TMainForm.cbTSUnknown2Click(Sender: TObject);
begin
        if not TileChange then SetTileStatic( Sender );
end;

procedure TMainForm.cbTSMapClick(Sender: TObject);
begin
        if not TileChange then SetTileStatic( Sender );
end;

procedure TMainForm.cBTSContainerClick(Sender: TObject);
begin
        if not TileChange then SetTileStatic( Sender );
end;

procedure TMainForm.cbTSWearableClick(Sender: TObject);
begin
        if not TileChange then SetTileStatic( Sender );
end;

procedure TMainForm.cbTSLightsourceClick(Sender: TObject);
begin
        if not TileChange then SetTileStatic( Sender );
end;

procedure TMainForm.cbTSAnimationClick(Sender: TObject);
begin
        if not TileChange then SetTileStatic( Sender );
end;

procedure TMainForm.cbTSNodiagonalClick(Sender: TObject);
begin
        if not TileChange then SetTileStatic( Sender );
end;

procedure TMainForm.cbTSUnknown3Click(Sender: TObject);
begin
        if not TileChange then SetTileStatic( Sender );
end;

procedure TMainForm.cbTSArmorClick(Sender: TObject);
begin
        if not TileChange then SetTileStatic( Sender );
end;

procedure TMainForm.cbTSRoofClick(Sender: TObject);
begin
        if not TileChange then SetTileStatic( Sender );
end;

procedure TMainForm.cbTSDoorClick(Sender: TObject);
begin
        if not TileChange then SetTileStatic( Sender );
end;

procedure TMainForm.cbTSStairbackClick(Sender: TObject);
begin
        if not TileChange then SetTileStatic( Sender );
end;

procedure TMainForm.cbTSStairrightClick(Sender: TObject);
begin
        if not TileChange then SetTileStatic( Sender );
end;

procedure TMainForm.btnTSSaveClick(Sender: TObject);
var     SaveDialog : TSaveDialog;
begin
        if not Tiledata.Loaded then exit;

        SaveDialog := TSaveDialog.Create( nil );
        SaveDialog.Filter := '*.txt|*.txt';
        SaveDialog.DefaultExt := 'txt';
        SaveDialog.FileName := 'StaticTiles';

        if not SaveDialog.Execute then begin
                SaveDialog.Free;
                exit;
        end;

        Tiledata.SaveStaticToFile( SaveDialog.FileName );
        SaveDialog.Free;
end;

procedure TMainForm.btnTSLoadClick(Sender: TObject);
var     OpenDialog : TOpenDialog;
        i : Integer;
        Name : String;
begin
        if not Tiledata.Loaded then exit;

        OpenDialog := TOpenDialog.Create( nil );
        OpenDialog.Filter := '*.txt|*.txt';

        if not OpenDialog.Execute then begin
                OpenDialog.Free;
                exit;
        end;

        if not FileExists( OpenDialog.FileName ) then begin
                OpenDialog.Free;
                exit;
        end;

        Tiledata.LoadStaticFromFile( OpenDialog.FileName );
        OpenDialog.Free;

        TileChange := True;
        lbTiledataStatic.Items.BeginUpdate;
        lbTiledataStatic.Clear;
        for i:=0 to $FFFF do begin
                Name := Tiledata.GetStaticName( i );
                lbTiledataStatic.Items.Add( Format( '0x%x %s', [ i, Name ] ) );
        end;
        lbTiledataStatic.Items.EndUpdate;

        TileChange := False;
end;

procedure TMainForm.btnArtStaticExtractHolesClick(Sender: TObject);
var     Id : Integer;
        Datei : TextFile;
        Loch : Boolean;
        SaveDialog : TSaveDialog;
        Anfang : Integer;
begin
        if not Art.loaded then exit;
        Loch := False;
        Anfang := 0;

        SaveDialog := TSaveDialog.Create( nil );
        SaveDialog.Filter := '*.txt|*.txt';
        SaveDialog.DefaultExt := 'txt';
        SaveDialog.FileName := 'Holes.txt';

        if not SaveDialog.Execute then begin
                SaveDialog.Free;
                exit;
        end;

        if FileExists( SaveDialog.FileName ) then
                DeleteFile( SaveDialog.FileName );

        AssignFile( Datei, SaveDialog.FileName );
        ReWrite( Datei );
        SaveDialog.Free;

        for Id := 0 to Art.GetStaticCount-1 do begin
                if Art.StaticExists( Id ) then begin
                        if Loch then begin
                                Writeln( Datei, Format( 'Anfang: 0x%x', [Anfang] ) );
                                Writeln( Datei, Format( 'Ende: 0x%x', [Id-1] ) );
                                Writeln( Datei, 'Grösse: ' + inttostr( Id-Anfang ) );
                                Loch := False;
                        end;
                end
                else begin
                        if not Loch then begin
                                Anfang := Id;
                                Loch := True;
                        end;
                end;
        end;

        CloseFile( Datei );
end;

procedure TMainForm.Button10Click(Sender: TObject);
var     Id : Integer;
        Datei : TextFile;
        SaveDialog : TSaveDialog;
begin
        if not Art.loaded then exit;

        SaveDialog := TSaveDialog.Create( nil );
        SaveDialog.Filter := '*.txt|*.txt';
        SaveDialog.DefaultExt := 'txt';
        SaveDialog.FileName := 'EmptyIDs.txt';

        if not SaveDialog.Execute then begin
                SaveDialog.Free;
                exit;
        end;

        if FileExists( SaveDialog.FileName ) then
                DeleteFile( SaveDialog.FileName );

        AssignFile( Datei, SaveDialog.FileName );
        ReWrite( Datei );
        SaveDialog.Free;

        for Id := 0 to Art.GetStaticCount-1 do begin
                if not Art.StaticExists( Id ) then begin
                        Writeln( Datei, Format( '0x%x', [Id] ) );
                end;
        end;

        CloseFile( Datei );
end;

procedure TMainForm.btnBrowseAutopatchClick(Sender: TObject);
var     NewFile : String;
begin
        NewFile := BrowseFile( '*.txt' );
        if NewFile <> '' then begin
                ePathAutopatch.Text := NewFile;
        end;
end;

procedure TMainForm.btnAutopatchStartClick(Sender: TObject);
var     Datei : Textfile;
        Zeile, Path : String;
        Id, k : Integer;
        Liste : TStringList;
        fromFile, usePalette : Boolean;
        P : Integer;
begin
        if ePathAutopatch.Text = '' then exit;
        if cbAutopatch.ItemIndex = -1 then exit;

        AssignFile( Datei, ePathAutopatch.Text );
        Reset( Datei );
        k := 0;

        //Animations
        if cbAutopatch.ItemIndex = 0 then begin
                if not Animation.Loaded then begin
                        CloseFile( Datei );
                        showmessage( 'Muls not loaded.' );
                        exit;
                end;
                GaugeForm.Activate;
                while not Eof( Datei ) do begin
                        GaugeForm.SetBalken( trunc( 100*FilePos( Datei ) / FileSize( Datei ) ) );
                        Readln( Datei, Zeile );
                        Liste := TStringlist.Create;
                        StrLib.Split( Zeile, ' ', Liste );
                        Id := strtoint( Liste.Strings[0] );
                        Path := Liste.Strings[1];

                        if Liste.Count > 2 then
                                fromFile := Liste.Strings[2] = '1'
                        else
                                fromFile := true;

                        if Liste.Count > 3 then
                                usePalette := Liste.Strings[3] = '1'
                        else
                                usePalette := true;

                        if fromFile then begin
                                Animation.LoadAnimFromFile( Id, Path );
                        end
                        else begin
                                Animation.LoadAnimFromDirectory( Id, Path, usePalette );
                        end;

                        Liste.Free;
                        inc( k );
                end;
                showmessage( Format( '%d Animations patched.', [k] ) );
                GaugeForm.Deactivate;
                CloseFile( Datei );
        end
        //Art Map
        else if cbAutopatch.ItemIndex = 1 then begin
                if not Art.loaded then begin
                        CloseFile( Datei );
                        showmessage( 'Muls not loaded.' );
                        exit;
                end;
                GaugeForm.Activate;
                while not Eof( Datei ) do begin
                        GaugeForm.SetBalken( trunc( 100*FilePos( Datei ) / FileSize( Datei ) ) );
                        Readln( Datei, Zeile );
                        P := Pos( ' ', Zeile );
                        Id := StrToInt( Copy( Zeile, 1, P-1 ) );
                        Path := Copy( Zeile, P+1, Length( Zeile )-P );

                        if (Path = 'remove') or (Path = 'delete') then
                                Art.DeleteMap( Id )
                        else
                                Art.LoadMapTile( Id, Path );
                        inc( k );
                end;
                showmessage( Format( '%d Arttiles patched.', [k] ) );
                GaugeForm.Deactivate;
                CloseFile( Datei );
        end
        //Art Static
        else if cbAutopatch.ItemIndex = 2 then begin
                if not Art.loaded then begin
                        CloseFile( Datei );
                        showmessage( 'Muls not loaded.' );
                        exit;
                end;
                GaugeForm.Activate;
                while not Eof( Datei ) do begin
                        GaugeForm.SetBalken( trunc( 100*FilePos( Datei ) / FileSize( Datei ) ) );
                        Readln( Datei, Zeile );
                        P := Pos( ' ', Zeile );
                        Id := StrToInt( Copy( Zeile, 1, P-1 ) );
                        Path := Copy( Zeile, P+1, Length( Zeile )-P );

                        if (Path = 'remove') or (Path = 'delete') then
                                Art.DeleteStatic( Id )
                        else
                                Art.LoadStaticTile( Id, Path );
                        inc( k );
                        Application.ProcessMessages;
                end;
                showmessage( Format( '%d Arttiles patched.', [k] ) );
                GaugeForm.Deactivate;
                CloseFile( Datei );
        end
        //Gumps
        else if cbAutopatch.ItemIndex = 3 then begin
                if not Gump.loaded then begin
                        CloseFile( Datei );
                        showmessage( 'Muls not loaded.' );
                        exit;
                end;
                GaugeForm.Activate;
                while not Eof( Datei ) do begin
                        GaugeForm.SetBalken( trunc( 100*FilePos( Datei ) / FileSize( Datei ) ) );
                        Readln( Datei, Zeile );
                        P := Pos( ' ', Zeile );
                        Id := StrToInt( Copy( Zeile, 1, P-1 ) );
                        Path := Copy( Zeile, P+1, Length( Zeile )-P );

                        if (Path = 'remove') or (Path = 'delete') then
                                Gump.Delete( Id )
                        else
                                Gump.LoadGump( Id, Path );
                        inc( k );
                end;
                showmessage( Format( '%d Gumps patched.', [k] ) );
                GaugeForm.Deactivate;
                CloseFile( Datei );
        end
        //Texturen
        else if cbAutopatch.ItemIndex = 4 then begin
                if not Textures.loaded then begin
                        CloseFile( Datei );
                        showmessage( 'Muls not loaded.' );
                        exit;
                end;
                GaugeForm.Activate;
                while not Eof( Datei ) do begin
                        GaugeForm.SetBalken( trunc( 100*FilePos( Datei ) / FileSize( Datei ) ) );
                        Readln( Datei, Zeile );
                        P := Pos( ' ', Zeile );
                        Id := StrToInt( Copy( Zeile, 1, P-1 ) );
                        Path := Copy( Zeile, P+1, Length( Zeile )-P );

                        if (Path = 'remove') or (Path = 'delete') then
                                Textures.Delete( Id )
                        else
                                Textures.LoadTex( Id, Path );
                        inc( k );
                end;
                GaugeForm.Deactivate;
                showmessage( Format( '%d Textures patched.', [k] ) );
                CloseFile( Datei );
        end;
end;

procedure TMainForm.btnExtractStartClick(Sender: TObject);
var     Path, Nummer : String;
        Bitmap : TBitmap32;
        Id : Integer;
        Liste : TStringList;
begin
        if cbExtract.ItemIndex = -1 then exit;

        //Art Map
        if cbExtract.ItemIndex = 0 then begin
                if not Art.loaded then exit;
                Liste := TStringList.Create;

                Path := ExtractFilePath( Application.ExeName ) + 'Artmap';
                if not DirectoryExists( Path ) then
                        CreateDir( Path );
                Path := Path + '\';

                GaugeForm.Activate;
                for Id := 0 to $FFFF do begin
                        GaugeForm.SetBalken( trunc( Id*100/$FFFF ) );
                        if Art.MapExists( Id ) then begin
                                Bitmap := Art.GetMapTile( Id );
                                Nummer := FormatId( Id, false );
                                Bitmap.SaveToFile( Path + Nummer + '.bmp' );
                                Bitmap.Free;

                                Liste.Add( Nummer + ' ' + Nummer + '.bmp' );
                        end;
                end;
                GaugeForm.Deactivate;
                Liste.SaveToFile( Path + 'list.txt' );
                Liste.Free;
        end
        //Art Static
        else if cbExtract.ItemIndex = 1 then begin
                if not Art.loaded then exit;
                Liste := TStringList.Create;

                Path := ExtractFilePath( Application.ExeName ) + 'Artstatic';
                if not DirectoryExists( Path ) then
                        CreateDir( Path );
                Path := Path + '\';

                GaugeForm.Activate;
                for Id := 0 to $FFFF do begin
                        GaugeForm.SetBalken( trunc( Id*100/$FFFF ) );
                        if Art.StaticExists( Id ) then begin
                                Bitmap := Art.GetStaticTile( Id );
                                Nummer := Format( '%x', [Id] );//FormatId( Id, false );
                                Bitmap.SaveToFile( Path + Nummer + '.bmp' );
                                Bitmap.Free;

                                Liste.Add( Nummer + ' ' + Nummer + '.bmp' );
                        end;
                end;
                GaugeForm.Deactivate;
                Liste.SaveToFile( Path + 'list.txt' );
                Liste.Free;
        end
        //Gumps
        else if cbExtract.ItemIndex = 2 then begin
                if not Gump.loaded then exit;
                Liste := TStringList.Create;

                Path := ExtractFilePath( Application.ExeName ) + 'Gumps';
                if not DirectoryExists( Path ) then
                        CreateDir( Path );
                Path := Path + '\';

                GaugeForm.Activate;
                for Id := 0 to $EEFF do begin
                        GaugeForm.SetBalken( trunc( Id*100/$EEFF ) );
                        if Gump.GumpExists( Id ) then begin
                                Bitmap := Gump.GetGump( Id );
                                Nummer := FormatId( Id, false );
                                Bitmap.SaveToFile( Path + Nummer + '.bmp' );
                                Bitmap.Free;

                                Liste.Add( Nummer + ' ' + Nummer + '.bmp' );
                        end;
                end;
                GaugeForm.Deactivate;
                Liste.SaveToFile( Path + 'list.txt' );
                Liste.Free;
        end
        //Texturen
        else if cbExtract.ItemIndex = 3 then begin
                if not Textures.loaded then exit;
                Liste := TStringList.Create;

                Path := ExtractFilePath( Application.ExeName ) + 'Textures';
                if not DirectoryExists( Path ) then
                        CreateDir( Path );
                Path := Path + '\';

                GaugeForm.Activate;
                for Id := 0 to $FFFF do begin
                        GaugeForm.SetBalken( trunc( Id*100/$FFFF ) );
                        if Textures.Exists( Id ) then begin
                                Bitmap := Textures.GetTex( Id );
                                Nummer := FormatId( Id, false );
                                Bitmap.SaveToFile( Path + Nummer + '.bmp' );
                                Bitmap.Free;

                                Liste.Add( Nummer + ' ' + Nummer + '.bmp' );
                        end;
                end;
                GaugeForm.Deactivate;
                Liste.SaveToFile( Path + 'list.txt' );
                Liste.Free;
        end;
end;

function TMainForm.FormatId( Id : Integer; Dezimal : Boolean ) : String;
begin
        if Dezimal then begin
                if Id >= 1000 then
                        Result := Format( '%d', [ Id ] )
                else if Id >= 100 then
                        Result := Format( '0%d', [ Id ] )
                else if Id >= 10 then
                        Result := Format( '00%d', [ Id ] )
                else
                        Result := Format( '000%d', [ Id ] );
        end
        else begin
                if Id >= $1000 then
                        Result := '0x' + Format( '%x', [ Id ] )
                else if Id >= $100 then
                        Result := '0x0' + Format( '%x', [ Id ] )
                else if Id >= $10 then
                        Result := '0x00' + Format( '%x', [ Id ] )
                else
                        Result := '0x000' + Format( '%x', [ Id ] );
        end;
end;

procedure TMainForm.Delete5Click(Sender: TObject);
var     Liste : TStringList;
        Id : Integer;
begin
        Liste := TStringList.Create;
        StrLib.Split( lbAnimations.Items[ lbAnimations.ItemIndex ], ' ', Liste );
        Id := strtoint( Liste.Strings[ 1 ] );
        Liste.Free;

        Animation.DeleteAnim( Id );
        lbAnimationsClick( Sender );
end;

procedure TMainForm.btnBrowseAnim2IdxClick(Sender: TObject);
var     NewFile : String;
begin
        NewFile := BrowseFile( 'Anim2.idx' );
        if NewFile <> '' then begin
                Config.SetString( 'Anim2Idx', Newfile );
                ePathAnim2Idx.Text := NewFile;
        end;
end;

procedure TMainForm.btnBrowseAnim2MulClick(Sender: TObject);
var     NewFile : String;
begin
        NewFile := BrowseFile( 'Anim2.mul' );
        if NewFile <> '' then begin
                Config.SetString( 'Anim2Mul', Newfile );
                ePathAnim2Mul.Text := NewFile;
        end;
end;


procedure TMainForm.btnAnim2LoadClick(Sender: TObject);
begin
        InitAnim2( Sender );
        showmessage( 'New Version does not load Anim2.mul into Memory anymore, but writes directly into Anim2.mul File. So make a backup before.' );
end;

procedure TMainForm.InitAnim2(Sender: TObject);
begin
        if ( ePathAnim2Idx.Text <> '' ) and ( ePathAnim2Mul.Text <> '' ) then
                Anim2.Load( ePathAnim2Idx.Text, ePathAnim2Mul.Text );

        cbAnim2.Clear;
        cbAnim2.Items.Add( 'All Slots' );
        cbAnim2.Items.Add( 'Empty Slots' );
        cbAnim2.Items.Add( 'Full Slots' );

        cbAnim2.ItemIndex := 0;
        cbAnim2Change( Sender );
end;

procedure TMainForm.cbAnim2Change(Sender: TObject);
var     i : integer;
        zeile, state : String;
begin
        lbAnim2.Clear;
        lbAnim2.Items.BeginUpdate;
        for i := 0 to Anim2.CountAllAnims-1 do begin
                if i < 122 then
                        zeile := 'H'
                else
                        zeile := 'L';
                zeile := zeile + ': ' + Format( '0x%x', [ i ] );

                state := cbAnim2.Items[ cbAnim2.ItemIndex ];
                if state = 'All Slots' then
                        lbAnim2.Items.Add( zeile )
                else if ( state = 'Empty Slots' ) and ( not Anim2.AnimExists( i ) ) then
                        lbAnim2.Items.Add( zeile )
                else if ( state = 'Full Slots' ) and ( Anim2.AnimExists( i ) ) then
                        lbAnim2.Items.Add( zeile );
        end;
        lbAnim2.Items.EndUpdate;
end;

procedure TMainForm.lbAnim2DrawItem(Control: TWinControl; Index: Integer;
  Rect: TRect; State: TOwnerDrawState);
var     Id : integer;
        Liste : TStringList;
begin
        lbAnim2.Canvas.Brush.Style := bsSolid;
        lbAnim2.Canvas.Brush.Color := clWhite;

        if ( odselected in state ) then begin
                lbAnim2.Canvas.Brush.Color := clNavy;
        end;
        lbAnim2.Canvas.FillRect( rect );

        Liste := TStringList.Create;
        StrLib.Split( lbAnim2.Items[ Index ], ' ', Liste );
        Id := strtoint( Liste.Strings[ 1 ] );
        Liste.Free;

        if Anim2.AnimExists( Id ) then
                lbAnim2.Canvas.Font.Color := clBlack
        else
                lbAnim2.Canvas.Font.Color := clRed;

        lbAnim2.Canvas.Brush.Style := bsClear;
        if ( odselected in state ) then begin
                lbAnim2.Canvas.Font.Color := clWhite;
        end;

        lbAnim2.Canvas.TextOut( 10, (-lbAnim2.TopIndex+Index)*lbAnim2.ItemHeight, lbAnim2.Items[ Index ] );
end;

procedure TMainForm.lbAnim2Click(Sender: TObject);
var     Bitmap : TBitmap32;
        Id : integer;
        Liste : TStringList;
begin
        Liste := TStringList.Create;
        StrLib.Split( lbAnim2.Items[ lbAnim2.ItemIndex ], ' ', Liste );
        Id := strtoint( Liste.Strings[ 1 ] );
        Liste.Free;

        if not Anim2.AnimExists( Id ) then begin
                iAnim2.Bitmap.SetSize( 360, 360 );
                iAnim2.Bitmap.Clear( Color32( iAnim2.Color ) );
                exit;
        end;

        Bitmap := Anim2.SaveFirstPicture( Id );
        iAnim2.Bitmap.SetSize( 360, 360 );
        iAnim2.Bitmap.Clear( Color32( iAnim2.Color ) );

        iAnim2.Bitmap.Draw( ( 360 - Bitmap.Width ) div 2, ( 360 - Bitmap.Height ) div 2, Bitmap );
        Bitmap.Free;
end;

procedure TMainForm.btnBrowseAnim3IdxClick(Sender: TObject);
var     NewFile : String;
begin
        NewFile := BrowseFile( 'Anim3.idx' );
        if NewFile <> '' then begin
                Config.SetString( 'Anim3Idx', Newfile );
                ePathAnim3Idx.Text := NewFile;
        end;
end;

procedure TMainForm.btnBrowseAnim3MulClick(Sender: TObject);
var     NewFile : String;
begin
        NewFile := BrowseFile( 'Anim3.mul' );
        if NewFile <> '' then begin
                Config.SetString( 'Anim3Mul', Newfile );
                ePathAnim3Mul.Text := NewFile;
        end;
end;

procedure TMainForm.btnAnim3LoadClick(Sender: TObject);
begin
        InitAnim3( Sender );
        showmessage( 'New Version does not load Anim3.mul into Memory anymore, but writes directly into Anim3.mul File. So make a backup before.' );
end;

procedure TMainForm.InitAnim3( Sender : TObject );
begin
        if ( ePathAnim3Idx.Text <> '' ) and ( ePathAnim3Mul.Text <> '' ) then
                Anim3.Load( ePathAnim3Idx.Text, ePathAnim3Mul.Text );

        cbAnim3.Clear;
        cbAnim3.Items.Add( 'All Slots' );
        cbAnim3.Items.Add( 'Empty Slots' );
        cbAnim3.Items.Add( 'Full Slots' );

        cbAnim3.ItemIndex := 0;
        cbAnim3Change( Sender );
end;

procedure TMainForm.cbAnim3Change(Sender: TObject);
var     i : integer;
        zeile, state : String;
begin
        lbAnim3.Clear;
        lbAnim3.Items.BeginUpdate;
        for i := 0 to Anim3.CountAllAnims-1 do begin
                if i < 700 then
                        zeile := 'H'
                else if i < 1400 then
                        zeile := 'L'
                else
                        zeile := 'P';
                zeile := zeile + ': ' + Format( '0x%x', [ i ] );

                state := cbAnim3.Items[ cbAnim3.ItemIndex ];
                if state = 'All Slots' then
                        lbAnim3.Items.Add( zeile )
                else if ( state = 'Empty Slots' ) and ( not Anim3.AnimExists( i ) ) then
                        lbAnim3.Items.Add( zeile )
                else if ( state = 'Full Slots' ) and ( Anim3.AnimExists( i ) ) then
                        lbAnim3.Items.Add( zeile );
        end;
        lbAnim3.Items.EndUpdate;
end;

procedure TMainForm.lbAnim3DrawItem(Control: TWinControl; Index: Integer;
  Rect: TRect; State: TOwnerDrawState);
var     Id : integer;
        Liste : TStringList;
begin
        lbAnim3.Canvas.Brush.Style := bsSolid;
        lbAnim3.Canvas.Brush.Color := clWhite;

        if ( odselected in state ) then begin
                lbAnim3.Canvas.Brush.Color := clNavy;
        end;
        lbAnim3.Canvas.FillRect( rect );

        Liste := TStringList.Create;
        StrLib.Split( lbAnim3.Items[ Index ], ' ', Liste );
        Id := strtoint( Liste.Strings[ 1 ] );
        Liste.Free;

        if Anim3.AnimExists( Id ) then
                lbAnim3.Canvas.Font.Color := clBlack
        else
                lbAnim3.Canvas.Font.Color := clRed;

        lbAnim3.Canvas.Brush.Style := bsClear;
        if ( odselected in state ) then begin
                lbAnim3.Canvas.Font.Color := clWhite;
        end;

        lbAnim3.Canvas.TextOut( 10, (-lbAnim3.TopIndex+Index)*lbAnim3.ItemHeight, lbAnim3.Items[ Index ] );
end;

procedure TMainForm.lbAnim3Click(Sender: TObject);
var     Bitmap : TBitmap32;
        Id : integer;
        Liste : TStringList;
begin
        Liste := TStringList.Create;
        StrLib.Split( lbAnim3.Items[ lbAnim3.ItemIndex ], ' ', Liste );
        Id := strtoint( Liste.Strings[ 1 ] );
        Liste.Free;

        if not Anim3.AnimExists( Id ) then begin
                iAnim3.Bitmap.SetSize( 360, 360 );
                iAnim3.Bitmap.Clear( Color32( iAnim3.Color ) );
                exit;
        end;

        Bitmap := Anim3.SaveFirstPicture( Id );
        iAnim3.Bitmap.SetSize( 360, 360 );
        iAnim3.Bitmap.Clear( Color32( iAnim3.Color ) );

        iAnim3.Bitmap.Draw( ( 360 - Bitmap.Width ) div 2, ( 360 - Bitmap.Height ) div 2, Bitmap );
        Bitmap.Free;
end;

procedure TMainForm.SaveAnimtoDirectory1Click(Sender: TObject);
var     SaveDialog : TrmBrowseForFolder;
        Id : integer;
        Liste : TStringList;
begin
        Liste := TStringList.Create;
        StrLib.Split( lbAnim2.Items[ lbAnim2.ItemIndex ], ' ', Liste );
        Id := strtoint( Liste.Strings[ 1 ] );
        Liste.Free;

        if not Anim2.AnimExists( Id ) then
                exit;

        SaveDialog := TrmBrowseForFolder.create( nil );
        SaveDialog.Title := 'Wohin soll die Animation gespeichert werden?';

        if not SaveDialog.Execute then begin
                SaveDialog.Free;
                exit;
        end;

        Anim2.SaveAnimToDirectory( Id, SaveDialog.Folder );
        SaveDialog.Free;
end;

procedure TMainForm.SaveAnimtoFile1Click(Sender: TObject);
var     SaveDialog : TSaveDialog;
        Id : integer;
        Liste : TStringList;
begin
        Liste := TStringList.Create;
        StrLib.Split( lbAnim2.Items[ lbAnim2.ItemIndex ], ' ', Liste );
        Id := strtoint( Liste.Strings[ 1 ] );
        Liste.Free;

        if not Anim2.AnimExists( Id ) then exit;

        SaveDialog := TSaveDialog.Create( nil );
        SaveDialog.DefaultExt := 'vd';
        SaveDialog.Filter := '*.vd|*.vd';
        SaveDialog.FileName := Format( '0x%x.vd', [Id] );

        if not SaveDialog.Execute then begin
                SaveDialog.Free;
                exit;
        end;

        Anim2.SaveAnimToFile( Id, SaveDialog.FileName );
        SaveDialog.Free;
end;

procedure TMainForm.lbAnim2ContextPopup(Sender: TObject; MousePos: TPoint;
  var Handled: Boolean);
begin
        if lbAnim2.ItemIndex = -1 then
                exit;
        popAnim2.Popup( MousePos.X+MainForm.Left, MousePos.Y+MainForm.Top );
end;

procedure TMainForm.lbAnim3ContextPopup(Sender: TObject; MousePos: TPoint;
  var Handled: Boolean);
begin
        if lbAnim3.ItemIndex = -1 then
                exit;
        popAnim3.Popup( MousePos.X+MainForm.Left, MousePos.Y+MainForm.Top );
end;

procedure TMainForm.SaveAnimtoDirectory2Click(Sender: TObject);
var     SaveDialog : TrmBrowseForFolder;
        Id : integer;
        Liste : TStringList;
begin
        Liste := TStringList.Create;
        StrLib.Split( lbAnim3.Items[ lbAnim3.ItemIndex ], ' ', Liste );
        Id := strtoint( Liste.Strings[ 1 ] );
        Liste.Free;

        if not Anim3.AnimExists( Id ) then
                exit;

        SaveDialog := TrmBrowseForFolder.create( nil );
        SaveDialog.Title := 'Wohin soll die Animation gespeichert werden?';

        if not SaveDialog.Execute then begin
                SaveDialog.Free;
                exit;
        end;

        Anim3.SaveAnimToDirectory( Id, SaveDialog.Folder );
        SaveDialog.Free;
end;

procedure TMainForm.SaveAnimtoFile2Click(Sender: TObject);
var     SaveDialog : TSaveDialog;
        Id : integer;
        Liste : TStringList;
begin
        Liste := TStringList.Create;
        StrLib.Split( lbAnim3.Items[ lbAnim3.ItemIndex ], ' ', Liste );
        Id := strtoint( Liste.Strings[ 1 ] );
        Liste.Free;

        if not Anim3.AnimExists( Id ) then exit;

        SaveDialog := TSaveDialog.Create( nil );
        SaveDialog.DefaultExt := 'vd';
        SaveDialog.Filter := '*.vd|*.vd';
        SaveDialog.FileName := Format( '0x%x.vd', [Id] );

        if not SaveDialog.Execute then begin
                SaveDialog.Free;
                exit;
        end;

        Anim3.SaveAnimToFile( Id, SaveDialog.FileName );
        SaveDialog.Free;
end;

procedure TMainForm.btnBrowseAnimdataClick(Sender: TObject);
var     NewFile : String;
begin
        NewFile := BrowseFile( 'Animdata.mul' );
        if NewFile <> '' then begin
                Config.SetString( 'Animdata', Newfile );
                ePathAnimdata.Text := NewFile;
        end;
end;

procedure TMainForm.btnAnimdataLoadClick(Sender: TObject);
begin
        InitAnimdata( Sender );
end;

procedure TMainForm.InitAnimdata( Sender : TObject );
begin
        if ePathAnimdata.Text = '' then exit;

        Animdata.Load( ePathAnimdata.Text );

        cbAnimdata.Clear;
        cbAnimdata.Items.Add( 'All Slots' );
        cbAnimdata.Items.Add( 'Empty Slots' );
        cbAnimdata.Items.Add( 'Full Slots' );

        cbAnimdata.ItemIndex := 0;
        cbAnimdataChange( Sender );
        AnimDataChange := False;
end;


procedure TMainForm.btnAnimdataSaveClick(Sender: TObject);
var     Path : String;
begin
        Path := SaveFile( 'Animdata.mul' );

        if ( Path <> '' ) then begin
                Animdata.Save( Path );
        end;
end;

procedure TMainForm.lbAnimdataDrawItem(Control: TWinControl;
  Index: Integer; Rect: TRect; State: TOwnerDrawState);
var     Id : integer;
begin
        lbAnimdata.Canvas.Brush.Style := bsSolid;
        lbAnimdata.Canvas.Brush.Color := clWhite;

        if ( odselected in state ) then begin
                lbAnimdata.Canvas.Brush.Color := clNavy;
        end;
        lbAnimdata.Canvas.FillRect( rect );

        Id := strtoint( lbAnimdata.Items[ Index ] );

        if Animdata.Exists( Id ) then
                lbAnimdata.Canvas.Font.Color := clBlack
        else
                lbAnimdata.Canvas.Font.Color := clRed;

        lbAnimdata.Canvas.Brush.Style := bsClear;
        if ( odselected in state ) then begin
                lbAnimdata.Canvas.Font.Color := clWhite;
        end;

        lbAnimdata.Canvas.TextOut( 10, (-lbAnimdata.TopIndex+Index)*lbAnimdata.ItemHeight, lbAnimdata.Items[ Index ] );
end;

procedure TMainForm.cbAnimdataChange(Sender: TObject);
var     i : integer;
        zeile, state : String;
begin
        lbAnimdata.Clear;
        lbAnimdata.Items.BeginUpdate;
        for i := 0 to $FFFF do begin
                zeile := Format( '0x%x', [ i ] );

                state := cbAnimdata.Items[ cbAnimdata.ItemIndex ];
                if state = 'All Slots' then
                        lbAnimdata.Items.Add( zeile )
                else if ( state = 'Empty Slots' ) and ( not Animdata.Exists( i ) ) then
                        lbAnimdata.Items.Add( zeile )
                else if ( state = 'Full Slots' ) and ( Animdata.Exists( i ) ) then
                        lbAnimdata.Items.Add( zeile );
        end;
        lbAnimdata.Items.EndUpdate;
end;

procedure TMainForm.lbAnimdataClick(Sender: TObject);
var     Id, Number : Integer;
        Anim : TAnimdataRecord;
begin
        AnimDataChange := True;
        Id := strtoint( lbAnimdata.Items[ lbAnimdata.ItemIndex ] );

        cbAnimdataFrameNumber.Clear;
        eAnimdataFrame.Text := '';
        eAnimdataFrameRelativ.Text := '';
        eAnimdataFrameCount.Text := '';
        eAnimdataFrameStart.Text := '';
        eAnimdataFrameInterval.Text := '';

        iAnimdataAnim.Bitmap.Clear( Color32( iAnimdataAnim.Color ) );
        TimerAnimdata.Enabled := False;

        if Id = -1 then begin
                AnimDataChange := False;
                exit;
        end;

        Anim := Animdata.GetAnimdata( Id );

        for Number := 0 to Anim.Count-1 do
                cbAnimdataFrameNumber.Items.Add( Format( 'Picture %d', [Number] ) );

        cbAnimdataFrameNumber.ItemIndex := 0;
        cbAnimdataFrameNumberChange( Sender );

        eAnimdataFrameCount.Text := inttostr( Anim.Count );
        eAnimdataFrameStart.Text := inttostr( Anim.FrameStart );
        eAnimdataFrameInterval.Text := inttostr( Anim.FrameInterval );
        AnimDataChange := False;
end;

procedure TMainForm.cbAnimdataFrameNumberChange(Sender: TObject);
var     Id, TileId : Integer;
        Anim : TAnimdataRecord;
        Bitmap : TBitmap32;
begin
        Id := strtoint( lbAnimdata.Items[ lbAnimdata.ItemIndex ] );
        Anim := Animdata.GetAnimdata( Id );
        TileId := Id + Anim.Frames[ cbAnimdataFrameNumber.ItemIndex ];

        iAnimdata.Bitmap.SetSize( 161, 137 );
        iAnimdata.Bitmap.Clear( Color32( iAnimdata.Color ) );
        if Art.loaded then begin
                Bitmap := MakeTransparent( Art.GetStaticTile( TileId ), Color32( iAnimdata.Color ), 0 );
                iAnimdata.Bitmap.Draw( 0, 0, Bitmap );
        end;

        eAnimdataFrame.Text := Format( '0x%x', [TileId] );
        eAnimdataFrameRelativ.Text := inttostr( Anim.Frames[ cbAnimdataFrameNumber.ItemIndex ] );
end;

procedure TMainForm.btnAnimdataStartClick(Sender: TObject);
var     Id : Integer;
begin
        Id := strtoint( lbAnimdata.Items[ lbAnimdata.ItemIndex ] );

        if Id = -1 then exit;
        if not Animdata.Loaded then exit;
        if not Art.loaded then exit;
        if not Animdata.Exists( Id ) then exit;

        TimerAnimdata.Tag := 0;
        TimerAnimdata.Interval := Animdata.GetAnimdata( Id ).FrameStart*50 + 10;
        TimerAnimdata.Enabled := True;
end;

procedure TMainForm.btnAnimdataStopClick(Sender: TObject);
begin
        iAnimdataAnim.Bitmap.Clear( Color32( iAnimdataAnim.Color ) );
        TimerAnimdata.Enabled := False;
end;

procedure TMainForm.TimerAnimdataTimer(Sender: TObject);
var     Id : Integer;
        Anim : TAnimdataRecord;
        Bitmap : TBitmap32;
begin
        Id := strtoint( lbAnimdata.Items[ lbAnimdata.ItemIndex ] );
        Anim := Animdata.GetAnimdata( Id );

        if TimerAnimdata.Tag = -1 then begin
                TimerAnimdata.Tag := 0;
                TimerAnimdata.Interval := 2000 + Anim.FrameStart*50;
                iAnimdataAnim.Bitmap.SetSize( 192, 192 );
                iAnimdataAnim.Bitmap.Clear( Color32( iAnimdataAnim.Color ) );
                exit;
        end;

        Bitmap := Art.GetStaticTile( Id + Anim.Frames[ TimerAnimdata.Tag ] );
        Bitmap := MakeTransparent( Bitmap, Color32( iAnimdataAnim.Color ), 0 );

        iAnimdataAnim.Bitmap.SetSize( 192, 192 );
        iAnimdataAnim.Bitmap.Clear( Color32( iAnimdataAnim.Color ) );
        iAnimdataAnim.Bitmap.Draw( 0, 192-Bitmap.Height, Bitmap );

        if TimerAnimdata.Tag < Anim.Count-1 then begin
                TimerAnimdata.Tag := TimerAnimdata.Tag+1;
                TimerAnimdata.Interval := Anim.FrameInterval*50;
        end
        else begin
                if cbAnimdataRepeat.Checked then begin
                        TimerAnimdata.Tag := -1;
                end
                else begin
                        iAnimdataAnim.Bitmap.SetSize( 192, 192 );
                        iAnimdataAnim.Bitmap.Clear( Color32( iAnimdataAnim.Color ) );
                        TimerAnimdata.Enabled := False;
                end;
        end;
end;

procedure TMainForm.AnimdataChanged(Sender: TObject);
var     Anim : TAnimdataRecord;
        Id, Number : Integer;
begin
        Id := strtoint( lbAnimdata.Items[ lbAnimdata.ItemIndex ] );
        Anim := Animdata.GetAnimdata( Id );

        if eAnimdataFrameInterval.Text <> '' then
                Anim.FrameInterval := strtoint( eAnimdataFrameInterval.Text );
        if eAnimdataFrameStart.Text <> '' then
                Anim.FrameStart := strtoint( eAnimdataFrameStart.Text );

        if Anim.Count <> strtoint( eAnimdataFrameCount.Text ) then begin
                Anim.Count := strtoint( eAnimdataFrameCount.Text );
                Animdata.SetAnimdata( Id, Anim );
        end
        else
                Animdata.SetAnimdata( Id, Anim );

        cbAnimdataFrameNumber.Clear;
        for Number := 0 to Anim.Count-1 do
                cbAnimdataFrameNumber.Items.Add( Format( 'Picture %d', [Number] ) );

        cbAnimdataFrameNumber.ItemIndex := 0;
        cbAnimdataFrameNumberChange( Sender );
end;

procedure TMainForm.eAnimdataFrameCountChange(Sender: TObject);
begin
        if not AnimDataChange then AnimDataChanged( Sender );
end;

procedure TMainForm.eAnimdataFrameStartChange(Sender: TObject);
begin
        if not AnimDataChange then AnimDataChanged( Sender );
end;

procedure TMainForm.eAnimdataFrameIntervalChange(Sender: TObject);
begin
        if not AnimDataChange then AnimDataChanged( Sender );
end;

procedure TMainForm.eAnimdataFrameRelativChange(Sender: TObject);
var     Anim : TAnimdataRecord;
        Id : Integer;
begin
        if AnimDataChange then exit;
        if eAnimdataFrameRelativ.Text = '-' then exit;
        Id := strtoint( lbAnimdata.Items[ lbAnimdata.ItemIndex ] );
        Anim := Animdata.GetAnimdata( Id );

        Anim.Frames[ cbAnimdataFrameNumber.ItemIndex ] := strtoint( eAnimdataFrameRelativ.Text );
        Animdata.SetAnimdata( Id, Anim );
        eAnimdataFrame.Text := Format( '0x%x', [ Id + Anim.Frames[ cbAnimdataFrameNumber.ItemIndex ] ] );
        cbAnimdataFrameNumberChange(Sender);
end;

procedure TMainForm.eAnimdataFrameChange(Sender: TObject);
var     Anim : TAnimdataRecord;
        Id : Integer;
begin
        if AnimDataChange then exit;
        Id := strtoint( lbAnimdata.Items[ lbAnimdata.ItemIndex ] );
        Anim := Animdata.GetAnimdata( Id );

        Anim.Frames[ cbAnimdataFrameNumber.ItemIndex ] := strtoint( eAnimdataFrame.Text ) - Id;
        Animdata.SetAnimdata( Id, Anim );
        eAnimdataFrameRelativ.Text := inttostr( Anim.Frames[ cbAnimdataFrameNumber.ItemIndex ] );
        cbAnimdataFrameNumberChange(Sender);
end;

procedure TMainForm.btnAboutClick(Sender: TObject);
begin
        AboutForm.Show;
end;

procedure TMainForm.btnChooseStaticClick(Sender: TObject);
var     Id, TileId : Integer;
        Anim : TAnimdataRecord;
begin
        if not Art.loaded then exit;
        if not Animdata.Loaded then exit;
        if cbAnimdataFrameNumber.ItemIndex = -1 then exit;

        Id := strtoint( lbAnimdata.Items[ lbAnimdata.ItemIndex ] );
        Anim := Animdata.GetAnimdata( Id );
        TileId := Id + Anim.Frames[ cbAnimdataFrameNumber.ItemIndex ];

        StaticChooseForm.StartId := TileId;
        StaticChooseForm.Show;
end;

procedure TMainForm.cbWin98Click(Sender: TObject);
begin
        Config.SetBool( 'Win98', cbWin98.Checked );
end;

procedure TMainForm.btnReIndexClick(Sender: TObject);
var     mulPath, idxPath : String;
begin
        if cbReIndex.ItemIndex = -1 then exit;

        //Animations
        if cbReIndex.ItemIndex = 0 then begin
                if not Animation.Loaded then exit;

                idxPath := SaveFile( 'Anim.idx' );
                mulPath := SaveFile( 'Anim.mul' );

                if ( idxPath = '' ) or ( mulPath = '' ) then exit;

                Animation.ReIndex( idxPath, mulPath );
        end

        //Art
        else if cbReIndex.ItemIndex = 1 then begin
                if not Art.loaded then exit;

                idxPath := SaveFile( 'Artidx.mul' );
                mulPath := SaveFile( 'Art.mul' );

                if ( idxPath = '' ) or ( mulPath = '' ) then exit;

                Art.ReIndex( idxPath, mulPath );
        end

        //Gumps
        else if cbReIndex.ItemIndex = 2 then begin
                if not Gump.loaded then exit;

                idxPath := SaveFile( 'Gumpidx.mul' );
                mulPath := SaveFile( 'GumpArt.mul' );

                if ( idxPath = '' ) or ( mulPath = '' ) then exit;

                Gump.ReIndex( idxPath, mulPath );
        end

        //Textures
        else if cbReIndex.ItemIndex = 3 then begin
                if not Textures.loaded then exit;

                idxPath := SaveFile( 'Texidx.mul' );
                mulPath := SaveFile( 'Texmaps.mul' );

                if ( idxPath = '' ) or ( mulPath = '' ) then exit;

                Textures.ReIndex( idxPath, mulPath );
        end

        //Statics
        else if cbReIndex.ItemIndex = 4 then begin
                if not Statics.loaded then exit;

                idxPath := SaveFile( 'Staidx0.mul' );
                mulPath := SaveFile( 'Statics0.mul' );

                if ( idxPath = '' ) or ( mulPath = '' ) then exit;

                Statics.ReIndex( idxPath, mulPath );
        end;
end;

function TMainForm.Search( lb : TListbox; Sender : TObject; SearchString : String ) : Integer;
var     i, Start, Ende : Integer;
begin
        SearchString := UpperCase( SearchString );

        if lb.Count = 0 then begin
                showmessage( 'Not found.' );
                Result := -1;
                exit;
        end;

        if lb.Tag = LastSearchType then begin
                if LastSearchIndex < lb.Count-1 then
                        Start := LastSearchIndex +1
                else
                        Start := 0;
                Ende := LastSearchIndex -1;
        end
        else begin
                Start := 0;
                Ende := 0;
        end;

        LastSearchType := lb.Tag;

        for i := Start to lb.Count-1 do begin
                if Pos( SearchString, UpperCase( lb.Items[i] ) ) <> 0 then begin
                        Result := i;
                        LastSearchIndex := i;
                        exit;
                end;
        end;

        if ( Start = 0 ) or ( Ende < 1 ) then begin
                showmessage( 'Not found.' );
                Result := -1;
                exit;
        end;

        for i := 0 to Ende do begin
                if Pos( SearchString, UpperCase( lb.Items[i] ) ) <> 0 then begin
                        Result := i;
                        LastSearchIndex := i;
                        exit;
                end;
        end;

        showmessage( 'Not found.' );
        Result := -1;
end;

procedure TMainForm.btnAnimSearchClick(Sender: TObject);
var     Index : Integer;
begin
        if eAnimSearch.Text <> '' then begin
                Index := Search( lbAnimations, Sender, eAnimSearch.Text );
                if Index <> -1 then begin
                        lbAnimations.ItemIndex := Index;
                        lbAnimationsClick( Sender );
                end;
        end;
end;

procedure TMainForm.eAnimSearchKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
        if Key = VK_Return then
                btnAnimSearchClick( Sender );
end;

procedure TMainForm.btnAnim2SearchClick(Sender: TObject);
var     Index : Integer;
begin
        if eAnim2Search.Text <> '' then begin
                Index := Search( lbAnim2, Sender, eAnim2Search.Text );
                if Index <> -1 then begin
                        lbAnim2.ItemIndex := Index;
                        lbAnim2Click( Sender );
                end;
        end;
end;

procedure TMainForm.eAnim2SearchKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
        if Key = VK_Return then
                btnAnim2SearchClick( Sender );
end;

procedure TMainForm.btnAnim3SearchClick(Sender: TObject);
var     Index : Integer;
begin
        if eAnim3Search.Text <> '' then begin
                Index := Search( lbAnim3, Sender, eAnim3Search.Text );
                if Index <> -1 then begin
                        lbAnim3.ItemIndex := Index;
                        lbAnim3Click( Sender );
                end;
        end;
end;

procedure TMainForm.eAnim3SearchKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
        if Key = VK_Return then
                btnAnim3SearchClick( Sender );
end;

procedure TMainForm.btnAnimdataSearchClick(Sender: TObject);
var     Index : Integer;
begin
        if eAnimdataSearch.Text <> '' then begin
                Index := Search( lbAnimdata, Sender, eAnimdataSearch.Text );
                if Index <> -1 then begin
                        lbAnimdata.ItemIndex := Index;
                        lbAnimdataClick( Sender );
                end;
        end;
end;

procedure TMainForm.eAnimdataSearchKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
        if Key = VK_Return then
                btnAnimdataSearchClick( Sender );
end;

procedure TMainForm.btnArtMapSearchClick(Sender: TObject);
var     Index : Integer;
begin
        if eArtMapSearch.Text <> '' then begin
                Index := Search( lbArtMap, Sender, eArtMapSearch.Text );
                if Index <> -1 then begin
                        lbArtMap.ItemIndex := Index;
                        lbArtMapClick( Sender );
                end;
        end;
end;

procedure TMainForm.eArtMapSearchKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
        if Key = VK_Return then
                btnArtMapSearchClick( Sender );
end;

procedure TMainForm.btnArtStaticSearchClick(Sender: TObject);
var     Index : Integer;
begin
        if eArtStaticSearch.Text <> '' then begin
                Index := Search( lbArtStatic, Sender, eArtStaticSearch.Text );
                if Index <> -1 then begin
                        lbArtStatic.ItemIndex := Index;
                        lbArtStaticClick( Sender );
                end;
        end;
end;

procedure TMainForm.eArtStaticSearchKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
        if Key = VK_Return then
                btnArtStaticSearchClick( Sender );
end;

procedure TMainForm.btnGumpAnimSearchClick(Sender: TObject);
var     Index : Integer;
begin
        if eGumpAnimSearch.Text <> '' then begin
                Index := Search( lbGumpAnim, Sender, eGumpAnimSearch.Text );
                if Index <> -1 then begin
                        lbGumpAnim.ItemIndex := Index;
                        lbGumpAnimClick( Sender );
                end;
        end;
end;

procedure TMainForm.eGumpAnimSearchKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
        if Key = VK_Return then
                btnGumpAnimSearchClick( Sender );
end;

procedure TMainForm.btnGumpNonAnimSearchClick(Sender: TObject);
var     Index : Integer;
begin
        if eGumpNonAnimSearch.Text <> '' then begin
                Index := Search( lbGumpNonAnim, Sender, eGumpNonAnimSearch.Text );
                if Index <> -1 then begin
                        lbGumpNonAnim.ItemIndex := Index;
                        lbGumpNonAnimClick( Sender );
                end;
        end;
end;

procedure TMainForm.eGumpNonAnimSearchKeyDown(Sender: TObject;
  var Key: Word; Shift: TShiftState);
begin
        if Key = VK_Return then
                btnGumpNonAnimSearchClick( Sender );
end;

procedure TMainForm.btnTexSearchClick(Sender: TObject);
var     Index : Integer;
begin
        if eTexSearch.Text <> '' then begin
                Index := Search( lbTex, Sender, eTexSearch.Text );
                if Index <> -1 then begin
                        lbTex.ItemIndex := Index;
                        lbTexClick( Sender );
                end;
        end;
end;

procedure TMainForm.eTexSearchKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
        if Key = VK_Return then
                btnTexSearchClick( Sender );
end;

procedure TMainForm.btnTMSearchClick(Sender: TObject);
var     Index : Integer;
begin
        if eTMSearch.Text <> '' then begin
                Index := Search( lbTiledataMap, Sender, eTMSearch.Text );
                if Index <> -1 then begin
                        lbTiledataMap.ItemIndex := Index;
                        lbTiledataMapClick( Sender );
                end;
        end;
end;

procedure TMainForm.eTMSearchKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
        if Key = VK_Return then
                btnTMSearchClick( Sender );
end;

procedure TMainForm.btnTSSearchClick(Sender: TObject);
var     Index : Integer;
begin
        if eTSSearch.Text <> '' then begin
                Index := Search( lbTiledataStatic, Sender, eTSSearch.Text );
                if Index <> -1 then begin
                        lbTiledataStatic.ItemIndex := Index;
                        lbTiledataStaticClick( Sender );
                end;
        end;
end;

procedure TMainForm.eTSSearchKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
        if Key = VK_Return then
                btnTSSearchClick( Sender );
end;


procedure TMainForm.btnBrowseSoundIdxClick(Sender: TObject);
var     NewFile : String;
begin
        NewFile := BrowseFile( 'Soundidx.mul' );
        if NewFile <> '' then begin
                Config.SetString( 'SoundIdx', Newfile );
                ePathSoundIdx.Text := NewFile;
        end;
end;

procedure TMainForm.btnBrowseSoundMulClick(Sender: TObject);
var     NewFile : String;
begin
        NewFile := BrowseFile( 'Sound.mul' );
        if NewFile <> '' then begin
                Config.SetString( 'SoundMul', Newfile );
                ePathSoundMul.Text := NewFile;
        end;
end;

procedure TMainForm.InitSound( Sender : TObject );
begin
        if ( ePathSoundIdx.Text = '' ) or ( ePathSoundMul.Text = '' ) then exit;

        Sound.Load( ePathSoundIdx.Text, ePathSoundMul.Text );

        cbSound.Clear;
        cbSound.Items.Add( 'All Slots' );
        cbSound.Items.Add( 'Empty Slots' );
        cbSound.Items.Add( 'Full Slots' );

        cbSound.ItemIndex := 0;
        cbSoundChange( Sender );
end;

procedure TMainForm.btnSoundSaveClick(Sender: TObject);
var     idxPath, mulPath : String;
begin
        idxPath := SaveFile( 'Soundidx.mul' );
        mulPath := SaveFile( 'Sound.mul' );

        if ( idxPath <> '' ) and ( mulPath <> '' ) then begin
                Sound.Save( idxPath, mulPath );
        end;
end;

procedure TMainForm.lbSoundDrawItem(Control: TWinControl; Index: Integer;
  Rect: TRect; State: TOwnerDrawState);
var     Id : integer;
begin
        lbSound.Canvas.Brush.Style := bsSolid;
        lbSound.Canvas.Brush.Color := clWhite;

        if ( odselected in state ) then begin
                lbSound.Canvas.Brush.Color := clNavy;
        end;
        lbSound.Canvas.FillRect( rect );

        Id := strtoint( lbSound.Items[ Index ] );

        if Sound.Exists( Id ) then
                lbSound.Canvas.Font.Color := clBlack
        else
                lbSound.Canvas.Font.Color := clRed;

        lbSound.Canvas.Brush.Style := bsClear;
        if ( odselected in state ) then begin
                lbSound.Canvas.Font.Color := clWhite;
        end;

        lbSound.Canvas.TextOut( 10, (-lbSound.TopIndex+Index)*lbSound.ItemHeight, lbSound.Items[ Index ] );
end;

procedure TMainForm.cbSoundChange(Sender: TObject);
var     i : integer;
        zeile, state : String;
begin
        lbSound.Clear;
        lbSound.Items.BeginUpdate;
        for i := 0 to $FFF do begin
                zeile := Format( '0x%x', [ i ] );

                state := cbSound.Items[ cbSound.ItemIndex ];
                if state = 'All Slots' then
                        lbSound.Items.Add( zeile )
                else if ( state = 'Empty Slots' ) and ( not Sound.Exists( i ) ) then
                        lbSound.Items.Add( zeile )
                else if ( state = 'Full Slots' ) and ( Sound.Exists( i ) ) then
                        lbSound.Items.Add( zeile );
        end;
        lbSound.Items.EndUpdate;
end;
procedure TMainForm.btnSoundLoadClick(Sender: TObject);
begin
        InitSound( Sender );
end;

procedure TMainForm.lbSoundContextPopup(Sender: TObject; MousePos: TPoint;
  var Handled: Boolean);
begin
        if lbSound.ItemIndex = -1 then
                exit;
        popSound.Popup( MousePos.X+MainForm.Left, MousePos.Y+MainForm.Top );
end;

procedure TMainForm.PlaySound1Click(Sender: TObject);
var     Id : Integer;
        Path : String;
begin
        Id :=  strtoint( lbSound.Items[ lbSound.ItemIndex ] );
        Path := ExtractFilePath( Application.ExeName ) + 'play.wav';
        Sound.SaveSound( Id, Path );
        sndPlaySound( PChar( Path ), SND_ASYNC );
end;

procedure TMainForm.SavetoFile3Click(Sender: TObject);
var     SaveDialog : TSaveDialog;
        Id : Integer;
        Path : String;
begin
        Id :=  strtoint( lbSound.Items[ lbSound.ItemIndex ] );

        SaveDialog := TSaveDialog.Create( nil );
        SaveDialog.Filter := '*.wav|*.wav';
        SaveDialog.DefaultExt := 'wav';
        SaveDialog.FileName := Format( '0x%x.wav', [Id] );

        if not SaveDialog.Execute then begin
                SaveDialog.Free;
                exit;
        end;

        Path := SaveDialog.FileName;
        SaveDialog.Free;

        Sound.SaveSound( Id, Path );
end;

procedure TMainForm.Delete6Click(Sender: TObject);
var     Id : Integer;
begin
        Id :=  strtoint( lbSound.Items[ lbSound.ItemIndex ] );
        Sound.Delete( Id );

        lbSound.Repaint;
end;

procedure TMainForm.LoadfromFile2Click(Sender: TObject);
var     OpenDialog : TOpenDialog;
        Id : Integer;
begin
        OpenDialog := TOpenDialog.Create( nil );
        OpenDialog.Filter := '*.wav|*.wav';

        if not OpenDialog.Execute then begin
                OpenDialog.Free;
                exit;
        end;

        Id :=  strtoint( lbSound.Items[ lbSound.ItemIndex ] );
        Sound.LoadSound( Id, OpenDialog.FileName );
        OpenDialog.Free;
end;

procedure TMainForm.btnSoundSearchClick(Sender: TObject);
var     Index : Integer;
begin
        if eSoundSearch.Text <> '' then begin
                Index := Search( lbSound, Sender, eSoundSearch.Text );
                if Index <> -1 then begin
                        lbSound.ItemIndex := Index;
                end;
        end;
end;

procedure TMainForm.eSoundSearchKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
        if Key = VK_Return then
                btnSoundSearchClick( Sender );
end;

procedure TMainForm.lbMultiDrawItem(Control: TWinControl; Index: Integer;
  Rect: TRect; State: TOwnerDrawState);
var     Id : integer;
begin
        lbMulti.Canvas.Brush.Style := bsSolid;
        lbMulti.Canvas.Brush.Color := clWhite;

        if ( odselected in state ) then begin
                lbMulti.Canvas.Brush.Color := clNavy;
        end;
        lbMulti.Canvas.FillRect( rect );

        Id := strtoint( lbMulti.Items[ Index ] );

        if Multi.Exists( Id ) then
                lbMulti.Canvas.Font.Color := clBlack
        else
                lbMulti.Canvas.Font.Color := clRed;

        lbMulti.Canvas.Brush.Style := bsClear;
        if ( odselected in state ) then begin
                lbMulti.Canvas.Font.Color := clWhite;
        end;

        lbMulti.Canvas.TextOut( 10, (-lbMulti.TopIndex+Index)*lbMulti.ItemHeight, lbMulti.Items[ Index ] );
end;

procedure TMainForm.cbMultiChange(Sender: TObject);
var     i : integer;
        zeile, state : String;
begin
        lbmulti.Clear;
        lbmulti.Items.BeginUpdate;

        state := cbmulti.Items[ cbmulti.ItemIndex ];

        for i := 0 to $1FF0 do begin
                zeile := Format( '0x%x', [ i ] );
                if state = 'All Slots' then
                        lbmulti.Items.Add( zeile )
                else if ( state = 'Empty Slots' ) and ( not Multi.Exists( i ) ) then
                        lbmulti.Items.Add( zeile )
                else if ( state = 'Full Slots' ) and ( Multi.Exists( i ) ) then
                        lbmulti.Items.Add( zeile );
        end;
        lbmulti.Items.EndUpdate;
end;

procedure TMainForm.btnMultiSearchClick(Sender: TObject);
var     Index : Integer;
begin
        if eMultiSearch.Text <> '' then begin
                Index := Search( lbMulti, Sender, eMultiSearch.Text );
                if Index <> -1 then begin
                        lbMulti.ItemIndex := Index;
                        lbMultiClick( Sender );
                end;
        end;
end;

procedure TMainForm.lbMultiClick(Sender: TObject);
var     Bitmap : TBitmap32;
        Id : integer;
begin
        Id := strtoint( lbMulti.Items[ lbMulti.ItemIndex ] );

        if not Multi.Exists( Id ) then begin
                iMulti.Width := 100;
                iMulti.Height := 100;
                iMulti.Bitmap.SetSize( 100, 100 );
                iMulti.Bitmap.Clear( Color32( iMulti.Color ) );
                exit;
        end;

        Bitmap := Multi.GetMulti( Id );
        iMulti.Width := Bitmap.Width;
        iMulti.Height := Bitmap.Height;
        iMulti.Bitmap.SetSize( Bitmap.Width, Bitmap.Height );
        iMulti.Bitmap.Clear( Color32( iMulti.Color ) );

        iMulti.Bitmap.Draw( 0, 0, Bitmap );
        Bitmap.Free;
end;

procedure TMainForm.eMultiSearchKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
        if Key = VK_Return then
                btnMultiSearchClick( Sender );
end;

procedure TMainForm.btnBrowseMultiIdxClick(Sender: TObject);
var     NewFile : String;
begin
        NewFile := BrowseFile( 'Multi.idx' );
        if NewFile <> '' then begin
                Config.SetString( 'MultiIdx', Newfile );
                ePathMultiIdx.Text := NewFile;
        end;
end;

procedure TMainForm.btnBrowseMultiMulClick(Sender: TObject);
var     NewFile : String;
begin
        NewFile := BrowseFile( 'Multi.mul' );
        if NewFile <> '' then begin
                Config.SetString( 'MultiMul', Newfile );
                ePathMultiMul.Text := NewFile;
        end;
end;

procedure TMainForm.btnMultiSaveClick(Sender: TObject);
var     idxPath, mulPath : String;
begin
        idxPath := SaveFile( 'Multi.idx' );
        mulPath := SaveFile( 'Multi.mul' );

        if ( idxPath <> '' ) and ( mulPath <> '' ) then begin
                Multi.Save( idxPath, mulPath );
        end;
end;

procedure TMainForm.btnMultiLoadClick(Sender: TObject);
begin
        InitMulti( Sender );
end;

procedure TMainForm.InitMulti( Sender : TObject );
begin
        if ( ePathMultiIdx.Text <> '' ) and ( ePathMultiMul.Text <> '' ) then
                Multi.Load( ePathMultiIdx.Text, ePathMultiMul.Text );

        cbMulti.Clear;
        cbMulti.Items.Add( 'All Slots' );
        cbMulti.Items.Add( 'Empty Slots' );
        cbMulti.Items.Add( 'Full Slots' );

        cbMulti.ItemIndex := 0;
        cbMultiChange( Sender );
end;

procedure TMainForm.lbMultiContextPopup(Sender: TObject; MousePos: TPoint;
  var Handled: Boolean);
begin
        if lbMulti.ItemIndex = -1 then
                exit;
        popMulti.Popup( MousePos.X+MainForm.Left, MousePos.Y+MainForm.Top );
end;

procedure TMainForm.SavetoWsc1Click(Sender: TObject);
var     Id : integer;
        SaveDialog : TSaveDialog;
begin
        Id := strtoint( lbMulti.Items[ lbMulti.ItemIndex ] );

        SaveDialog := TSaveDialog.Create( nil );
        SaveDialog.Filter := '*.scp|*.scp';
        SaveDialog.DefaultExt := 'scp';
        SaveDialog.FileName := Format( '0x%x.scp', [Id] );

        if not SaveDialog.Execute then begin
                SaveDialog.Free;
                exit;
        end;

        Multi.SaveToSphere51a( Id, SaveDialog.FileName );
        SaveDialog.Free;
end;

procedure TMainForm.SavetoWsc2Click(Sender: TObject);
var     Id : integer;
        SaveDialog : TSaveDialog;
begin
        Id := strtoint( lbMulti.Items[ lbMulti.ItemIndex ] );

        SaveDialog := TSaveDialog.Create( nil );
        SaveDialog.Filter := '*.wsc|*.wsc';
        SaveDialog.DefaultExt := 'wsc';
        SaveDialog.FileName := Format( '0x%x.wsc', [Id] );

        if not SaveDialog.Execute then begin
                SaveDialog.Free;
                exit;
        end;

        Multi.SaveToWsc( Id, SaveDialog.FileName );
        SaveDialog.Free;
end;

procedure TMainForm.LoadfromSphere51a1Click(Sender: TObject);
var     OpenDialog : TOpenDialog;
        Id : Integer;
begin
        OpenDialog := TOpenDialog.Create( nil );
        OpenDialog.Filter := '*.scp|*.scp';

        if not OpenDialog.Execute then begin
                OpenDialog.Free;
                exit;
        end;

        Id := strtoint( lbMulti.Items[ lbMulti.ItemIndex ] );
        Multi.LoadFromSphere51a( Id, OpenDialog.FileName );
        lbMultiClick( Sender );

        OpenDialog.Free;
end;

procedure TMainForm.LoadfromWsc1Click(Sender: TObject);
var     OpenDialog : TOpenDialog;
        Id : Integer;
begin
        OpenDialog := TOpenDialog.Create( nil );
        OpenDialog.Filter := '*.wsc|*.wsc';

        if not OpenDialog.Execute then begin
                OpenDialog.Free;
                exit;
        end;

        Id := strtoint( lbMulti.Items[ lbMulti.ItemIndex ] );
        Multi.LoadFromWsc( Id, OpenDialog.FileName );
        lbMultiClick( Sender );

        OpenDialog.Free;
end;

procedure TMainForm.Delete7Click(Sender: TObject);
var     Id : Integer;
begin
        Id := strtoint( lbMulti.Items[ lbMulti.ItemIndex ] );
        Multi.Delete( Id );
        lbMultiClick( Sender );
end;

procedure TMainForm.btnBrowseStaticIdxClick(Sender: TObject);
var     NewFile : String;
begin
        NewFile := BrowseFile( 'Staidx*.mul' );
        if NewFile <> '' then begin
                Config.SetString( 'StaticIdx', Newfile );
                ePathStaticIdx.Text := NewFile;
        end;
end;

procedure TMainForm.btnBrowseStaticMulClick(Sender: TObject);
var     NewFile : String;
begin
        NewFile := BrowseFile( 'Statics*.mul' );
        if NewFile <> '' then begin
                Config.SetString( 'StaticMul', Newfile );
                ePathStaticMul.Text := NewFile;
        end;
end;

procedure TMainForm.btnStaticSaveClick(Sender: TObject);
var     idxPath, mulPath : String;
begin
        idxPath := SaveFile( 'Staidx0.mul' );
        mulPath := SaveFile( 'Statics0.mul' );

        if ( idxPath <> '' ) and ( mulPath <> '' ) then begin
                Statics.Save( idxPath, mulPath );
        end;
end;

procedure TMainForm.btnStaticLoadClick(Sender: TObject);
var     Width, Height : Integer;
begin
        if ( ePathStaticIdx.Text <> '' ) and ( ePathStaticMul.Text <> '' ) then begin
                try
                        Width := StrToInt( eMapWidth.Text );
                        Height := StrToInt( eMapHeight.Text );
                except
                        ShowMessage( 'Width or Height incorrect or missing (before ML: 6144x4096).' );
                        Exit;
                end;
                Statics.Load( ePathStaticIdx.Text, ePathStaticMul.Text, Width, Height );
        end;
end;

procedure TMainForm.btnActivateEditorClick(Sender: TObject);
begin
        if not Art.loaded then btnArtLoadClick( Sender );
        if not Statics.loaded then btnStaticLoadClick( Sender );
        if not Tiledata.Loaded then btnTiledataLoadClick( Sender );
        if not Textures.loaded then btnTexLoadClick( Sender );
        if not Hues.loaded then btnHuesLoadClick( Sender );
        if not Animdata.Loaded then btnAnimdataLoadClick( Sender );
        if not RadarCol.loaded then btnLoadRadarColClick( Sender );
        if not Map.Loaded then btnMapLoadClick( Sender );
        SEditorForm.Show;
        MainForm.Hide;
end;

procedure TMainForm.lbSoundClick(Sender: TObject);
var     Id : Integer;
begin
        Id :=  strtoint( lbSound.Items[ lbSound.ItemIndex ] );
        if Sound.Exists( Id ) then
                lSound.Caption := Sound.GetName( Id )
        else
                lSound.Caption := '';
end;

procedure TMainForm.btnStatDiffToolClick(Sender: TObject);
begin
        DiffForm.Show;
end;

procedure TMainForm.SaveToTextfile1Click(Sender: TObject);
var     Id : integer;
        SaveDialog : TSaveDialog;
begin
        Id := strtoint( lbMulti.Items[ lbMulti.ItemIndex ] );

        SaveDialog := TSaveDialog.Create( nil );
        SaveDialog.Filter := '*.txt|*.txt';
        SaveDialog.DefaultExt := 'txt';
        SaveDialog.FileName := Format( '0x%x.txt', [Id] );

        if not SaveDialog.Execute then begin
                SaveDialog.Free;
                exit;
        end;

        Multi.SaveToText( Id, SaveDialog.FileName );
        SaveDialog.Free;
end;

procedure TMainForm.LoadfromTextfile1Click(Sender: TObject);
var     OpenDialog : TOpenDialog;
        Id : Integer;
begin
        OpenDialog := TOpenDialog.Create( nil );
        OpenDialog.Filter := '*.txt|*.txt';

        if not OpenDialog.Execute then begin
                OpenDialog.Free;
                exit;
        end;

        Id := strtoint( lbMulti.Items[ lbMulti.ItemIndex ] );
        Multi.LoadFromText( Id, OpenDialog.FileName );
        lbMultiClick( Sender );

        OpenDialog.Free;
end;

procedure TMainForm.ShowDetails1Click(Sender: TObject);
var     Id : integer;
begin
        Id := strtoint( lbArtStatic.Items[ lbArtStatic.ItemIndex ] );

        Art.ShowStaticDetails( Id );
end;

procedure TMainForm.btnBrowseMapClick(Sender: TObject);
var     NewFile : String;
begin
        NewFile := BrowseFile( 'Map*.mul' );
        if NewFile <> '' then begin
                Config.SetString( 'Map', Newfile );
                ePathMap.Text := NewFile;
        end;
end;

procedure TMainForm.btnMapLoadClick(Sender: TObject);
var     Width, Height : Integer;
begin
        if ePathMap.Text <> '' then begin
                try
                        Width := StrToInt( eMapWidth.Text );
                        Height := StrToInt( eMapHeight.Text );
                except
                        ShowMessage( 'Width or Height incorrect or missing (before ML: 6144x4096).' );
                        Exit;
                end;
                Map.Load( ePathMap.Text, Width, Height );
        end;
end;

procedure TMainForm.lbTiledataMapDblClick(Sender: TObject);
var     Id : Integer;
        Liste : TStringList;
begin
        Liste := TStringList.Create;
        StrLib.Split( lbTiledataMap.Items[ lbTiledataMap.ItemIndex ], ' ', Liste );
        Id := strtoint( Liste.Strings[ 0 ] );
        Liste.Free;

        Showmessage( 'Flag: ' + inttostr( Tiledata.GetCompleteLandFlag( Id ) ) );
end;

procedure TMainForm.btnCreateScriptsClick(Sender: TObject);
var     SaveDialog : TSaveDialog;
        Path : String;
        Liste : TStringList;
        Id, Counter : Integer;
        Zeile : String;
begin
        SaveDialog := TSaveDialog.Create( nil );
        SaveDialog.Title := 'Save...';

        if cbScripts.ItemIndex = 0 then begin
                SaveDialog.Filter := 'XML File (*.xml)|*.xml';
                SaveDialog.DefaultExt := 'xml';
        end
        else begin
                SaveDialog.Free;
                exit;
        end;

        if not SaveDialog.Execute then begin
                SaveDialog.Free;
                exit;
        end;

        Path := SaveDialog.FileName;
        SaveDialog.Free;

        Liste := TStringList.Create;
        if cbScripts.ItemIndex = 0 then begin
                Counter := 0;
                for Id := StrToInt( eFromID.Text ) to StrToInt( eToID.Text ) do begin
                        Liste.Add( Format( '<item id="%x">', [ ID ] ) );
                        Liste.Add( Format( '   <id>0x%x</id>', [ ID ] ) );
                        Zeile := eStandartDescription.Text;
                        if Pos( '%d', Zeile ) > 0 then begin
                                Zeile := Format( Zeile, [Counter] );
                                inc( Counter );
                        end;
                        Liste.Add( Format( '   <category>%s</category>', [Zeile] ) );
                        Liste.Add( '</item>' );
                        Liste.Add( '' );
                end;
        end;
        Liste.SaveToFile( Path );
        Liste.Free;
end;

procedure TMainForm.SetTag1Click(Sender: TObject);
var     Id, Tag : Integer;
begin
        Id := strtoint( lbArtStatic.Items[ lbArtStatic.ItemIndex ] );
        Tag := strtoint( InputBox( 'Tag', 'Gebt einen Tag an.', '0' ) );
        Art.SetStaticTag( Id, Tag );
end;

procedure TMainForm.cbLowMemoryClick(Sender: TObject);
begin
        Config.SetBool( 'LowMemory', cbLowMemory.Checked );
end;

procedure TMainForm.TimerLoadTimer(Sender: TObject);
begin
        TimerLoad.Enabled := False;
        btnActivateEditorClick( Sender );
end;

procedure TMainForm.btnCountTexClick(Sender: TObject);
begin
        if not Map.Loaded then begin
                showmessage( 'Load Map0.mul first.' );
                exit;
        end;
        Map.ProduceTexList( ExtractFilePath( Application.Exename ) + 'texturelist.csv', ExtractFilePath( Application.Exename ) + 'artlist.csv' );
end;

procedure TMainForm.btnChooseMapFileClick(Sender: TObject);
var     NewFile : String;
begin
        NewFile := BrowseFile( '*.txt' );
        if NewFile <> '' then begin
                eMapId.Text := NewFile;
        end;
end;

procedure TMainForm.btnStartMapIdChangeClick(Sender: TObject);
var     Liste : TStringList;
        IdArray : Array of MapId;
        I : Integer;
        SplitListe : TStringList;
begin
        if not Map.Loaded then begin
                showmessage( 'Load Map first.' );
                exit;
        end;

        Liste := TStringList.Create;
        Liste.LoadFromFile( eMapId.Text );

        if Liste.Count = 0 then exit;

        SetLength( IdArray, Liste.Count );
        for I := 0 to Liste.Count-1 do begin
                SplitListe := TStringList.Create;
                StrLib.Split( Liste.Strings[ I ], ' ', SplitListe );
                try
                        IdArray[ I ].Id := StrToInt( SplitListe.Strings[ 0 ] );
                except
                        showmessage( Format( 'Bug in Zeile %d', [I] ) );
                end;
                IdArray[ I ].IdListe := SplitListe.Strings[ 1 ];
                SplitListe.Free;
        end;

        Liste.Free;
        Map.ChangeIds( IdArray );
end;

procedure TMainForm.btnCreateStaticMapClick(Sender: TObject);
var     SaveDialog : TSaveDialog;
        Bitmap : TBitmap32;
begin
        if not Statics.loaded then begin
                showmessage( 'Load Statics first.' );
                exit;
        end;

        SaveDialog := TSaveDialog.Create( nil );
        SaveDialog.Filter := '*.bmp|*.bmp';
        SaveDialog.Title := 'Where do you want to save the staticmap?';

        if not SaveDialog.Execute then begin
                SaveDialog.Free;
                exit;
        end;

        Bitmap := Statics.CreateStaticMap;
        Bitmap.SaveToFile( SaveDialog.FileName );
        Bitmap.Free;

        SaveDialog.Free;
end;

procedure TMainForm.btnMapCopyClick(Sender: TObject);
var     SrcMap, TrgMap : TFileStream;
        SX, SY, TX, TY : Integer;
        SX1, SY1, SX2, SY2 : Integer;
        TX1, TY1, I : Integer;
        MapBlock : TMapBlock;
        Cell : TMapCell;
        BlockID : Integer;
        SrcHoehe, SrcBreite, TrgHoehe, TrgBreite : Integer;
begin
        SrcBreite := StrToInt( eMCSrcBreite.Text ) div 8;
        SrcHoehe := StrToInt( eMCSrcHoehe.Text ) div 8;
        TrgBreite := StrToInt( eMCTrgBreite.Text ) div 8;
        TrgHoehe := StrToInt( eMCTrgHoehe.Text ) div 8;

        SX1 := Min( StrToInt( eX1.Text ), StrToInt( eX2.Text ) );
        SY1 := Min( StrToInt( eY1.Text ), StrToInt( eY2.Text ) );
        SX2 := Max( StrToInt( eX1.Text ), StrToInt( eX2.Text ) );
        SY2 := Max( StrToInt( eY1.Text ), StrToInt( eY2.Text ) );

        TX1 := StrToInt( eTargX1.Text );
        TY1 := StrToInt( eTargY1.Text );

        SrcMap := TFileStream.Create( eMapCopyFrom.Text, fmOpenRead );
        if FileExists( eMapCopyTo.Text ) then begin
                TrgMap := TFileStream.Create( eMapCopyTo.Text, fmOpenReadWrite )
        end
        else begin
                TrgMap := TFileStream.Create( eMapCopyTo.Text, fmCreate );
                MapBlock.Header := 0;
                for I := 0 to 63 do begin
                        MapBlock.Cells[ I ].Id := 0;
                        MapBlock.Cells[ I ].Z := 0;
                end;
                for I := 0 to TrgHoehe*TrgBreite-1 do begin
                        TrgMap.Write( MapBlock, sizeof( TMapBlock ) );
                end;
        end;

        for SY := SY1 to SY2 do begin
                for SX := SX1 to SX2 do begin
                        BlockID := ( SX div 8 ) * SrcHoehe + ( SY div 8 );
                        SrcMap.Seek( BlockID*sizeof( TMapBlock ), soFromBeginning );
                        SrcMap.Read( MapBlock, sizeof( TMapBlock ) );

                        Cell := MapBlock.Cells[ (SY mod 8)*8 + (SX mod 8) ];
                        TX := TX1 + SX - SX1;
                        TY := TY1 + SY - SY1;

                        BlockID := ( TX div 8 ) * TrgHoehe + ( TY div 8 );
                        TrgMap.Seek( BlockID*sizeof( TMapBlock ), soFromBeginning );
                        TrgMap.Read( MapBlock, sizeof( TMapBlock ) );

                        MapBlock.Cells[ (TY mod 8)*8 + (TX mod 8) ] := Cell;

                        TrgMap.Seek( BlockID*sizeof( TMapBlock ), soFromBeginning );
                        TrgMap.Write( MapBlock, sizeof( TMapBlock ) );
                end;
                gMap.Percent := Ceil( (SY-SY1)*100/(SY2-SY1) );
                Application.ProcessMessages;
        end;

        SrcMap.Free;
        TrgMap.Free;
end;

procedure TMainForm.btnBrowseStaticIdxDeleteClick(Sender: TObject);
var     Dialog : TOpenDialog;
begin
        Dialog := TOpenDialog.Create( nil );
        Dialog.Title := 'Choose the Static Indexfile.';

        if not Dialog.Execute then begin
                Dialog.Free;
                exit;
        end;

        eStaticIdxDeletePath.Text := Dialog.FileName;
        Dialog.Free;
end;

procedure TMainForm.btnBrowseStaticMulDeleteClick(Sender: TObject);
var     Dialog : TOpenDialog;
begin
        Dialog := TOpenDialog.Create( nil );
        Dialog.Title := 'Choose the Static Datafile.';

        if not Dialog.Execute then begin
                Dialog.Free;
                exit;
        end;

        eStaticMulDeletePath.Text := Dialog.FileName;
        Dialog.Free;
end;

procedure TMainForm.btnStartStaticDeleteClick(Sender: TObject);
var     IdxFile, MulFile : TFileStream;
        IndexRecord : TIndexRecord;
begin
        if FileExists( eStaticMulDeletePath.Text ) then
                DeleteFile( eStaticMulDeletePath.Text );
        MulFile := TFileStream.Create( eStaticMulDeletePath.Text, fmCreate );
        MulFile.Seek( 0, soFromBeginning );
        MulFile.Free;

        IdxFile := TFileStream.Create( eStaticIdxDeletePath.Text, fmOpenWrite );
        IdxFile.Seek( 0, soFromBeginning );
        GaugeForm.Activate;
        while IdxFile.Position < IdxFile.Size do begin
                IndexRecord.Offset := -1;
                IndexRecord.Length := -1;
                IndexRecord.Extra := 0;
                IdxFile.Write( IndexRecord, 12 );
                GaugeForm.SetBalken( Trunc( IdxFile.Position*100/IdxFile.Size ) );
        end;
        GaugeForm.Deactivate;
end;

procedure TMainForm.btnSearchIDClick(Sender: TObject);
begin
        Statics.IDSearch( ExtractFilePath( Application.Exename ) );
end;

procedure TMainForm.btnMCBrowseFromClick(Sender: TObject);
var     Dialog : TOpenDialog;
begin
        Dialog := TOpenDialog.Create( nil );
        Dialog.Title := 'Choose the source mapfile to copy from.';

        if not Dialog.Execute then begin
                Dialog.Free;
                exit;
        end;

        eMapCopyFrom.Text := Dialog.FileName;
        Dialog.Free;
end;

procedure TMainForm.Button1Click(Sender: TObject);
var     Dialog : TSaveDialog;
begin
        Dialog := TSaveDialog.Create( nil );
        Dialog.Title := 'Choose the target mapfile to save to.';

        if not Dialog.Execute then begin
                Dialog.Free;
                exit;
        end;

        eMapCopyTo.Text := Dialog.FileName;
        Dialog.Free;
end;

procedure TMainForm.eMapCopyFromChange(Sender: TObject);
begin
        Config.SetString( 'MCFrom', eMapCopyFrom.Text );
end;

procedure TMainForm.eMapCopyToChange(Sender: TObject);
begin
        Config.SetString( 'MCTo', eMapCopyTo.Text );
end;

procedure TMainForm.eX1Change(Sender: TObject);
begin
        Config.SetString( 'MCX1', eX1.Text );
end;

procedure TMainForm.eY1Change(Sender: TObject);
begin
        Config.SetString( 'MCY1', eY1.Text );
end;

procedure TMainForm.eX2Change(Sender: TObject);
begin
        Config.SetString( 'MCX2', eX2.Text );
end;

procedure TMainForm.eY2Change(Sender: TObject);
begin
        Config.SetString( 'MCY2', eY2.Text );
end;

procedure TMainForm.eMCSrcBreiteChange(Sender: TObject);
begin
        Config.SetString( 'MCSrcWidth', eMCSrcBreite.Text );
end;

procedure TMainForm.eMCSrcHoeheChange(Sender: TObject);
begin
        Config.SetString( 'MCSrcHeight', eMCSrcHoehe.Text );
end;

procedure TMainForm.eTargX1Change(Sender: TObject);
begin
        Config.SetString( 'MCTargX1', eTargX1.Text );
end;

procedure TMainForm.eTargY1Change(Sender: TObject);
begin
        Config.SetString( 'MCTargY1', eTargY1.Text );
end;

procedure TMainForm.eMCTrgBreiteChange(Sender: TObject);
begin
        Config.SetString( 'MCTrgWidth', eMCTrgBreite.Text );
end;

procedure TMainForm.eMCTrgHoeheChange(Sender: TObject);
begin
        Config.SetString( 'MCTrgHeight', eMCTrgHoehe.Text );
end;

procedure TMainForm.btnExtractFromFileClick(Sender: TObject);
var     OpenDialog : TOpenDialog;
        I, Id : Integer;
        Bitmap : TBitmap32;
        Liste : TStringList;
        Path : String;
begin
        if not Art.loaded then exit;

        OpenDialog := TOpenDialog.Create( nil );
        OpenDialog.Title := 'Choose File to read IDs from...';
        OpenDialog.Filter := '*.txt|*.txt';

        if not OpenDialog.Execute then begin
                OpenDialog.Free;
                exit;
        end;

        Liste := TStringList.Create;
        Liste.LoadFromFile( OpenDialog.FileName );
        Path := ExtractFilePath( OpenDialog.FileName );
        OpenDialog.Free;

        GaugeForm.Activate;
        for I := 0 to Liste.Count-1 do begin
                if Liste.Strings[ I ] = '' then continue;
                Id := StrToInt( Liste.Strings[ I ] );

                GaugeForm.SetBalken( trunc( I*100/Liste.Count ) );
                if Art.StaticExists( Id ) then begin
                        if not FileExists( Path + Format( '%x', [Id] ) + '.bmp' ) then begin
                                Bitmap := Art.GetStaticTile( Id );
                                Bitmap.SaveToFile( Path + Format( '%x', [Id] ) + '.bmp' );
                                Bitmap.Free;
                        end;
                end;
        end;
        GaugeForm.Deactivate;
        Liste.Free;
        showmessage( 'Done.' );
end;

procedure TMainForm.SaveTo2Click(Sender: TObject);
var     Id : integer;
        SaveDialog : TSaveDialog;
begin
        Id := strtoint( lbMulti.Items[ lbMulti.ItemIndex ] );

        SaveDialog := TSaveDialog.Create( nil );
        SaveDialog.Filter := '*.txt|*.txt';
        SaveDialog.DefaultExt := 'txt';
        SaveDialog.FileName := Format( '0x%x.txt', [Id] );

        if not SaveDialog.Execute then begin
                SaveDialog.Free;
                exit;
        end;

        Multi.SaveToUOAText( Id, SaveDialog.FileName );
        SaveDialog.Free;
end;

procedure TMainForm.LoadfromUOATextfile1Click(Sender: TObject);
var     OpenDialog : TOpenDialog;
        Id : Integer;
begin
        OpenDialog := TOpenDialog.Create( nil );
        OpenDialog.Filter := '*.txt|*.txt';

        if not OpenDialog.Execute then begin
                OpenDialog.Free;
                exit;
        end;

        Id := strtoint( lbMulti.Items[ lbMulti.ItemIndex ] );
        Multi.LoadFromUOAText( Id, OpenDialog.FileName );
        lbMultiClick( Sender );

        OpenDialog.Free;
end;

procedure TMainForm.btnPBrowseClick(Sender: TObject);
var     Browse : TrmBrowseForFolder;
begin
        Browse := TrmBrowseForFolder.create( nil );

        if not Browse.Execute then begin
                Browse.Free;
                exit;
        end;

        ePDir.Text := Browse.Folder + '\';
        Browse.Free;

        Config.SetString( 'PatchDir', EPDir.Text );

        UpdatePatchMaps;
end;

procedure TMainForm.UpdatePatchMaps;
var     I : Integer;
begin
        if ePDir.Text = '' then
                exit;

        cbChooseMap.Clear;

        for I := 0 to 255 do begin
                if FileExists( Format( '%smap%d.mul', [ePDir.Text,I] ) ) and
                   FileExists( Format( '%sstaidx%d.mul', [ePDir.Text,I] ) ) and
                   FileExists( Format( '%sstatics%d.mul', [ePDir.Text,I] ) ) then begin
                   cbChooseMap.Items.Add( IntToStr( I ) );
                end;
        end;
end;

procedure TMainForm.btnPStartClick(Sender: TObject);
var     SaveDialog : TSaveDialog;
        FStream : TFileStream;
        IndexRecord : TIndexRecord;

        BlockID : LongWord;
        MapBlock : TMapBlock;
        Cell : TMapCell;
        Map, StaIdx, StaMul, ArtIdx, ArtMul, TexIdx, TexMul : TFileStream;

        XMin, XMax, YMin, YMax, X, Y : Integer;
        Hoehe, Breite : Word;
        Typ : Byte;
        PX, PY : Word;
        SX, SY : Byte;
        SZ : ShortInt;
        Id, Color : Word;
        TexList, ArtList : TList;
        I : Integer;
        Gefunden : Boolean;
begin
        SaveDialog := TSaveDialog.Create( nil );
        SaveDialog.Title := 'Where do you want to save the patch?';
        SaveDialog.Filter := '*.pvd|*.pvd';

        if not SaveDialog.Execute then begin
                SaveDialog.Free;
                exit;
        end;

        FStream := TFileStream.Create( SaveDialog.FileName, fmCreate );
        SaveDialog.Free;

        try
                XMin := Min( StrToInt( ePX1.Text ), StrToInt( ePX2.Text ) );
                XMax := Max( StrToInt( ePX1.Text ), StrToInt( ePX2.Text ) );
                YMin := Min( StrToInt( ePY1.Text ), StrToInt( ePY2.Text ) );
                YMax := Max( StrToInt( ePY1.Text ), StrToInt( ePY2.Text ) );
        except
                ShowMessage( 'Coordinates have to be Integer values.' );
                FStream.Free;
                Exit;
        end;

        if cbPMap.Checked then begin
                Map := TFileStream.Create( ePDir.Text + Format( 'map%s.mul', [cbChooseMap.Items[cbChooseMap.ItemIndex]] ), fmOpenRead );
        end
        else begin
                Map := nil;
        end;
        if cbPStatics.Checked then begin
                StaIdx := TFileStream.Create( ePDir.Text + Format( 'staidx%s.mul', [cbChooseMap.Items[cbChooseMap.ItemIndex]] ), fmOpenRead );
                StaMul := TFileStream.Create( ePDir.Text + Format( 'statics%s.mul', [cbChooseMap.Items[cbChooseMap.ItemIndex]] ), fmOpenRead );
        end
        else begin
                StaIdx := nil;
                StaMul := nil;
        end;
        if cbPArt.Checked then begin
                ArtIdx := TFileStream.Create( ePDir.Text + 'artidx.mul', fmOpenRead );
                ArtMul := TFileStream.Create( ePDir.Text + 'art.mul', fmOpenRead );
        end
        else begin
                ArtIdx := nil;
                ArtMul := nil;
        end;
        if cbPTex.Checked then begin
                TexIdx := TFileStream.Create( ePDir.Text + 'texidx.mul', fmOpenRead );
                TexMul := TFileStream.Create( ePDir.Text + 'texmaps.mul', fmOpenRead );
        end
        else begin
                TexIdx := nil;
                TexMul := nil;
        end;

        Hoehe := StrToInt( ePHeight.Text ) div 8;
        Breite := StrToInt( ePWidth.Text ) div 8;

        TexList := TList.Create;
        ArtList := TList.Create;

        for X := XMin to XMax do begin
                for Y := YMin to YMax do begin
                        BlockID := ( X div 8 ) * Hoehe + ( Y div 8 );
                        PX := X - XMin;
                        PY := Y - YMin;

                        if cbPMap.Checked then begin
                                Map.Seek( BlockId*sizeof( TMapBlock ), soFromBeginning );
                                Map.Read( MapBlock, sizeof( TMapBlock ) );
                                Cell := MapBlock.Cells[ (Y mod 8)*8+(X mod 8) ];

                                Typ := 0;
                                FStream.Write( Typ, 1 );
                                FStream.Write( PX, 2 );
                                FStream.Write( PY, 2 );
                                FStream.Write( Cell, sizeof( TMapCell ) );

                                if cbPTex.Checked then begin
                                        Gefunden := False;
                                        for I := 0 to TexList.Count-1 do
                                                if Word( TexList.Items[ I ] ) = Cell.Id then begin
                                                        Gefunden := True;
                                                        Break;
                                                end;

                                        if not Gefunden then begin
                                                TexList.Add( Pointer( Cell.Id ) );

                                                TexIdx.Seek( Cell.Id*12, soFromBeginning );
                                                TexIdx.Read( IndexRecord, 12 );

                                                Typ := 1;
                                                FStream.Write( Typ, 1 );
                                                FStream.Write( IndexRecord, 12 );

                                                if (IndexRecord.Offset <> -1) and (IndexRecord.Length <> -1) then begin
                                                        TexMul.Seek( IndexRecord.Offset, soFromBeginning );
                                                        FStream.CopyFrom( TexMul, IndexRecord.Length );
                                                end;
                                        end;
                                end;
                        end;
                        if cbPStatics.Checked then begin
                                StaIdx.Seek( BlockId*12, soFromBeginning );
                                StaIdx.Read( IndexRecord, 12 );

                                if (IndexRecord.Offset <> -1) and (IndexRecord.Length <> -1) then begin
                                        StaMul.Seek( IndexRecord.Offset, soFromBeginning );

                                        while StaMul.Position < IndexRecord.Offset+IndexRecord.Length do begin
                                                StaMul.Read( Id, 2 );
                                                StaMul.Read( SX, 1 );
                                                StaMul.Read( SY, 1 );
                                                StaMul.Read( SZ, 1 );
                                                StaMul.Read( Color, 2 );

                                                if ((X mod 8) <> SX) or ((Y mod 8) <> SY) then
                                                        continue;

                                                PX := ( BlockId div 512 )*8 + SX - XMin;
                                                PY := ( BlockId mod 512 )*8 + SY - YMin;

                                                Typ := 2;
                                                FStream.Write( Typ, 1 );
                                                FStream.Write( PX, 2 );
                                                FStream.Write( PY, 2 );
                                                FStream.Write( SZ, 1 );
                                                FStream.Write( Id, 2 );
                                                FStream.Write( Color, 2 );

                                                if cbPTex.Checked then begin
                                                        Gefunden := False;
                                                        for I := 0 to TexList.Count-1 do
                                                                if Word( ArtList.Items[ I ] ) = Id then begin
                                                                        Gefunden := True;
                                                                        Break;
                                                                end;

                                                        if not Gefunden then begin
                                                                ArtList.Add( Pointer( Cell.Id ) );

                                                                ArtIdx.Seek( Id*12, soFromBeginning );
                                                                ArtIdx.Read( IndexRecord, 12 );

                                                                Typ := 3;
                                                                FStream.Write( Typ, 1 );
                                                                FStream.Write( IndexRecord, 12 );

                                                                if (IndexRecord.Offset <> -1) and (IndexRecord.Length <> -1) then begin
                                                                        ArtMul.Seek( IndexRecord.Offset, soFromBeginning );
                                                                        FStream.CopyFrom( ArtMul, IndexRecord.Length );
                                                                end;
                                                        end;
                                                end;
                                        end;
                                end;
                        end;

                        gP.Percent := Round( 100*( (X-XMin)*(YMax-YMin+1) + (Y-YMin) ) / ( (XMax-XMin+1)*(YMax-YMin+1) ) );
                        Application.ProcessMessages;
                end;
        end;

        TexList.Free;
        ArtList.Free;

        FStream.Free;

        if Map <> nil then
                Map.Free;

        if StaIdx <> nil then
                StaIdx.Free;

        if StaMul <> nil then
                StaMul.Free;

        if ArtIdx <> nil then
                ArtIdx.Free;

        if ArtMul <> nil then
                ArtMul.Free;

        if TexIdx <> nil then
                TexIdx.Free;

        if TexMul <> nil then
                TexMul.Free;
end;

procedure TMainForm.btnStartHeightClick(Sender: TObject);
var     FStream : TFileStream;
        IndexRecord : TIndexRecord;

        BlockID : LongWord;
        MapBlock : TMapBlock;
        Cell : TMapCell;
        Map, StaIdx, StaMul : TFileStream;

        XMin, XMax, YMin, YMax, X, Y : Integer;
        Hoehe, Breite : Word;
        Typ : Byte;
        PX, PY : Word;
        SX, SY : Byte;
        SZ : ShortInt;
        Id, Color : Word;
        TexList, ArtList : TList;
        I : Integer;
        Gefunden : Boolean;
        Delta : Integer;
begin
        XMin := Min( StrToInt( ePX1.Text ), StrToInt( ePX2.Text ) );
        XMax := Max( StrToInt( ePX1.Text ), StrToInt( ePX2.Text ) );
        YMin := Min( StrToInt( ePY1.Text ), StrToInt( ePY2.Text ) );
        YMax := Max( StrToInt( ePY1.Text ), StrToInt( ePY2.Text ) );

        if cbCHMap.Checked then begin
                Map := TFileStream.Create( ePDir.Text + Format( 'map%s.mul', [cbChooseMap.Items[cbChooseMap.ItemIndex]] ), fmOpenReadWrite );
        end
        else begin
                Map := nil;
        end;
        if cbCHStatics.Checked then begin
                StaIdx := TFileStream.Create( ePDir.Text + Format( 'staidx%s.mul', [cbChooseMap.Items[cbChooseMap.ItemIndex]] ), fmOpenReadWrite );
                StaMul := TFileStream.Create( ePDir.Text + Format( 'statics%s.mul', [cbChooseMap.Items[cbChooseMap.ItemIndex]] ), fmOpenReadWrite );
        end
        else begin
                StaIdx := nil;
                StaMul := nil;
        end;

        Hoehe := StrToInt( ePHeight.Text ) div 8;
        Breite := StrToInt( ePWidth.Text ) div 8;

        Delta := StrToInt( eChangeHoehe.Text );

        for X := XMin to XMax do begin
                for Y := YMin to YMax do begin
                        BlockID := ( X div 8 ) * Hoehe + ( Y div 8 );

                        if cbCHMap.Checked then begin
                                Map.Seek( BlockId*sizeof( TMapBlock ), soFromBeginning );
                                Map.Read( MapBlock, sizeof( TMapBlock ) );

                                Cell := MapBlock.Cells[ (Y mod 8)*8+(X mod 8) ];
                                Cell.Z := Cell.Z + Delta;
                                MapBlock.Cells[ (Y mod 8)*8+(X mod 8) ] := Cell;

                                Map.Seek( BlockId*sizeof( TMapBlock ), soFromBeginning );
                                Map.Write( MapBlock, sizeof( TMapBlock ) );
                        end;
                        if cbCHStatics.Checked then begin
                                StaIdx.Seek( BlockId*12, soFromBeginning );
                                StaIdx.Read( IndexRecord, 12 );

                                if (IndexRecord.Offset <> -1) and (IndexRecord.Length <> -1) then begin
                                        StaMul.Seek( IndexRecord.Offset, soFromBeginning );

                                        while StaMul.Position < IndexRecord.Offset+IndexRecord.Length do begin
                                                StaMul.Read( Id, 2 );
                                                StaMul.Read( SX, 1 );
                                                StaMul.Read( SY, 1 );
                                                StaMul.Read( SZ, 1 );

                                                if ((X mod 8) = SX) and ((Y mod 8) = SY) then begin
                                                        SZ := SZ + Delta;
                                                        StaMul.Seek( -1, soFromCurrent );
                                                        StaMul.Write( SZ, 1 );
                                                end;

                                                StaMul.Read( Color, 2 );
                                        end;
                                end;
                        end;

                        gP.Percent := Round( 100*( (X-XMin)*(YMax-YMin+1) + (Y-YMin) ) / ( (XMax-XMin+1)*(YMax-YMin+1) ) );
                        Application.ProcessMessages;
                end;
        end;

        if Map <> nil then
                Map.Free;

        if StaIdx <> nil then
                StaIdx.Free;

        if StaMul <> nil then
                StaMul.Free;
end;

procedure TMainForm.btnStartApplyPatchClick(Sender: TObject);
var     OpenDialog : TOpenDialog;
        SaveDialog : TSaveDialog;
        FStream, BStream : TFileStream;
        IndexRecord, OldIndexRecord : TIndexRecord;

        BlockID : LongWord;
        MapBlock : TMapBlock;
        Cell : TMapCell;
        Map, StaIdx, StaMul, ArtIdx, ArtMul, TexIdx, TexMul : TFileStream;

        XMin, XMax, YMin, YMax, X, Y : Integer;
        Hoehe, Breite : Word;
        Typ : Byte;
        PX, PY : Word;
        SX, SY : Byte;
        SZ : ShortInt;
        Id, Color : Word;
        I : Integer;
        Gefunden : Boolean;
        Buf : PByteArray;
begin
        OpenDialog := TOpenDialog.Create( nil );
        OpenDialog.Title := 'Which patch do you want to apply?';
        OpenDialog.Filter := '*.pvd|*.pvd';

        if not OpenDialog.Execute then begin
                OpenDialog.Free;
                exit;
        end;

        FStream := TFileStream.Create( OpenDialog.FileName, fmOpenRead );
        OpenDialog.Free;

        if cbPBackup.Checked then begin
                SaveDialog := TSaveDialog.Create( nil );
                SaveDialog.Title := 'Where do you want to save your backup?';
                SaveDialog.Filter := '*.pvd|*.pvd';

                if not SaveDialog.Execute then begin
                        SaveDialog.Free;
                        BStream := nil;
                        cbPBackup.Checked := False;
                end
                else begin
                        BStream := TFileStream.Create( SaveDialog.FileName, fmCreate );
                        SaveDialog.Free;
                end;
        end;

        XMin := StrToInt( ePX1.Text );
        YMin := StrToInt( ePY1.Text );

        Map := TFileStream.Create( ePDir.Text + Format( 'map%s.mul', [cbChooseMap.Items[cbChooseMap.ItemIndex]] ), fmOpenReadWrite );

        StaIdx := TFileStream.Create( ePDir.Text + Format( 'staidx%s.mul', [cbChooseMap.Items[cbChooseMap.ItemIndex]] ), fmOpenReadWrite );
        StaMul := TFileStream.Create( ePDir.Text + Format( 'statics%s.mul', [cbChooseMap.Items[cbChooseMap.ItemIndex]] ), fmOpenReadWrite );

        ArtIdx := TFileStream.Create( ePDir.Text + 'artidx.mul', fmOpenReadWrite );
        ArtMul := TFileStream.Create( ePDir.Text + 'art.mul', fmOpenReadWrite );

        TexIdx := TFileStream.Create( ePDir.Text + 'texidx.mul', fmOpenReadWrite );
        TexMul := TFileStream.Create( ePDir.Text + 'texmaps.mul', fmOpenReadWrite );

        Hoehe := StrToInt( ePHeight.Text ) div 8;
        Breite := StrToInt( ePWidth.Text ) div 8;

        FStream.Seek( 0, soFromBeginning );

        while FStream.Position < FStream.Size do begin
                FStream.Read( Typ, 1 );

                Case Typ of
                        //Map
                        0 : begin
                                FStream.Read( PX, 2 );
                                FStream.Read( PY, 2 );
                                FStream.Read( Cell, sizeof( TMapCell ) );

                                X := XMin + PX;
                                Y := YMin + PY;
                                BlockID := ( X div 8 ) * Hoehe + ( Y div 8 );

                                Map.Seek( BlockID*sizeof( TMapBlock ), soFromBeginning );
                                Map.Read( MapBlock, sizeof( TMapBlock ) );

                                if cbPBackup.Checked then begin
                                        BStream.Write( Typ, 1 );
                                        BStream.Write( PX, 2 );
                                        BStream.Write( PY, 2 );
                                        BStream.Write( MapBlock.Cells[ (Y mod 8)*8+(X mod 8) ], sizeof( TMapCell ) );
                                end;

                                MapBlock.Cells[ (Y mod 8)*8+(X mod 8) ] := Cell;
                                Map.Seek( BlockID*sizeof( TMapBlock ), soFromBeginning );
                                Map.Write( MapBlock, sizeof( TMapBlock ) );
                        end;
                        //Tex
                        1 : begin
                                FStream.Read( Id, 2 );
                                FStream.Read( IndexRecord, 12 );

                                if cbPBackup.Checked and (Id*12 < TexIdx.Size) then begin
                                        TexIdx.Seek( Id*12, soFromBeginning );
                                        TexIdx.Read( OldIndexRecord, 12 );

                                        BStream.Write( Typ, 1 );
                                        BStream.Write( Id, 2 );
                                        BStream.Write( IndexRecord, 12 );

                                        if (IndexRecord.Offset <> -1) and (IndexRecord.Length <> -1) then begin
                                                TexMul.Seek( IndexRecord.Offset, soFromBeginning );
                                                BStream.CopyFrom( TexMul, IndexRecord.Length );
                                        end;
                                end;

                                while Id*12 > TexIdx.Size do begin
                                        OldIndexRecord.Offset := -1;
                                        OldIndexRecord.Length := -1;
                                        OldIndexRecord.Extra := 0;
                                        TexIdx.Seek( 0, soFromEnd );
                                        TexIdx.Write( OldIndexRecord, 12 );
                                end;

                                TexIdx.Seek( Id*12, soFromBeginning );

                                if (IndexRecord.Offset <> -1) and (IndexRecord.Length <> -1) then begin
                                        IndexRecord.Offset := TexMul.Size;
                                        TexIdx.Write( IndexRecord, 12 );

                                        TexMul.Seek( 0, soFromEnd );
                                        TexMul.CopyFrom( FStream, IndexRecord.Length );
                                end
                                else begin
                                        TexIdx.Write( IndexRecord, 12 );
                                end;
                        end;
                        //Static
                        2 : begin
                                FStream.Read( PX, 2 );
                                FStream.Read( PY, 2 );
                                FStream.Read( SZ, 1 );
                                FStream.Read( Id, 2 );
                                FStream.Read( Color, 2 );

                                X := XMin + PX;
                                Y := YMin + PY;
                                BlockID := ( X div 8 ) * Hoehe + ( Y div 8 );

                                if cbPBackup.Checked then begin
                                        Typ := 4;
                                        BStream.Write( Typ, 1 );
                                        BStream.Write( PX, 2 );
                                        BStream.Write( PY, 2 );
                                        BStream.Write( SZ, 1 );
                                        BStream.Write( Id, 2 );
                                        BStream.Write( Color, 2 );
                                        Typ := 2;
                                end;

                                StaIdx.Seek( BlockID*12, soFromBeginning );
                                StaIdx.Read( OldIndexRecord, 12 );

                                IndexRecord.Offset := StaMul.Size;
                                if OldIndexRecord.Length = -1 then
                                        IndexRecord.Length := 7
                                else
                                        IndexRecord.Length := OldIndexRecord.Length+7;

                                StaIdx.Seek( -12, soFromCurrent );
                                StaIdx.Write( IndexRecord, 12 );

                                if OldIndexRecord.Offset <> -1 then begin
                                        StaMul.Seek( OldIndexRecord.Offset, soFromBeginning );
                                        GetMem( Buf, OldIndexRecord.Length );
                                        StaMul.Read( Buf^, OldIndexRecord.Length );
                                        StaMul.Seek( 0, soFromEnd );
                                        StaMul.Write( Buf^, OldIndexRecord.Length );
                                        FreeMem( Buf );
                                end
                                else begin
                                        StaMul.Seek( 0, soFromEnd );
                                end;

                                SX := X mod 8;
                                SY := Y mod 8;

                                StaMul.Write( Id, 2 );
                                StaMul.Write( SX, 1 );
                                StaMul.Write( SY, 1 );
                                StaMul.Write( SZ, 1 );
                                StaMul.Write( Color, 2 );
                        end;
                        //Art
                        3 : begin
                                FStream.Read( Id, 2 );
                                FStream.Read( IndexRecord, 12 );

                                if cbPBackup.Checked and (Id*12 < ArtIdx.Size) then begin
                                        ArtIdx.Seek( Id*12, soFromBeginning );
                                        ArtIdx.Read( OldIndexRecord, 12 );

                                        BStream.Write( Typ, 1 );
                                        BStream.Write( Id, 2 );
                                        BStream.Write( IndexRecord, 12 );

                                        if (IndexRecord.Offset <> -1) and (IndexRecord.Length <> -1) then begin
                                                ArtMul.Seek( IndexRecord.Offset, soFromBeginning );
                                                BStream.CopyFrom( ArtMul, IndexRecord.Length );
                                        end;
                                end;

                                while Id*12 > ArtIdx.Size do begin
                                        OldIndexRecord.Offset := -1;
                                        OldIndexRecord.Length := -1;
                                        OldIndexRecord.Extra := 0;
                                        ArtIdx.Seek( 0, soFromEnd );
                                        ArtIdx.Write( OldIndexRecord, 12 );
                                end;

                                ArtIdx.Seek( Id*12, soFromBeginning );

                                if (IndexRecord.Offset <> -1) and (IndexRecord.Length <> -1) then begin
                                        IndexRecord.Offset := ArtMul.Size;
                                        ArtIdx.Write( IndexRecord, 12 );

                                        ArtMul.Seek( 0, soFromEnd );
                                        ArtMul.CopyFrom( FStream, IndexRecord.Length );
                                end
                                else begin
                                        ArtIdx.Write( IndexRecord, 12 );
                                end;
                        end;
                        //Remove Static
                        4 : begin
                        end;
                end;

                gP.Percent := Round( 100*FStream.Position/FStream.Size );
                Application.ProcessMessages;
        end;

        if BStream <> nil then
                BStream.Free;

        FStream.Free;

        if Map <> nil then
                Map.Free;

        if StaIdx <> nil then
                StaIdx.Free;

        if StaMul <> nil then
                StaMul.Free;

        if ArtIdx <> nil then
                ArtIdx.Free;

        if ArtMul <> nil then
                ArtMul.Free;

        if TexIdx <> nil then
                TexIdx.Free;

        if TexMul <> nil then
                TexMul.Free;
end;

procedure TMainForm.Button2Click(Sender: TObject);
begin
        Art.FillStatics;
end;

procedure TMainForm.Button3Click(Sender: TObject);
var     Dialog : TOpenDialog;
begin
        Dialog := TOpenDialog.Create( nil );
        Dialog.Title := 'Choose the Static Indexfile.';

        if not Dialog.Execute then begin
                Dialog.Free;
                exit;
        end;

        eMSIdx1.Text := Dialog.FileName;
        Dialog.Free;
end;

procedure TMainForm.Button4Click(Sender: TObject);
var     Dialog : TOpenDialog;
begin
        Dialog := TOpenDialog.Create( nil );
        Dialog.Title := 'Choose the Static Indexfile.';

        if not Dialog.Execute then begin
                Dialog.Free;
                exit;
        end;

        eMSMul1.Text := Dialog.FileName;
        Dialog.Free;
end;

procedure TMainForm.Button6Click(Sender: TObject);
var     Dialog : TOpenDialog;
begin
        Dialog := TOpenDialog.Create( nil );
        Dialog.Title := 'Choose the Static Indexfile.';

        if not Dialog.Execute then begin
                Dialog.Free;
                exit;
        end;

        eMSIdx2.Text := Dialog.FileName;
        Dialog.Free;
end;

procedure TMainForm.Button5Click(Sender: TObject);
var     Dialog : TOpenDialog;
begin
        Dialog := TOpenDialog.Create( nil );
        Dialog.Title := 'Choose the Static Indexfile.';

        if not Dialog.Execute then begin
                Dialog.Free;
                exit;
        end;

        eMSMul2.Text := Dialog.FileName;
        Dialog.Free;
end;

procedure TMainForm.btnMSRunClick(Sender: TObject);
var     Idx1, Mul1, Idx2, Mul2, TIdx, TMul : TFileStream;
        IndexRecord : TIndexRecord;
        Item : Record Id : Word; X, Y : Byte; Z : ShortInt; Color : Word; end;
        Dialog : TOpenDialog;
        I, Position : Integer;
begin
        Dialog := TOpenDialog.Create( nil );
        Dialog.Title := 'Choose Target Staidx.mul';

        if not Dialog.Execute then begin
                Dialog.Free;
                exit;
        end;

        TIdx := TFileStream.Create( Dialog.FileName, fmCreate );

        Dialog.Title := 'Choose Target Statics.mul';

        if not Dialog.Execute then begin
                TIdx.Free;
                Dialog.Free;
                exit;
        end;

        TMul := TFileStream.Create( Dialog.FileName, fmCreate );
        Dialog.Free;

        if not (FileExists( eMSIdx1.Text ) and FileExists( eMSMul1.Text ) and FileExists( eMSIdx2.Text ) and FileExists( eMSMul2.Text ) ) then begin
                TIdx.Free;
                TMul.Free;
                exit;
        end;

        Idx1 := TFileStream.Create( eMSIdx1.Text, fmOpenRead );
        Mul1 := TFileStream.Create( eMSMul1.Text, fmOpenRead );
        Idx2 := TFileStream.Create( eMSIdx2.Text, fmOpenRead );
        Mul2 := TFileStream.Create( eMSMul2.Text, fmOpenRead );

        Idx1.Seek( 0, soFromBeginning );
        Idx2.Seek( 0, soFromBeginning );
        TIdx.Seek( 0, soFromBeginning );
        TMul.Seek( 0, soFromBeginning );

        for I := 0 to (Max( Idx1.Size, Idx2.Size ) div 12)-1 do begin
                Position := TMul.Position;
                if Idx1.Size > I*12 then begin
                        Idx1.Seek( I*12, soFromBeginning );
                        Idx1.Read( IndexRecord, 12 );

                        if (IndexRecord.Offset <> -1) and (IndexRecord.Length <> -1) then begin
                                Mul1.Seek( IndexRecord.Offset, soFromBeginning );
                                while Mul1.Position < IndexRecord.Offset+IndexRecord.Length do begin
                                        Mul1.Read( Item, 7 );
                                        TMul.Write( Item, 7 );
                                end;
                        end;
                end;

                if Idx2.Size > I*12 then begin
                        Idx2.Seek( I*12, soFromBeginning );
                        Idx2.Read( IndexRecord, 12 );

                        if (IndexRecord.Offset <> -1) and (IndexRecord.Length <> -1) then begin
                                Mul2.Seek( IndexRecord.Offset, soFromBeginning );
                                while Mul2.Position < IndexRecord.Offset+IndexRecord.Length do begin
                                        Mul2.Read( Item, 7 );
                                        TMul.Write( Item, 7 );
                                end;
                        end;
                end;

                if TMul.Position > Position then begin
                        IndexRecord.Offset := Position;
                        IndexRecord.Length := TMul.Position - Position;
                        IndexRecord.Extra := 0;
                end
                else begin
                        IndexRecord.Offset := -1;
                        IndexRecord.Length := -1;
                        IndexRecord.Extra := 0;
                end;
                TIdx.Write( IndexRecord, 12 );
        end;

        Idx1.Free;
        Mul1.Free;
        Idx2.Free;
        Mul2.Free;

        TIdx.Free;
        TMul.Free;

        Showmessage( 'Merging done.' );
end;

procedure TMainForm.Button7Click(Sender: TObject);
var     NewFile : String;
begin
        NewFile := BrowseFile( '*.*' );
        if NewFile <> '' then begin
                eCutFileName.Text := NewFile;
        end;
end;

procedure TMainForm.Button8Click(Sender: TObject);
var     FOld, FNew : TFileStream;
begin
        FOld := TFileStream.Create( eCutFileName.Text, fmOpenRead );
        FOld.Seek( 0, soFromBeginning );

        if FileExists( eCutFileName.Text + '.new' ) then
                DeleteFile( eCutFileName.Text + '.new' );

        FNew := TFileStream.Create( eCutFileName.Text + '.new', fmCreate );
        FNew.Seek( 0, soFromBeginning );

        FNew.CopyFrom( FOld, StrToInt( eCutToSize.Text ) );
        FNew.Free;

        FOld.Free;

        Showmessage( 'File cut.' );
end;

procedure TMainForm.Button9Click(Sender: TObject);
var     I : Integer;
        Name : String;
begin
        TileChange := True;
        Tiledata.FillStatics;

        lbTiledataStatic.Clear;
        lbTiledataStatic.Items.BeginUpdate;
        for i:= 0 to $FFFF do begin
                Name := Tiledata.GetStaticName( i );
                lbTiledataStatic.Items.Add( Format( '0x%x %s', [ i, Name ] ) );
        end;
        for I := $4000 to Tiledata.GetStaticTileCount-1 do begin
                Name := Tiledata.GetStaticName( i );
                lbTiledataStatic.Items.Add( Format( '0x%x %s', [ i, Name ] ) );
        end;

        lbTiledataStatic.Items.EndUpdate;

        TileChange := False;
end;

procedure TMainForm.LoadfromDirectory1Click(Sender: TObject);
var     Dir : TSearchRec;
        Path : String;
        Browse : TrmBrowseForFolder;
        DateiListe : TStringList;
        I, Id : Integer;
begin
        //Zuerst suchen wir uns das Verzeichnis
        Browse := TrmBrowseForFolder.create( nil );
        Browse.Title := 'Choose a directory';

        if not Browse.Execute then begin
                Browse.Free;
                exit;
        end;

        Path := Browse.Folder + '\';
        Browse.Free;

        //Verzeichnis haben wir, suchen wir uns alle Dateien drin und schreiben
        //sie in eine Liste

        if FindFirst( Path + '*', faArchive, Dir ) <> 0 then begin
                //Verzeichnis ist leer
                ShowMessage( 'Your directory is empty.' );
                exit;
        end;

        //Liste initialisieren wo die Dateinamen drin gespeichert werden sollen
        DateiListe := TStringList.Create;
        repeat
                DateiListe.Add( Path + Dir.Name );
        until FindNext( Dir ) <> 0;
        //Das war die letzte Datei
        FindClose( Dir );
        //Dateisuchdingends wieder freigeben


        //Jetzt haben wir in unsere Liste alle Dateinamen die wir patchen wollen
        //sie patchen

        //Test ob die Art überhaupt geladen ist
        if not Art.loaded then begin
                //Dateiliste freigeben bevor wir die procedure beenden
                DateiListe.Free;
                Showmessage( 'Art not loaded.' );
                exit;
        end;

        //Als erste ID nehmen wir die ausgewählte, danach immer die nächste freie
        //Dafür lesen wir einfach aus welche Id in der Art - Listbox steht
        //Ist notwendig, da z.b. wenn nur leere Ids angezeigt werden, die Id nicht
        //mit der Position in der Liste übereinstimmt
        Id := StrToInt( lbArtStatic.Items[ lbArtStatic.ItemIndex ] );

        //Der Reihe nach einpatchen
        for I := 0 to DateiListe.Count-1 do begin
                Art.LoadStaticTile( Id, DateiListe.Strings[ I ] );

                //Wir erhöhen die Id um 1
                Inc( Id );

                //Und wiederholen das solange, bis die Id frei ist
                while Art.StaticExists( Id ) do begin
                        Inc( Id );

                        if Id >= Art.GetStaticCount then begin
                                //Wir haben schon eine höhere Id erreicht als die ArtIdx.mul
                                //gross ist => keine freie Id mehr vorhanden, wir melden das
                                //und hören auf
                                Showmessage( 'No empty Id left.' );

                                //Wieder Liste freigeben bevor wir die procedure beenden
                                DateiListe.Free;

                                Showmessage( IntToStr( I+1 ) + ' graphics patched.' );

                                exit;
                        end;
                end;
        end;

        //Wir sagen noch wieviele Grafiken wir gepatcht haben
        Showmessage( IntToStr( DateiListe.Count ) + ' graphics patched.' );

        //Und geben unsere Liste frei
        DateiListe.Free;
end;

procedure TMainForm.btnCreateEmptyClick(Sender: TObject);
var     SaveDialog : TrmBrowseForFolder;
        Path : String;
        fStream : TFileStream;
        I : Integer;
        IndexRecord : TIndexRecord;
        B : Byte;
begin
        Case cbCreateEmpty.ItemIndex of
                -1 : begin
                        Exit;
                end;
                0 : begin
                        SaveDialog := TrmBrowseForFolder.create( nil );
                        SaveDialog.Title := 'Where do you want to save the files?';
                        if not SaveDialog.Execute then begin
                                SaveDialog.Free;
                                Exit;
                        end;

                        Path := SaveDialog.Folder + '\';
                        SaveDialog.Free;

                        IndexRecord.Offset := -1;
                        IndexRecord.Length := -1;
                        IndexRecord.Extra := -1;

                        fStream := TFileStream.Create( Path + 'anim.mul', fmCreate );
                        fStream.Free;

                        fStream := TFileStream.Create( Path + 'anim.idx', fmCreate );
                        fStream.Seek( 0, soFromBeginning );

                        for I := 0 to 148810-1 do begin
                                fStream.Write( IndexRecord, 12 );
                        end;

                        fStream.Free;
                end;
                1 : begin
                        SaveDialog := TrmBrowseForFolder.create( nil );
                        SaveDialog.Title := 'Where do you want to save the files?';
                        if not SaveDialog.Execute then begin
                                SaveDialog.Free;
                                Exit;
                        end;

                        Path := SaveDialog.Folder + '\';
                        SaveDialog.Free;

                        IndexRecord.Offset := -1;
                        IndexRecord.Length := -1;
                        IndexRecord.Extra := -1;

                        fStream := TFileStream.Create( Path + 'art.mul', fmCreate );
                        fStream.Free;

                        fStream := TFileStream.Create( Path + 'artidx.mul', fmCreate );
                        fStream.Seek( 0, soFromBeginning );

                        for I := 0 to $FFFF do begin
                                fStream.Write( IndexRecord, 12 );
                        end;

                        fStream.Free;
                end;
                2 : begin
                        SaveDialog := TrmBrowseForFolder.create( nil );
                        SaveDialog.Title := 'Where do you want to save the files?';
                        if not SaveDialog.Execute then begin
                                SaveDialog.Free;
                                Exit;
                        end;

                        Path := SaveDialog.Folder + '\';
                        SaveDialog.Free;

                        IndexRecord.Offset := -1;
                        IndexRecord.Length := -1;
                        IndexRecord.Extra := -1;

                        fStream := TFileStream.Create( Path + 'gumpart.mul', fmCreate );
                        fStream.Free;

                        fStream := TFileStream.Create( Path + 'gumpidx.mul', fmCreate );
                        fStream.Seek( 0, soFromBeginning );

                        for I := 0 to $EEFF do begin
                                fStream.Write( IndexRecord, 12 );
                        end;

                        fStream.Free;
                end;
                3 : begin
                        SaveDialog := TrmBrowseForFolder.create( nil );
                        SaveDialog.Title := 'Where do you want to save the files?';
                        if not SaveDialog.Execute then begin
                                SaveDialog.Free;
                                Exit;
                        end;

                        Path := SaveDialog.Folder + '\';
                        SaveDialog.Free;

                        IndexRecord.Offset := -1;
                        IndexRecord.Length := -1;
                        IndexRecord.Extra := -1;

                        fStream := TFileStream.Create( Path + 'texmaps.mul', fmCreate );
                        fStream.Free;

                        fStream := TFileStream.Create( Path + 'texidx.mul', fmCreate );
                        fStream.Seek( 0, soFromBeginning );

                        for I := 0 to $FFFF do begin
                                fStream.Write( IndexRecord, 12 );
                        end;

                        fStream.Free;
                end;
                4 : begin
                        SaveDialog := TrmBrowseForFolder.create( nil );
                        SaveDialog.Title := 'Where do you want to save the files?';
                        if not SaveDialog.Execute then begin
                                SaveDialog.Free;
                                Exit;
                        end;

                        Path := SaveDialog.Folder + '\';
                        SaveDialog.Free;

                        IndexRecord.Offset := -1;
                        IndexRecord.Length := -1;
                        IndexRecord.Extra := -1;

                        fStream := TFileStream.Create( Path + 'sound.mul', fmCreate );
                        fStream.Free;

                        fStream := TFileStream.Create( Path + 'soundidx.mul', fmCreate );
                        fStream.Seek( 0, soFromBeginning );

                        for I := 0 to $FFF do begin
                                fStream.Write( IndexRecord, 12 );
                        end;

                        fStream.Free;
                end;
                5 : begin
                        SaveDialog := TrmBrowseForFolder.create( nil );
                        SaveDialog.Title := 'Where do you want to save the files?';
                        if not SaveDialog.Execute then begin
                                SaveDialog.Free;
                                Exit;
                        end;

                        Path := SaveDialog.Folder + '\';
                        SaveDialog.Free;

                        IndexRecord.Offset := -1;
                        IndexRecord.Length := -1;
                        IndexRecord.Extra := -1;

                        fStream := TFileStream.Create( Path + 'statics0.mul', fmCreate );
                        fStream.Free;

                        fStream := TFileStream.Create( Path + 'staidx0.mul', fmCreate );
                        fStream.Seek( 0, soFromBeginning );

                        for I := 0 to 393216-1 do begin
                                fStream.Write( IndexRecord, 12 );
                        end;

                        fStream.Free;
                end;
                6 : begin
                        SaveDialog := TrmBrowseForFolder.create( nil );
                        SaveDialog.Title := 'Where do you want to save the files?';
                        if not SaveDialog.Execute then begin
                                SaveDialog.Free;
                                Exit;
                        end;

                        Path := SaveDialog.Folder + '\';
                        SaveDialog.Free;

                        IndexRecord.Offset := -1;
                        IndexRecord.Length := -1;
                        IndexRecord.Extra := -1;

                        fStream := TFileStream.Create( Path + 'map0.mul', fmCreate );
                        fStream.Seek( 0, soFromBeginning );

                        b := 0;

                        for I := 0 to 77070336-1 do begin
                                fStream.Write( b, 1 );
                        end;

                        fStream.Free;
                end;
                7 : begin
                        SaveDialog := TrmBrowseForFolder.create( nil );
                        SaveDialog.Title := 'Where do you want to save the files?';
                        if not SaveDialog.Execute then begin
                                SaveDialog.Free;
                                Exit;
                        end;

                        Path := SaveDialog.Folder + '\';
                        SaveDialog.Free;

                        IndexRecord.Offset := -1;
                        IndexRecord.Length := -1;
                        IndexRecord.Extra := -1;

                        fStream := TFileStream.Create( Path + 'tiledata.mul', fmCreate );
                        fStream.Seek( 0, soFromBeginning );

                        b := 0;

                        for I := 0 to 1644544-1 do begin
                                fStream.Write( b, 1 );
                        end;

                        fStream.Free;
                end;
                8 : begin
                        SaveDialog := TrmBrowseForFolder.create( nil );
                        SaveDialog.Title := 'Where do you want to save the files?';
                        if not SaveDialog.Execute then begin
                                SaveDialog.Free;
                                Exit;
                        end;

                        Path := SaveDialog.Folder + '\';
                        SaveDialog.Free;

                        IndexRecord.Offset := -1;
                        IndexRecord.Length := -1;
                        IndexRecord.Extra := -1;

                        fStream := TFileStream.Create( Path + 'verdata.mul', fmCreate );
                        fStream.Seek( 0, soFromBeginning );

                        b := 0;

                        for I := 0 to 3 do begin
                                fStream.Write( b, 1 );
                        end;

                        fStream.Free;
                end;
        end;
end;

procedure TMainForm.btnSedinBrowseGumpClick(Sender: TObject);
var     OpenDialog : TOpenDialog;
begin
        OpenDialog := TOpenDialog.Create( nil );
        OpenDialog.Filter := '*.bmp|*.bmp';

        if not OpenDialog.Execute then begin
                OpenDialog.Free;
                exit;
        end;

        if not FileExists(OpenDialog.FileName) then begin
                Application.MessageBox( 'Diese Datei ist nicht existent. Bitte wählen sie einen gültigen Dateinamen.', 'Datei nicht gefunden', MB_OK+MB_ICONERROR );
                OpenDialog.Free;
                Exit;
        end;

        eSedinPathGump.Text := OpenDialog.FileName;
        OpenDialog.Free;
end;

procedure TMainForm.btnSedinBrowseArtClick(Sender: TObject);
var     OpenDialog : TOpenDialog;
begin
        OpenDialog := TOpenDialog.Create( nil );
        OpenDialog.Filter := '*.bmp|*.bmp';

        if not OpenDialog.Execute then begin
                OpenDialog.Free;
                exit;
        end;

        if not FileExists(OpenDialog.FileName) then begin
                Application.MessageBox( 'Diese Datei ist nicht existent. Bitte wählen sie einen gültigen Dateinamen.', 'Datei nicht gefunden', MB_OK+MB_ICONERROR );
                OpenDialog.Free;
                Exit;
        end;

        eSedinPathArt.Text := OpenDialog.FileName;
        OpenDialog.Free;
end;

procedure TMainForm.cbSedinPathClick(Sender: TObject);
var     GumpId, ArtId, OldAnimId, NewAnimId : Word;
        StaticTileRecord : TStaticTileRecord;
begin
        if not Gump.loaded then begin
                showmessage( 'Load Gumps.' );
                exit;
        end;

        if not Art.loaded then begin
                showmessage( 'Load Art.' );
                exit;
        end;

        if not Animation.Loaded then begin
                showmessage( 'Load Anims.' );
                exit;
        end;

        if not Tiledata.Loaded then begin
                showmessage( 'Load Tiledata.' );
                exit;
        end;

        if cbSedinLayer.ItemIndex = -1 then begin
                showmessage( 'Choose a layer.' );
                exit;
        end;

        GumpId := StrToInt( eSedinGumpId.Text );
        ArtId := StrToInt( eSedinArtId.Text );
        OldAnimId := StrToInt( eSedinAnimId.Text );
        NewAnimId := GumpId - 50000;

        Gump.LoadGump( GumpId, eSedinPathGump.Text );
        if eSedinPathGumpW.Text <> '' then
                Gump.LoadGump( GumpId, eSedinPathGumpW.Text );
        Art.LoadStaticTile( ArtId, eSedinPathArt.Text );
        Animation.DupeAnim( OldAnimId, NewAnimId, '' );

        StrPCopy( StaticTileRecord.Name, eSedinName.Text );
        StaticTileRecord.AnimID := NewAnimId;
        StaticTileRecord.Quantity := 0;
        StaticTileRecord.Weight := StrToInt( eSedinWeight.Text );
        StaticTileRecord.Quality := cbSedinLayer.ItemIndex;
        StaticTileRecord.Unknown1 := 0;
        StaticTileRecord.Unknown2 := 0;
        StaticTileRecord.Unknown3 := 0;
        StaticTileRecord.Unknown4 := 0;
        StaticTileRecord.Unknown5 := 0;
        StaticTileRecord.Hue := 0;
        StaticTileRecord.Height := 0;
        StaticTileRecord.Flags := 0;
        StaticTileRecord.Flags := StaticTileRecord.Flags + AddFlag( dPartialHue, cbSedinPartialHue.Checked );
        StaticTileRecord.Flags := StaticTileRecord.Flags + AddFlag( dLightSource, cbSedinLightSource.Checked );
        StaticTileRecord.Flags := StaticTileRecord.Flags + AddFlag( dWeapon, cbSedinWeapon.Checked );
        StaticTileRecord.Flags := StaticTileRecord.Flags + AddFlag( dArmor, cbSedinArmor.Checked );
        StaticTileRecord.Flags := StaticTileRecord.Flags + AddFlag( dWearable, cbSedinWearable.Checked );

        Tiledata.SetStaticTile( ArtId, StaticTileRecord );
end;

procedure TMainForm.cbSedinClearClick(Sender: TObject);
begin
        eSedinPathGump.Text := '';
        eSedinPathArt.Text := '';

        eSedinGumpId.Text := '';
        eSedinArtId.Text := '';
        eSedinAnimId.Text := '';

        cbSedinLayer.ItemIndex := -1;
        cbSedinWearable.Checked := True;
        cbSedinWeapon.Checked := False;
        cbSedinArmor.Checked := False;
        cbSedinPartialHue.Checked := False;
        cbSedinLightSource.Checked := False;

        eSedinName.Text := '';
        eSedinWeight.Text := '';
end;

procedure TMainForm.Button11Click(Sender: TObject);
var     SaveDialog : TSaveDialog;
        Path : String;
        GesamtMap : TBitmap32;
        MapWidth, MapHeight : Integer;
        mulStream : TFileStream;
        MapBlock : TMapBlock;
        MapCell : TMapCell;
        X, Y, CX, CY : Integer;
        BlockID : Integer;
        IndexRecord : TIndexRecord;
        staIdx, staMul : TFileStream;
        ZLevel : Array[0..63] of ShortInt;
        SId, SColor : Word;
        SX, SY : Byte;
        SZ : ShortInt;
begin
        if not RadarCol.loaded then begin
                showmessage( 'load radarcol.mul first.' );
                exit;
        end;

        SaveDialog := TSaveDialog.Create( nil );
        SaveDialog.Title := 'Where do you want to save the Radarmap to?';
        SaveDialog.Filter := '*.bmp|*.bmp';
        SaveDialog.DefaultExt := 'bmp';

        if not SaveDialog.Execute then begin
                SaveDialog.Free;
                Exit;
        end;

        Path := SaveDialog.FileName;
        SaveDialog.Free;

        MapWidth := Map.Width;
        MapHeight := Map.Height;

        GesamtMap := TBitmap32.Create;
        GesamtMap.Width := MapWidth;
        GesamtMap.Height := MapHeight;
        GesamtMap.Clear( Color32( clBtnFace ) );

        if Map.Loaded then begin
                Map.Free;
                Map := TMap.Create;
        end;

        if Statics.loaded then begin
                Statics.Free;
                Statics := TStatics.Create;
        end;

        mulStream := TFileStream.Create( ePathMap.Text, fmOpenRead );
        staIdx := TFileStream.Create( ePathStaticIdx.Text, fmOpenRead );
        staMul := TFileStream.Create( ePathStaticMul.Text, fmOpenRead );

        for X := 0 to (MapWidth div 8)-1 do begin
                for Y := 0 to (MapHeight div 8)-1 do begin
                        lWorldRadarMap.Caption := Format( '%d %', [Round(100*(X*(MapHeight div 8)+Y)/(MapWidth*MapHeight/64))] );
                        Application.ProcessMessages;

                        BlockID := x * (MapHeight div 8) + y;
                        mulStream.Seek( BlockID*sizeof( TMapBlock ), soFromBeginning );
                        mulStream.Read( MapBlock, sizeof( TMapBlock ) );

                        for CY := 0 to 7 do
                                for CX := 0 to 7 do begin
                                        MapCell := MapBlock.Cells[ CY*8+CX ];
                                        ZLevel[ CY*8+CX ] := MapCell.Z;
                                        GesamtMap.Pixel[ X*8+CX, Y*8+CY ] := Color32( Radarcol.GetColor( MapCell.Id ) );
                                end;

                        staIdx.Seek( BlockID*12, soFromBeginning );
                        staIdx.Read( IndexRecord, 12 );

                        if (IndexRecord.Offset <> -1) and (IndexRecord.Length > 0) then begin
                                staMul.Seek( IndexRecord.Offset, soFromBeginning );
                                while staMul.Position < IndexRecord.Offset+IndexRecord.Length do begin
                                        staMul.Read( SId, 2 );
                                        staMul.Read( SX, 1 );
                                        staMul.Read( SY, 1 );
                                        staMul.Read( SZ, 1 );
                                        staMul.Read( SColor, 2 );

                                        if SZ > ZLevel[ SY*8+SX ] then begin
                                                ZLevel[ SY*8+SX ] := SZ;
                                                GesamtMap.Pixel[ X*8+SX, Y*8+SY ] := Color32( Radarcol.GetColor( SId + $4000 ) );
                                        end;
                                end;
                        end;
                end;
        end;

        GesamtMap.SaveToFile( Path );
        GesamtMap.Free;

        mulStream.Free;
        staIdx.Free;
        staMul.Free;

        Showmessage( 'Done.' );
end;

procedure TMainForm.Button12Click(Sender: TObject);
type    TStaticItem = Record Id : Word; X, Y : Byte; Z : ShortInt; Color : Word; end;
        PStaticItem = ^TStaticItem;
var     idxStream, mulStream : TFileStream;
        IndexRecord : TIndexRecord;
        SId, SColor : Word;
        SX, SY : Byte;
        SZ : ShortInt;
        BlockID : LongWord;
        PX, PY, BX, BY : LongWord;
        Liste : TList;
        Item, NewItem : PStaticItem;
        Buf : PByteArray;
        I : Integer;
        Changed : Boolean;
begin
        if not Map.Loaded then
                exit;

        idxStream := TFileStream.Create( ePathStaticIdx.Text, fmOpenReadWrite );
        idxStream.Seek( 0, soFromBeginning );

        mulStream := TFileStream.Create( ePathStaticMul.Text, fmOpenReadWrite );

        GaugeForm.Activate;

        while idxStream.Position < idxStream.Size do begin
                GaugeForm.SetBalken( Trunc( 100*idxStream.Position/idxStream.Size ) );
                idxStream.Read( IndexRecord, 12 );

                if (IndexRecord.Offset <> -1) and (IndexRecord.Length > 0) then begin
                        mulStream.Seek( IndexRecord.Offset, soFromBeginning );

                        Liste := TList.Create;
                        Changed := False;

                        BlockID := (idxStream.Position - 12) div 12;
                        BX := ( BlockID div 512 )*8;
                        PY := ( BlockID mod 512 )*8;

                        while mulStream.Position < IndexRecord.Offset+IndexRecord.Length do begin
                                New( Item );

                                mulStream.Read( Item.Id, 2 );
                                mulStream.Read( Item.X, 1 );
                                mulStream.Read( Item.Y, 1 );
                                mulStream.Read( Item.Z, 1 );
                                mulStream.Read( Item.Color, 2 );

                                if (Item.Id < $39E7) or (Item.Id > $39EE) then begin
                                        Liste.Add( Item );

                                        if (Item.Id = $CF3) or (Item.Id = $CF4) or (Item.Id = $CF6) or (Item.Id = $CF7) then begin
                                                if Map.GetZLevel( BX + Item.X, BY + Item.Y ) < Item.Z then begin
                                                        New( NewItem );
                                                        NewItem.Id := $28C1;
                                                        NewItem.X := Item.X;
                                                        NewItem.Y := Item.Y;
                                                        NewItem.Z := Item.Z;
                                                        NewItem.Color := 0;
                                                        Liste.Add( NewItem );

                                                        Changed := True;
                                                end;
                                        end;
                                end
                                else begin
                                        Changed := True;
                                        Dispose( Item );
                                end;
                        end;

                        if Changed then begin
                                if Liste.Count > 0 then begin
                                        mulStream.Seek( 0, soFromEnd );
                                        IndexRecord.Offset := mulStream.Position;

                                        for I := 0 to Liste.Count-1 do begin
                                                Item := PStaticItem( Liste.Items[ I ] );

                                                mulStream.Write( Item.Id, 2 );
                                                mulStream.Write( Item.X, 1 );
                                                mulStream.Write( Item.Y, 1 );
                                                mulStream.Write( Item.Z, 1 );
                                                mulStream.Write( Item.Color, 2 );
                                        end;

                                        IndexRecord.Length := mulStream.Position - IndexRecord.Offset;
                                        idxStream.Seek( -12, soFromCurrent );
                                        idxStream.Write( IndexRecord, 12 );
                                end
                                else begin
                                        IndexRecord.Offset := -1;
                                        IndexRecord.Length := -1;
                                        IndexRecord.Extra := 0;
                                        idxStream.Seek( -12, soFromCurrent );
                                        idxStream.Write( IndexRecord, 12 );
                                end;
                        end;

                        for I := 0 to Liste.Count-1 do begin
                                Dispose( PStaticItem( Liste.Items[ I ] ) );
                        end;

                        Liste.Free;
                end;
        end;

        GaugeForm.Deactivate;

        idxStream.Free;
        mulStream.Free;
end;

procedure TMainForm.cbMEClick(Sender: TObject);
var     UserName, PassWord : String;
begin
        if cbME.Checked then begin
                if MulCrypt <> nil then
                        MulCrypt.Free;

                UserName := '';
                if not InputQuery( 'Username', 'Username', UserName ) then begin
                        cbME.Checked := False;
                        Exit;
                end;

                PassWord := '';
                if not InputQuery( 'Password', 'Password', PassWord ) then begin
                        cbME.Checked := False;
                        Exit;
                end;

                MulCrypt := TMulCrypt.Create( UserName, PassWord, 3 );
        end;
end;

procedure TMainForm.btnCPAStartClick(Sender: TObject);
begin
        Animation.DupeAnim( StrToInt( eCPAFromID.Text ), StrToInt( eCPAToID.Text ), ePathAnimIdx.Text );
end;

procedure TMainForm.Button13Click(Sender: TObject);
var     OpenDialog : TOpenDialog;
        FileName : String;
        FStream : TFileStream;
        ID : Integer;
        Hoehe, Breite : Word;
        Null : Word;
begin
        OpenDialog := TOpenDialog.Create( nil );
        OpenDialog.Title := 'Where to save the file?';

        if not OpenDialog.Execute then begin
                OpenDialog.Free;
                Exit;
        end;

        FileName := OpenDialog.FileName;
        OpenDialog.Free;

        if not Art.loaded then begin
                Showmessage( 'Load Art first.' );
                Exit;
        end;

        if FileExists( FileName ) then
                DeleteFile( FileName );

        FStream := TFileStream.Create( FileName, fmCreate );
        Null := 0;

        for ID := 0 to Art.GetStaticCount-1 do begin
                FStream.Write( Null, 2 );
                FStream.Write( Null, 2 );

                if Art.StaticExists( ID ) then begin
                        Breite := Art.GetStaticTileWidth( ID );
                        Hoehe := Art.GetStaticTileHeight( ID );
                        FStream.Write( Breite, 2 );
                        FStream.Write( Hoehe, 2 );
                end
                else begin
                        FStream.Write( Null, 2 );
                        FStream.Write( Null, 2 );
                end;
        end;

        FStream.Free;

        ShowMessage( 'Done' );
end;

procedure TMainForm.Button14Click(Sender: TObject);
var     OpenDialog : TOpenDialog;
        FileName : String;
        FStream : TFileStream;
        ID : Integer;
        Hoehe, Breite : Word;
        Null : Word;
begin
        OpenDialog := TOpenDialog.Create( nil );
        OpenDialog.Title := 'Where to save the file?';

        if not OpenDialog.Execute then begin
                OpenDialog.Free;
                Exit;
        end;

        FileName := OpenDialog.FileName;
        OpenDialog.Free;

        if not Gump.loaded then begin
                Showmessage( 'Load Gumps first.' );
                Exit;
        end;

        if FileExists( FileName ) then
                DeleteFile( FileName );

        FStream := TFileStream.Create( FileName, fmCreate );
        Null := 0;

        for ID := 0 to Gump.GetGumpCount-1 do begin
                FStream.Write( Null, 2 );
                FStream.Write( Null, 2 );

                if Gump.GumpExists( ID ) then begin
                        Breite := Gump.GetGumpWidth( ID );
                        Hoehe := Gump.GetGumpHeight( ID );
                        FStream.Write( Breite, 2 );
                        FStream.Write( Hoehe, 2 );
                end
                else begin
                        FStream.Write( Null, 2 );
                        FStream.Write( Null, 2 );
                end;
        end;

        FStream.Free;

        ShowMessage( 'Done' );
end;

procedure TMainForm.btnSedinBrowseGumpWClick(Sender: TObject);
var     OpenDialog : TOpenDialog;
begin
        OpenDialog := TOpenDialog.Create( nil );
        OpenDialog.Filter := '*.bmp|*.bmp';

        if not OpenDialog.Execute then begin
                OpenDialog.Free;
                exit;
        end;

        if not FileExists(OpenDialog.FileName) then begin
                Application.MessageBox( 'Diese Datei ist nicht existent. Bitte wählen sie einen gültigen Dateinamen.', 'Datei nicht gefunden', MB_OK+MB_ICONERROR );
                OpenDialog.Free;
                Exit;
        end;

        eSedinPathGumpW.Text := OpenDialog.FileName;
        OpenDialog.Free;
end;

constructor TClilocEntry.Create( Id : LongWord; Name : String );
begin
        Self.Id := Id;
        Self.Name := Name;
end;

destructor TClilocEntry.Free;
begin
end;

procedure TMainForm.btnMergeClilocClick(Sender: TObject);
        function SortItems( Item1, Item2 : Pointer ) : Integer;
        var Entry1, Entry2 : TClilocEntry;
        begin
                Entry1 := TClilocEntry( Item1 );
                Entry2 := TClilocEntry( Item2 );

                if Entry1.Id > Entry2.Id then
                        Result := 1
                else if Entry1.Id < Entry2.Id then
                        Result := -1
                else
                        Result := 0;
        end;

var     OpenDialog : TOpenDialog;
        ClilocPath : String;
        Cliloc : TFileStream;
        List1, List2, List4 : TList;
        I, J : Integer;
        Id : LongWord; Name : String;
        Unknown, Buchstabe : Byte;
        Count : Word;
        GroupId : Word;
        Entry : TClilocEntry;
begin
        OpenDialog := TOpenDialog.Create( nil );
        OpenDialog.Filter := '*.bmp|*.bmp';

        if not OpenDialog.Execute then begin
                OpenDialog.Free;
                exit;
        end;

        ClilocPath := OpenDialog.FileName;
        OpenDialog.Free;

        if not FileExists( ePathTiledata.Text ) then begin
                Application.MessageBox( 'Tiledata ist nicht existent. Bitte wählen sie einen gültigen Dateinamen (Settings).', 'Datei nicht gefunden', MB_OK+MB_ICONERROR );
                Exit;
        end;

        Tiledata.Load( ePathTiledata.Text );

        List1 := TList.Create;
        List2 := TList.Create;
        List4 := TList.Create;

        if FileExists( ClilocPath ) then begin
                Cliloc := TFileStream.Create( ClilocPath, fmOpenRead );
                Cliloc.Seek( 6, soFromBeginning );
                while Cliloc.Position < Cliloc.Size do begin
                        Cliloc.Read( Id, 4 );
                        Cliloc.Read( Unknown, 1 );
                        Cliloc.Read( Count, 2 );

                        Name := '';
                        I := 0;
                        while I < Count do begin
                                Cliloc.Read( Buchstabe, 1 );
                                Name := Name + Chr( Buchstabe );
                                Inc( I );
                        end;
                        Name := Utf8Decode( Name );

                        Entry := TClilocEntry.Create( Id, Name );

                        GroupId := Id div 500000;
                        Case GroupId of
                                1 : List1.Add( Entry );
                                2 : List2.Add( Entry );
                                4 : List4.Add( Entry );
                        end;
                end;
        end;

        for Id := 0 to Tiledata.GetStaticTileCount-1 do begin
                if Tiledata.GetStaticName( Id ) <> '' then begin
                        Entry := nil;
                        for J := 0 to List2.Count-1 do begin
                                if (TClilocEntry( List2.Items[ J ] ).Id - 1020000 ) = Id then begin
                                        Entry := TClilocEntry( List2.Items[ J ] );
                                        Break;
                                end;
                        end;

                        if Entry = nil then begin
                                Entry := TClilocEntry.Create( Id + 1020000, Tiledata.GetStaticName( Id ) );
                                List2.Add( Entry );
                        end
                        else begin
                                Entry.Name := Tiledata.GetStaticName( Id );
                        end;
                end;
        end;

        Cliloc.Free;
        List2.Sort( @SortItems );

        if FileExists( ClilocPath ) then begin
                DeleteFile( ClilocPath );
        end;

        Cliloc := TFileStream.Create( ClilocPath, fmCreate );
        Cliloc.Seek( 0, soFromBeginning );
        Unknown := 0;
        Cliloc.Write( Unknown, 1 );
        Cliloc.Write( Unknown, 1 );
        Cliloc.Write( Unknown, 1 );
        Cliloc.Write( Unknown, 1 );
        Cliloc.Write( Unknown, 1 );
        Cliloc.Write( Unknown, 1 );

        for I := 0 to List1.Count-1 do begin
                Entry := TClilocEntry( List1.Items[ I ] );
                Cliloc.Write( Entry.Id, 4 );
                Cliloc.Write( Unknown, 1 );
                Name := Utf8Encode( Entry.Name );
                Count := Length( Name );
                Cliloc.Write( Count, 2 );
                for J := 1 to Length( Name ) do begin
                        Buchstabe := Ord( Name[ J ] );
                        Cliloc.Write( Buchstabe, 1 );
                end;
        end;

        for I := 0 to List2.Count-1 do begin
                Entry := TClilocEntry( List2.Items[ I ] );
                Cliloc.Write( Entry.Id, 4 );
                Cliloc.Write( Unknown, 1 );
                Name := Utf8Encode( Entry.Name );
                Count := Length( Name );
                Cliloc.Write( Count, 2 );
                for J := 1 to Length( Name ) do begin
                        Buchstabe := Ord( Name[ J ] );
                        Cliloc.Write( Buchstabe, 1 );
                end;
        end;

        for I := 0 to List4.Count-1 do begin
                Entry := TClilocEntry( List4.Items[ I ] );
                Cliloc.Write( Entry.Id, 4 );
                Cliloc.Write( Unknown, 1 );
                Name := Utf8Encode( Entry.Name );
                Count := Length( Name );
                Cliloc.Write( Count, 2 );
                for J := 1 to Length( Name ) do begin
                        Buchstabe := Ord( Name[ J ] );
                        Cliloc.Write( Buchstabe, 1 );
                end;
        end;

        Cliloc.Free;

        for I := 0 to List1.Count-1 do begin
                TClilocEntry( List1.Items[ I ] ).Free;
        end;
        List1.Free;

        for I := 0 to List2.Count-1 do begin
                TClilocEntry( List2.Items[ I ] ).Free;
        end;
        List2.Free;

        for I := 0 to List4.Count-1 do begin
                TClilocEntry( List4.Items[ I ] ).Free;
        end;
        List4.Free;

        Tiledata.Free;
        Tiledata := TTiledata.Create;

        Showmessage( 'Done' );
end;

procedure TMainForm.Button15Click(Sender: TObject);
var     Id : Integer;
        Text : TStringList;
begin
        if not Animation.Loaded then begin
                Showmessage( 'anim not loaded' );
                exit;
        end;

        if not Gump.loaded then begin
                Showmessage( 'gump not loaded' );
                exit;
        end;

        Text := TStringList.Create;
        for Id := 50000 to Gump.GetGumpCount-1 do begin
                if Gump.GumpExists( Id ) and (not Animation.AnimExists( Id-50000 )) then begin
                        Text.Add( Format( '0x%x 0x%x',[Id,Id-50000] ) );
                end;
        end;

        Text.SaveToFile( ExtractFilePath( Application.ExeName ) + 'missinganims.txt' );
        Text.Free;

        ShowMessage( 'Ids saved to ' + ExtractFilePath( Application.ExeName ) + 'missinganims.txt' );
end;

procedure TMainForm.Button16Click(Sender: TObject);
var     Id : Integer;
        Datei : TextFile;
        SaveDialog : TSaveDialog;
begin
        if not Gump.loaded then exit;

        SaveDialog := TSaveDialog.Create( nil );
        SaveDialog.Filter := '*.txt|*.txt';
        SaveDialog.DefaultExt := 'txt';
        SaveDialog.FileName := 'EmptyIDs.txt';

        if not SaveDialog.Execute then begin
                SaveDialog.Free;
                exit;
        end;

        if FileExists( SaveDialog.FileName ) then
                DeleteFile( SaveDialog.FileName );

        AssignFile( Datei, SaveDialog.FileName );
        ReWrite( Datei );
        SaveDialog.Free;

        for Id := 0 to Gump.GetGumpCount-1 do begin
                if not Gump.GumpExists( Id ) then begin
                        Writeln( Datei, Format( '0x%x', [Id] ) );
                end;
        end;

        CloseFile( Datei );
end;

procedure TMainForm.Button17Click(Sender: TObject);
var     Id : Integer;
        Datei : TextFile;
        SaveDialog : TSaveDialog;
begin
        if not Textures.loaded then exit;

        SaveDialog := TSaveDialog.Create( nil );
        SaveDialog.Filter := '*.txt|*.txt';
        SaveDialog.DefaultExt := 'txt';
        SaveDialog.FileName := 'EmptyIDs.txt';

        if not SaveDialog.Execute then begin
                SaveDialog.Free;
                exit;
        end;

        if FileExists( SaveDialog.FileName ) then
                DeleteFile( SaveDialog.FileName );

        AssignFile( Datei, SaveDialog.FileName );
        ReWrite( Datei );
        SaveDialog.Free;

        for Id := 0 to Textures.GetCount-1 do begin
                if not Textures.Exists( Id ) then begin
                        Writeln( Datei, Format( '0x%x', [Id] ) );
                end;
        end;

        CloseFile( Datei );
end;

procedure TMainForm.btnArtDeleteIdsClick(Sender: TObject);
var     FirstID, LastID, ID : Integer;
begin
        if not Art.loaded then begin
                ShowMessage( 'Load Art first.' );
                exit;
        end;

        try
                FirstID := StrToInt( ArtDeleteIDFirst.Text );
                LastID := StrToInt( ArtDeleteIDLast.Text );
        except
                ShowMessage( 'Bad IDs.' );
                exit;
        end;

        for ID := FirstID to LastID do begin
                Art.DeleteStatic( ID );
        end;
end;

procedure TMainForm.Button18Click(Sender: TObject);
var     Id : Integer;
        Datei : TextFile;
        SaveDialog : TSaveDialog;
begin
        if not Tiledata.Loaded then begin
                ShowMessage( 'Load Tiledata first.' );
                Exit;
        end;

        if not Animation.Loaded then begin
                ShowMessage( 'Load Anims first.' );
                Exit;
        end;

        SaveDialog := TSaveDialog.Create( nil );
        SaveDialog.Filter := '*.txt|*.txt';
        SaveDialog.DefaultExt := 'txt';
        SaveDialog.FileName := 'EmptyIDs.txt';

        if not SaveDialog.Execute then begin
                SaveDialog.Free;
                exit;
        end;

        if FileExists( SaveDialog.FileName ) then
                DeleteFile( SaveDialog.FileName );

        AssignFile( Datei, SaveDialog.FileName );
        ReWrite( Datei );
        SaveDialog.Free;

        for Id := 0 to Tiledata.GetStaticTileCount-1 do begin
                if (Tiledata.GetStaticAnimId( Id ) <> 0) and (not Animation.AnimExists( Tiledata.GetStaticAnimId( Id ) )) then begin
                        Writeln( Datei, Format( '0x%x', [Id] ) );
                end;
        end;

        CloseFile( Datei );
end;

procedure TMainForm.btnAnim4SearchClick(Sender: TObject);
var     Index : Integer;
begin
        if eAnim4Search.Text <> '' then begin
                Index := Search( lbAnim4, Sender, eAnim4Search.Text );
                if Index <> -1 then begin
                        lbAnim4.ItemIndex := Index;
                        lbAnim4Click( Sender );
                end;
        end;
end;

procedure TMainForm.cbAnim4Change(Sender: TObject);
var     i : integer;
        zeile, state : String;
begin
        lbAnim4.Clear;
        lbAnim4.Items.BeginUpdate;
        for i := 0 to Anim4.CountAllAnims-1 do begin
                if i < 200 then
                        zeile := 'H'
                else if i < 400 then
                        zeile := 'L'
                else
                        zeile := 'P';
                zeile := zeile + ': ' + Format( '0x%x', [ i ] );

                state := cbAnim4.Items[ cbAnim4.ItemIndex ];
                if state = 'All Slots' then
                        lbAnim4.Items.Add( zeile )
                else if ( state = 'Empty Slots' ) and ( not Anim4.AnimExists( i ) ) then
                        lbAnim4.Items.Add( zeile )
                else if ( state = 'Full Slots' ) and ( Anim4.AnimExists( i ) ) then
                        lbAnim4.Items.Add( zeile );
        end;
        lbAnim4.Items.EndUpdate;
end;

procedure TMainForm.eAnim4SearchKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
        if Key = VK_Return then
                btnAnim4SearchClick( Sender );
end;

procedure TMainForm.lbAnim4Click(Sender: TObject);
var     Bitmap : TBitmap32;
        Id : integer;
        Liste : TStringList;
begin
        Liste := TStringList.Create;
        StrLib.Split( lbAnim4.Items[ lbAnim4.ItemIndex ], ' ', Liste );
        Id := strtoint( Liste.Strings[ 1 ] );
        Liste.Free;

        if not Anim4.AnimExists( Id ) then begin
                iAnim4.Bitmap.SetSize( 360, 360 );
                iAnim4.Bitmap.Clear( Color32( iAnim4.Color ) );
                exit;
        end;

        Bitmap := Anim4.SaveFirstPicture( Id );
        iAnim4.Bitmap.SetSize( 360, 360 );
        iAnim4.Bitmap.Clear( Color32( iAnim4.Color ) );

        iAnim4.Bitmap.Draw( ( 360 - Bitmap.Width ) div 2, ( 360 - Bitmap.Height ) div 2, Bitmap );
        Bitmap.Free;
end;

procedure TMainForm.lbAnim4ContextPopup(Sender: TObject; MousePos: TPoint;
  var Handled: Boolean);
begin
        if lbAnim4.ItemIndex = -1 then
                exit;
        popAnim4.Popup( MousePos.X+MainForm.Left, MousePos.Y+MainForm.Top );
end;

procedure TMainForm.lbAnim4DrawItem(Control: TWinControl; Index: Integer;
  Rect: TRect; State: TOwnerDrawState);
var     Id : integer;
        Liste : TStringList;
begin
        lbAnim4.Canvas.Brush.Style := bsSolid;
        lbAnim4.Canvas.Brush.Color := clWhite;

        if ( odselected in state ) then begin
                lbAnim4.Canvas.Brush.Color := clNavy;
        end;
        lbAnim4.Canvas.FillRect( rect );

        Liste := TStringList.Create;
        StrLib.Split( lbAnim4.Items[ Index ], ' ', Liste );
        Id := strtoint( Liste.Strings[ 1 ] );
        Liste.Free;

        if Anim4.AnimExists( Id ) then
                lbAnim4.Canvas.Font.Color := clBlack
        else
                lbAnim4.Canvas.Font.Color := clRed;

        lbAnim4.Canvas.Brush.Style := bsClear;
        if ( odselected in state ) then begin
                lbAnim4.Canvas.Font.Color := clWhite;
        end;

        lbAnim4.Canvas.TextOut( 10, (-lbAnim4.TopIndex+Index)*lbAnim4.ItemHeight, lbAnim4.Items[ Index ] );
end;

procedure TMainForm.MenuItem4Click(Sender: TObject);
var     SaveDialog : TrmBrowseForFolder;
        Id : integer;
        Liste : TStringList;
begin
        Liste := TStringList.Create;
        StrLib.Split( lbAnim4.Items[ lbAnim4.ItemIndex ], ' ', Liste );
        Id := strtoint( Liste.Strings[ 1 ] );
        Liste.Free;

        if not Anim4.AnimExists( Id ) then
                exit;

        SaveDialog := TrmBrowseForFolder.create( nil );
        SaveDialog.Title := 'Wohin soll die Animation gespeichert werden?';

        if not SaveDialog.Execute then begin
                SaveDialog.Free;
                exit;
        end;

        Anim4.SaveAnimToDirectory( Id, SaveDialog.Folder );
        SaveDialog.Free;
end;

procedure TMainForm.MenuItem5Click(Sender: TObject);
var     SaveDialog : TSaveDialog;
        Id : integer;
        Liste : TStringList;
begin
        Liste := TStringList.Create;
        StrLib.Split( lbAnim4.Items[ lbAnim4.ItemIndex ], ' ', Liste );
        Id := strtoint( Liste.Strings[ 1 ] );
        Liste.Free;

        if not Anim4.AnimExists( Id ) then exit;

        SaveDialog := TSaveDialog.Create( nil );
        SaveDialog.DefaultExt := 'vd';
        SaveDialog.Filter := '*.vd|*.vd';
        SaveDialog.FileName := Format( '0x%x.vd', [Id] );

        if not SaveDialog.Execute then begin
                SaveDialog.Free;
                exit;
        end;

        Anim4.SaveAnimToFile( Id, SaveDialog.FileName );
        SaveDialog.Free;
end;

procedure TMainForm.MenuItem6Click(Sender: TObject);
var     SaveDialog : TrmBrowseForFolder;
        Id : integer;
        Liste : TStringList;
begin
        Liste := TStringList.Create;
        StrLib.Split( lbAnim5.Items[ lbAnim5.ItemIndex ], ' ', Liste );
        Id := strtoint( Liste.Strings[ 1 ] );
        Liste.Free;

        if not Anim5.AnimExists( Id ) then
                exit;

        SaveDialog := TrmBrowseForFolder.create( nil );
        SaveDialog.Title := 'Wohin soll die Animation gespeichert werden?';

        if not SaveDialog.Execute then begin
                SaveDialog.Free;
                exit;
        end;

        Anim5.SaveAnimToDirectory( Id, SaveDialog.Folder );
        SaveDialog.Free;
end;

procedure TMainForm.MenuItem7Click(Sender: TObject);
var     SaveDialog : TSaveDialog;
        Id : integer;
        Liste : TStringList;
begin
        Liste := TStringList.Create;
        StrLib.Split( lbAnim5.Items[ lbAnim5.ItemIndex ], ' ', Liste );
        Id := strtoint( Liste.Strings[ 1 ] );
        Liste.Free;

        if not Anim5.AnimExists( Id ) then exit;

        SaveDialog := TSaveDialog.Create( nil );
        SaveDialog.DefaultExt := 'vd';
        SaveDialog.Filter := '*.vd|*.vd';
        SaveDialog.FileName := Format( '0x%x.vd', [Id] );

        if not SaveDialog.Execute then begin
                SaveDialog.Free;
                exit;
        end;

        Anim5.SaveAnimToFile( Id, SaveDialog.FileName );
        SaveDialog.Free;
end;

procedure TMainForm.btnAnim5SearchClick(Sender: TObject);
var     Index : Integer;
begin
        if eAnim5Search.Text <> '' then begin
                Index := Search( lbAnim5, Sender, eAnim5Search.Text );
                if Index <> -1 then begin
                        lbAnim5.ItemIndex := Index;
                        lbAnim5Click( Sender );
                end;
        end;
end;

procedure TMainForm.cbAnim5Change(Sender: TObject);
var     i : integer;
        zeile, state : String;
begin
        lbAnim5.Clear;
        lbAnim5.Items.BeginUpdate;
        for i := 0 to Anim5.CountAllAnims-1 do begin
                if i < 200 then
                        zeile := 'H'
                else if i < 400 then
                        zeile := 'L'
                else
                        zeile := 'P';
                zeile := zeile + ': ' + Format( '0x%x', [ i ] );

                state := cbAnim5.Items[ cbAnim5.ItemIndex ];
                if state = 'All Slots' then
                        lbAnim5.Items.Add( zeile )
                else if ( state = 'Empty Slots' ) and ( not Anim5.AnimExists( i ) ) then
                        lbAnim5.Items.Add( zeile )
                else if ( state = 'Full Slots' ) and ( Anim5.AnimExists( i ) ) then
                        lbAnim5.Items.Add( zeile );
        end;
        lbAnim5.Items.EndUpdate;
end;


procedure TMainForm.eAnim5SearchKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
        if Key = VK_Return then
                btnAnim5SearchClick( Sender );
end;

procedure TMainForm.lbAnim5Click(Sender: TObject);
var     Bitmap : TBitmap32;
        Id : integer;
        Liste : TStringList;
begin
        Liste := TStringList.Create;
        StrLib.Split( lbAnim5.Items[ lbAnim5.ItemIndex ], ' ', Liste );
        Id := strtoint( Liste.Strings[ 1 ] );
        Liste.Free;

        if not Anim5.AnimExists( Id ) then begin
                iAnim5.Bitmap.SetSize( 360, 360 );
                iAnim5.Bitmap.Clear( Color32( iAnim5.Color ) );
                exit;
        end;

        Bitmap := Anim5.SaveFirstPicture( Id );
        iAnim5.Bitmap.SetSize( 360, 360 );
        iAnim5.Bitmap.Clear( Color32( iAnim5.Color ) );

        iAnim5.Bitmap.Draw( ( 360 - Bitmap.Width ) div 2, ( 360 - Bitmap.Height ) div 2, Bitmap );
        Bitmap.Free;
end;

procedure TMainForm.lbAnim5ContextPopup(Sender: TObject; MousePos: TPoint;
  var Handled: Boolean);
begin
        if lbAnim5.ItemIndex = -1 then
                exit;
        popAnim5.Popup( MousePos.X+MainForm.Left, MousePos.Y+MainForm.Top );
end;

procedure TMainForm.lbAnim5DrawItem(Control: TWinControl; Index: Integer;
  Rect: TRect; State: TOwnerDrawState);
var     Id : integer;
        Liste : TStringList;
begin
        lbAnim5.Canvas.Brush.Style := bsSolid;
        lbAnim5.Canvas.Brush.Color := clWhite;

        if ( odselected in state ) then begin
                lbAnim5.Canvas.Brush.Color := clNavy;
        end;
        lbAnim5.Canvas.FillRect( rect );

        Liste := TStringList.Create;
        StrLib.Split( lbAnim5.Items[ Index ], ' ', Liste );
        Id := strtoint( Liste.Strings[ 1 ] );
        Liste.Free;

        if Anim5.AnimExists( Id ) then
                lbAnim5.Canvas.Font.Color := clBlack
        else
                lbAnim5.Canvas.Font.Color := clRed;

        lbAnim5.Canvas.Brush.Style := bsClear;
        if ( odselected in state ) then begin
                lbAnim5.Canvas.Font.Color := clWhite;
        end;

        lbAnim5.Canvas.TextOut( 10, (-lbAnim5.TopIndex+Index)*lbAnim5.ItemHeight, lbAnim5.Items[ Index ] );
end;

procedure TMainForm.btnBrowseAnim4IdxClick(Sender: TObject);
var     NewFile : String;
begin
        NewFile := BrowseFile( 'Anim4.idx' );
        if NewFile <> '' then begin
                Config.SetString( 'Anim4Idx', Newfile );
                ePathAnim4Idx.Text := NewFile;
        end;
end;

procedure TMainForm.btnBrowseAnim4MulClick(Sender: TObject);
var     NewFile : String;
begin
        NewFile := BrowseFile( 'Anim4.mul' );
        if NewFile <> '' then begin
                Config.SetString( 'Anim4Mul', Newfile );
                ePathAnim4Mul.Text := NewFile;
        end;
end;

procedure TMainForm.btnAnim4LoadClick(Sender: TObject);
begin
        InitAnim4( Sender );
        showmessage( 'New Version does not load Anim4.mul into Memory anymore, but writes directly into Anim4.mul File. So make a backup before.' );
end;

procedure TMainForm.InitAnim4( Sender : TObject );
begin
        if ( ePathAnim4Idx.Text <> '' ) and ( ePathAnim4Mul.Text <> '' ) and FileExists( ePathAnim4Idx.Text ) and FileExists( ePathAnim4Mul.Text ) then
                Anim4.Load( ePathAnim4Idx.Text, ePathAnim4Mul.Text );

        cbAnim4.Clear;
        cbAnim4.Items.Add( 'All Slots' );
        cbAnim4.Items.Add( 'Empty Slots' );
        cbAnim4.Items.Add( 'Full Slots' );

        cbAnim4.ItemIndex := 0;
        cbAnim4Change( Sender );
end;

procedure TMainForm.btnBrowseAnim5IdxClick(Sender: TObject);
var     NewFile : String;
begin
        NewFile := BrowseFile( 'Anim5.idx' );
        if NewFile <> '' then begin
                Config.SetString( 'Anim5Idx', Newfile );
                ePathAnim5Idx.Text := NewFile;
        end;
end;

procedure TMainForm.btnBrowseAnim5MulClick(Sender: TObject);
var     NewFile : String;
begin
        NewFile := BrowseFile( 'Anim5.mul' );
        if NewFile <> '' then begin
                Config.SetString( 'Anim5Mul', Newfile );
                ePathAnim5Mul.Text := NewFile;
        end;
end;

procedure TMainForm.btnAnim5LoadClick(Sender: TObject);
begin
        InitAnim5( Sender );
        showmessage( 'New Version does not load Anim5.mul into Memory anymore, but writes directly into Anim5.mul File. So make a backup before.' );
end;

procedure TMainForm.InitAnim5( Sender : TObject );
begin
        if ( ePathAnim5Idx.Text <> '' ) and ( ePathAnim5Mul.Text <> '' ) and FileExists( ePathAnim5Idx.Text ) and FileExists( ePathAnim5Mul.Text ) then
                Anim5.Load( ePathAnim5Idx.Text, ePathAnim5Mul.Text );

        cbAnim5.Clear;
        cbAnim5.Items.Add( 'All Slots' );
        cbAnim5.Items.Add( 'Empty Slots' );
        cbAnim5.Items.Add( 'Full Slots' );

        cbAnim5.ItemIndex := 0;
        cbAnim5Change( Sender );
end;

procedure TMainForm.Button19Click(Sender: TObject);
var     Bitmap : TBitmap;
        OpenDialog : TOpenDialog;
        FileName : String;
        X, Y : Integer;
        Color32 : Integer;
        Color15 : Word;
        NewColor : TColor;
        Form : TForm;
        Image : TImage;
begin
        OpenDialog := TOpenDialog.Create( nil );
        OpenDialog.Title := 'Choose your bitmap.';
        OpenDialog.Filter := '*.bmp|*.bmp';

        if not OpenDialog.Execute then begin
                OpenDialog.Free;
                Exit;
        end;

        FileName := OpenDialog.FileName;
        OpenDialog.Free;

        Bitmap := TBitmap.Create;
        Bitmap.LoadFromFile( FileName );

        try
                NewColor := TColor( StrToInt( eColorMarkPixels.Text ) );
        except
                NewColor := TColor( $FF0080 );
        end;

        GaugeForm.Activate;
        for X := 0 to Bitmap.Width-1 do
                for Y := 0 to Bitmap.Height-1 do begin
                        Color32 := Bitmap.Canvas.Pixels[X,Y];
                        Color15 := ((Color32 and $F80000) shr 19) or ((Color32 and $F800) shr 6) or ((Color32 and $F8) shl 7);

                        if ( Color15 = 32767 ) or ( Color15 = 0 ) then begin
                                Bitmap.Canvas.Pixels[X,Y] := NewColor;
                        end;

                        GaugeForm.SetBalken( Round( (X*Bitmap.Height + Y)*100 / (Bitmap.Width*Bitmap.Height) ) );
                end;
        GaugeForm.Deactivate;

        Form := TForm.Create( nil );
        Form.ClientWidth := Bitmap.Width;
        Form.ClientHeight := Bitmap.Height;

        Image := TImage.Create( Form );
        Image.Parent := Form;
        Image.Width := Bitmap.Width;
        Image.Height := Bitmap.Height;
        Image.Left := 0;
        Image.Top := 0;
        Image.Visible := True;
        Image.Picture.Assign( Bitmap );

        Form.ShowModal;
        Form.Free;

        Bitmap.Free;
end;

procedure TMainForm.eColorMarkPixelsChange(Sender: TObject);
begin
        Config.SetString( 'ColorMarkPixels', eColorMarkPixels.Text );
end;

procedure TMainForm.Button20Click(Sender: TObject);
begin
        if not Statics.loaded then begin
                ShowMessage( 'Load Statics first.' );
                Exit;
        end;

        Statics.Cleanup;
end;

procedure TMainForm.eMapWidthChange(Sender: TObject);
begin
        Config.SetString( 'MapWidth', eMapWidth.Text );
end;

procedure TMainForm.eMapHeightChange(Sender: TObject);
begin
        Config.SetString( 'MapHeight', eMapHeight.Text );
end;

end.


