UNIT Unit4;
INTERFACE
USES
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls, ComCtrls, StrUtils;
TYPE
  TForm4 = Class(TForm)
    Label1: TLabel;
    edit_char: TEdit;
    list: TListBox;
    Label2: TLabel;
    btn_demo: TButton;
    check_freeze: TCheckBox;
    timer_anim: TTimer;
    check_global: TRadioButton;
    check_local: TRadioButton;
    updown: TUpDown;
    group_anim: TGroupBox;
    lbl_lvl: TLabel;
    memo: TMemo;
    PROCEDURE listClick(Sender: TObject);
    PROCEDURE btn_demoClick(Sender: TObject);
    PROCEDURE updownClick(Sender: TObject; Button: TUDBtnType);
    PROCEDURE FormCreate(Sender: TObject);
    PROCEDURE FormCloseQuery(Sender: TObject; var CanClose: Boolean);
    PROCEDURE check_localClick(Sender: TObject);
    PROCEDURE check_globalClick(Sender: TObject);
    PROCEDURE timer_animTimer(Sender: TObject);
    PROCEDURE check_freezeClick(Sender: TObject);
  PRIVATE
  PUBLIC
  END;
VAR
  Form4: TForm4;

IMPLEMENTATION
USES Unit1, Unit2, Unit8;
VAR
  demo_active:Boolean=False;
  first_global:LongWord;
  first_local:LongWord;
{$R *.dfm}

PROCEDURE TForm4.check_freezeClick(Sender: TObject);
  BEGIN
    btn_demo.Caption:='Start demo';
    demo_active:=False;
  END;

FUNCTION patch_loader_loaded:Boolean;
  CONST check_for:LongWord=$0010656EE9;
    address_at:LongWord=$4228ED;
  BEGIN
    IF Decode_Int(ReadMem(address_at,4))=check_for THEN result:=True
    ELSE result:=False;
  END;

FUNCTION GetAnimAddress:LongWord;
  VAR offset:LongWord;
  BEGIN
    IF Form4.check_global.Checked THEN BEGIN
      offset:=animations_l0[Form4.list.ItemIndex+1].offset;
      result:=first_global+offset;
    END ELSE BEGIN
      CASE lvlnumber OF
        1: offset:=animations_l1[Form4.list.ItemIndex+1].offset;
        2: offset:=animations_l2[Form4.list.ItemIndex+1].offset;
        3: offset:=animations_l3[Form4.list.ItemIndex+1].offset;
        4: offset:=animations_l4[Form4.list.ItemIndex+1].offset;
        5: offset:=animations_l5[Form4.list.ItemIndex+1].offset;
        6: offset:=animations_l6[Form4.list.ItemIndex+1].offset;
        7: offset:=animations_l7[Form4.list.ItemIndex+1].offset;
        8: offset:=animations_l8[Form4.list.ItemIndex+1].offset;
        9: offset:=animations_l9[Form4.list.ItemIndex+1].offset;
        10: offset:=animations_l10[Form4.list.ItemIndex+1].offset;
        11: offset:=animations_l11[Form4.list.ItemIndex+1].offset;
        12: offset:=animations_l12[Form4.list.ItemIndex+1].offset;
        13: offset:=animations_l13[Form4.list.ItemIndex+1].offset;
        14: offset:=animations_l14[Form4.list.ItemIndex+1].offset;
      END;
      result:=first_local+offset;
    END;
  END;

PROCEDURE TForm4.timer_animTimer(Sender: TObject);
  VAR struct3:LongWord;
    buffer:byte_array;
    address:LongWord;
  BEGIN
    IF _connected AND (lvlnumber>0) AND patch_loader_loaded THEN BEGIN
      first_global:=Decode_Int(ReadMem($10F08,4));
      first_local:=Decode_Int(ReadMem($10F0C,4));
      struct3:=Decode_Int(ReadMem(PointerStruct3,4))+StrToInt(Form4.edit_char.Text)*$2838;
      address:=GetAnimAddress;

      IF demo_active THEN BEGIN
        IF Decode_Int(ReadMem(struct3+$1AF8,4))<>address THEN BEGIN
          REPEAT
            Form4.list.ItemIndex:=Form4.list.ItemIndex+1;
          UNTIL (Pos('_tgt',Form4.list.Items.Strings[Form4.list.ItemIndex])=0);
          address:=GetAnimAddress;
          buffer:=Encode_Int(address);
          WriteMem(struct3+$1AF8,4,buffer);
        END;
      END;
      IF check_freeze.Checked THEN BEGIN
        buffer:=Encode_Int(address);
        WriteMem(struct3+$1AF8,4,buffer);
      END;
    END ELSE BEGIN
      IF _connected AND (lvlnumber>0) AND (demo_active OR check_freeze.Checked) THEN BEGIN
        MessageBox(Form4.Handle,PChar('Oni.exe is not patched.'),PChar('Error'),MB_OK);
      END;
    END;
  END;

PROCEDURE load_anim_list(anims:Array OF animation);
  VAR i:Word;
  BEGIN
      Form4.list.Items.Clear;
      FOR i:=0 TO High(anims) DO BEGIN
        Form4.list.Items.Add(anims[i].name);
      END;
  END;

PROCEDURE TForm4.check_globalClick(Sender: TObject);
  BEGIN
    IF check_global.Checked THEN BEGIN
      load_anim_list(animations_l0);
    END;
  END;

PROCEDURE TForm4.check_localClick(Sender: TObject);
  BEGIN
    IF check_local.Checked THEN BEGIN
      IF lvlnumber>0 THEN BEGIN
        CASE lvlnumber OF
          1: load_anim_list(animations_l1);
          2: load_anim_list(animations_l2);
          3: load_anim_list(animations_l3);
          4: load_anim_list(animations_l4);
          5: load_anim_list(animations_l5);
          6: load_anim_list(animations_l6);
          7: load_anim_list(animations_l7);
          8: load_anim_list(animations_l8);
          9: load_anim_list(animations_l9);
          10: load_anim_list(animations_l10);
          11: load_anim_list(animations_l11);
          12: load_anim_list(animations_l12);
          13: load_anim_list(animations_l13);
          14: load_anim_list(animations_l14);
        END;
      END ELSE BEGIN
        check_global.Checked:=True;
      END;
    END;
  END;

PROCEDURE TForm4.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
  BEGIN
    Self.Visible:=False;
    CanClose:=False;
    Form1.menu_Anims.Checked:=False;
  END;

PROCEDURE TForm4.FormCreate(Sender: TObject);
  BEGIN
    load_anim_list(animations_l0);
    list.ItemIndex:=0;
    updown.Max:=ais_controlled;
  END;

PROCEDURE TForm4.updownClick(Sender: TObject; Button: TUDBtnType);
  BEGIN
    Form4.edit_char.Text:=IntToStr(updown.Position);
  END;

PROCEDURE TForm4.btn_demoClick(Sender: TObject);
  VAR struct3,address:LongWord;
    buffer:byte_array;
  BEGIN
    IF demo_active THEN BEGIN
      check_freeze.Checked:=False;
      btn_demo.Caption:='Start demo';
      demo_active:=False;
    END ELSE BEGIN
      check_freeze.Checked:=False;
      btn_demo.Caption:='Stop demo';
      demo_active:=True;
      IF _connected AND (lvlnumber>0) AND patch_loader_loaded THEN BEGIN
        first_global:=Decode_Int(ReadMem($10F08,4));
        first_local:=Decode_Int(ReadMem($10F0C,4));
        struct3:=Decode_Int(ReadMem(PointerStruct3,4))+StrToInt(Form4.edit_char.Text)*$2838;
        address:=GetAnimAddress;
        buffer:=Encode_Int(address);
        WriteMem(struct3+$1AF8,4,buffer);
      END ELSE BEGIN
        IF _connected AND (lvlnumber>0) THEN BEGIN
          MessageBox(Form4.Handle,PChar('Oni.exe is not patched.'),PChar('Error'),MB_OK);
        END;
      END;
    END;
  END;

PROCEDURE TForm4.listClick(Sender: TObject);
  VAR address:LongWord;
    buffer:byte_array;
    i:Byte;
    temp:String;
    old:LongWord;
  BEGIN
    IF _connected AND (lvlnumber>0) AND patch_loader_loaded THEN BEGIN
      first_global:=Decode_Int(ReadMem($10F08,4));
      first_local:=Decode_Int(ReadMem($10F0C,4));
      address:=GetAnimAddress;
      Form4.lbl_lvl.Caption:='Lvl required (@'+IntToHex(address,8)+'): '+IntToStr(Decode_Int(ReadMem(address+$176,1)));
//      VirtualProtectEx(_ProcessHandle,address+$176,2,PAGE_READWRITE,old);
//      MessageBox(Form4.Handle,PChar('BLA: '+IntToStr(GetLastError)+'#'+IntToHex(GetLastError,8)),PChar('Error'),MB_OK);
      WriteMem(address+$176,1,Encode_Int(0));
//      MessageBox(Form4.Handle,PChar('BLA: '+IntToStr(GetLastError)+'#'+IntToHex(GetLastError,8)),PChar('Error'),MB_OK);
      Form4.memo.Lines.Clear;
      temp:='';
      buffer:=ReadMem(address,$D0);
      FOR i:=0 TO ($D0 - 1) DO BEGIN
        temp:=temp+IntToHex(buffer[i],2);
        IF ((i+1) MOD $10)=0 THEN BEGIN
          Form4.memo.Lines.Add(temp);
          temp:='';
        END;
      END;
      buffer:=ReadMem(address+$D0,$D0);
      FOR i:=0 TO ($D0 - 1) DO BEGIN
        temp:=temp+IntToHex(buffer[i],2);
        IF ((i+1) MOD $10)=0 THEN BEGIN
          Form4.memo.Lines.Add(temp);
          temp:='';
        END;
      END;
    END ELSE BEGIN
      IF _connected AND (lvlnumber>0) THEN BEGIN
        MessageBox(Form4.Handle,PChar('Oni.exe is not patched.'),PChar('Error'),MB_OK);
      END;
    END;
  END;

END.
