+ Reply to Thread
Page 1 of 6 123 ... LastLast
Results 1 to 25 of 146

Thread: MSI Form ~ Bugs and Suggestions

  1. #1
    Join Date
    Apr 2008
    Location
    Marquette, MI
    Posts
    15,252
    Mentioned
    138 Post(s)
    Quoted
    680 Post(s)

    Default MSI Form ~ Bugs and Suggestions

    If you haven't read already, please read this thread.

    This thread is for all bugs you may encounter while using the form, and also anything you would like to see changed. Don't be afraid to post your honest opinions either. Keep in mind that this thread is for bugs and suggestions for the MSI Form only, if you are having problems with the script itself, please post in the Script didn't run thread.

    Bugs:
    • Out of range when trying to delete the last player in the list.
    • Invalid boolean when you don't fill out one of the script settings' combo boxes.


    Suggestions:
    • Ability to save multiple files (Save/Load specified files, rather than just one).
    • Display the first player by default in the panel's combo boxes.
    • A 'Group' feature that will use the same settings for each player in the group.
    • A CheckBox that will use the player's in a random order, rather than the order added.
    • A CheckBox to show/hide the player's passwords.
    • Drag and drop players in the player list.


    Soon to come...
    • Player editing
    • Descriptions of how to setup certain components (Hint pointer).
    • Form dragging
    • Show only the valid locations for each script.
    • Have Settings.txt created automatically instead of added to the SVN (to avoid overriding).


    Enjoy,
    The MSI Team
    Last edited by Coh3n; 04-28-2011 at 06:05 PM.

  2. #2
    Join Date
    May 2007
    Location
    Some where fun.
    Posts
    2,891
    Mentioned
    1 Post(s)
    Quoted
    5 Post(s)

    Default

    This is so awesome Can't wait to test it out.

  3. #3
    Join Date
    May 2007
    Location
    Tasmania, Aus
    Posts
    898
    Mentioned
    0 Post(s)
    Quoted
    1 Post(s)

    Default

    tested, and I don't know how it could really be much better

  4. #4
    Join Date
    Dec 2010
    Location
    Leuven
    Posts
    57
    Mentioned
    0 Post(s)
    Quoted
    0 Post(s)

    Default

    Works really well, good job .

    Maybe a suggestion: you could add some explanatory text of some settings when you hover your mouse over them. For example the 'Level to Debug' etc. Would make it even more transparent for unexperienced people. Or some kind of 'Set Defaults' button, which would fill in some of the less personal settings to a value that would be reasonable.

  5. #5
    Join Date
    Apr 2008
    Location
    Marquette, MI
    Posts
    15,252
    Mentioned
    138 Post(s)
    Quoted
    680 Post(s)

    Default

    Quote Originally Posted by Furyan View Post
    Works really well, good job .

    Maybe a suggestion: you could add some explanatory text of some settings when you hover your mouse over them. For example the 'Level to Debug' etc. Would make it even more transparent for unexperienced people. Or some kind of 'Set Defaults' button, which would fill in some of the less personal settings to a value that would be reasonable.
    Oh sorry, I forgot to commit the Settings.txt file that holds the default script settings. Also, if you hit the ? in the top right corner, it will open the MSI setup guide in your browser.

    And I'm not sure if you can have a message appear when hovering over a component. That's something to look into. I'll add it to the first post.

  6. #6
    Join Date
    Jan 2008
    Location
    Ontario, Canada
    Posts
    7,805
    Mentioned
    5 Post(s)
    Quoted
    3 Post(s)

    Default

    Quote Originally Posted by Coh3n View Post
    Oh sorry, I forgot to commit the Settings.txt file that holds the default script settings. Also, if you hit the ? in the top right corner, it will open the MSI setup guide in your browser.

    And I'm not sure if you can have a message appear when hovering over a component. That's something to look into. I'll add it to the first post.
    Most form components have the ``hint'' field, use that!
    Writing an SRL Member Application | [Updated] Pascal Scripting Statements
    My GitHub

    Progress Report:
    13:46 <@BenLand100> <SourceCode> @BenLand100: what you have just said shows you 
                        have serious physchological problems
    13:46 <@BenLand100> HE GETS IT!
    13:46 <@BenLand100> HE FINALLY GETS IT!!!!1

  7. #7
    Join Date
    Apr 2007
    Posts
    3,152
    Mentioned
    3 Post(s)
    Quoted
    1 Post(s)

    Default

    for my list:

    -can't edit names. (timer is probably the only way to do it without a working onclickitem) I completely forgot about that. An Edit button could also be added and once clicked, the selected player's info would show in the TEdits.
    a button is possible, but it would be much nicer if it just did so when you selected a person.

    -make back/combobox/forward an array and all have the same procedures to do stuff. Yeah that all should have been done in the beginning, but you know what, they all work right now, so I suggest leaving it the way it is. That being said, if you want to change them, be my guest.
    i plan to.

    -not loading smart/srl and hopefully msi until after the form closes. I actually looked into this today, and it's not really possible unless we used different variables/types. Right now, throughout the form I set MSI_Players (rather than a temporary "FormPlayers". Also, some functions (from MSI) for setting the magic skill are used and the Script/Location lists are obtained from MSI_Scripts and MSI_Locations (which are set in SetupMSI). When writing most of the functionality I tried my best to make it so the form stuff is updated when MSI's global variables are updated.
    well loading srl/smart at least seems to be possible. I dont see the problem with including the consts file and the file containing the spells into msi and that being it personally. Though i guess i can see why it might not be the perfect solution, it think it would be better than adding the really large wait time loading stuff that might not be needed.

    -change buttons to images This isn't hard, just may be time consuming making all the bitmaps. And honestly, I don't think it's that necessary because we can't make custom ListBoxes, so they would stand out regardless.
    i agree to an extent, but i think that if someone were to make the bitmaps, they should definitely be added. The smaller the number of things that go out of the theme the better. If that werent the case, we might as well get rid of the close button and just use the native ones.

    -shorten form in general (namely making the changing of images to their hovers not stupid complicated) How would you suggest doing it? Again, I suggest leaving this one alone simply because it works. There's no sense in changing something that's working fine.
    I would be willing to bet there are loads of things to be shortened. Im almost positive a lot of the mousehovering stuff is overly complicated.

    -either delete form dragging or make it work There is no code for form dragging? I got rid of it a long time ago, unless I forgot part of it.
    ah, last time i looked there was some stuff. That was 4-5 days ago probably, so unless you got rid of ti before then, i think there is still some stuff.

    -either delete the question mark button or make it work It does work. It opens the MSI setup guide in your browser.
    Didnt know that.

    -try changing certain things to arrays instead of consts Like what? The constants we have now represent the indexes of arrays..
    A perfect example of ways to shorten the code. If they represent indexes of arrays...why not just use arrays? They're shorter. You wouldnt end up with annoying problems like we have now when you want to add something and stuff gets screwed up. Trust me it would make things a lot easier.

    -i dont understand why the >> tab doesn't work in the same way as the other tabs It does? I'm pretty positive I committed it, but earlier today I added that tab to the panels array and it does the same animation as the rest of them.
    Ah, well it was all separate and such before and didnt work in the same way, if that's fixed then great.

    -i also dont understand how the script choosing in the checkboxlists work. What don't you understand? You just check off the scripts you want to use for each player.
    There are just so many items in the list. I was under the impression that the goal was to only display checkboxes for stuff that was applicable to the selected scripts. Like on the 4th tab (including the >>) if i have draynor willows selected, then would varrok east actually be a valid location that the script could work with? If so then disregard my comment


    EDIT: ohh, and fixing the loading and saving of players to have dialog boxes or at the very least, not error if the file you load doesn't exist.
    SCAR Tutorials: The Form Tutorial | Types, Arrays, and Classes
    Programming Projects: NotePad | Tetris | Chess


  8. #8
    Join Date
    Sep 2008
    Location
    Not here.
    Posts
    5,422
    Mentioned
    13 Post(s)
    Quoted
    242 Post(s)

    Default

    Out of range error when you delete the last player to empty the playerlist.

  9. #9
    Join Date
    Apr 2008
    Location
    Marquette, MI
    Posts
    15,252
    Mentioned
    138 Post(s)
    Quoted
    680 Post(s)

    Default

    Quote Originally Posted by Nava2 View Post
    Most form components have the ``hint'' field, use that!
    Genius! I'll have to look into that.

    Quote Originally Posted by Dan Cardin View Post
    i agree to an extent, but i think that if someone were to make the bitmaps, they should definitely be added. The smaller the number of things that go out of the theme the better. If that werent the case, we might as well get rid of the close button and just use the native ones.
    I agree.

    Quote Originally Posted by Dan Cardin View Post
    well loading srl/smart at least seems to be possible. I dont see the problem with including the consts file and the file containing the spells into msi and that being it personally. Though i guess i can see why it might not be the perfect solution, it think it would be better than adding the really large wait time loading stuff that might not be needed.
    There'll have to be a wait regardless. I don't really see the difference if it's before or after the form loads. That's just me though. I think if we were to call MSI_LoadAllScripts, etc before the form came up, it may work. I'm not 100% sure though.

    Quote Originally Posted by Dan Cardin View Post
    I would be willing to bet there are loads of things to be shortened. Im almost positive a lot of the mousehovering stuff is overly complicated.
    Oh I'm sure they is, but right now it works and I have a hard time re-writing something that works.

    Quote Originally Posted by Dan Cardin View Post
    A perfect example of ways to shorten the code. If they represent indexes of arrays...why not just use arrays? They're shorter. You wouldnt end up with annoying problems like we have now when you want to add something and stuff gets screwed up. Trust me it would make things a lot easier.
    I don't know what you mean. There are arrays... the point of the constants are so throughout the script you can use Images[IMG_EXIT] rather than having to remember Images[11] for the exit image. You should be able to change the constants without there being an error, and in this case I don't think you can. When the constants are setup properly, I don't know how you think they're pointless. Maybe you just don't understand them, but that's just my opinion. When used properly, it makes knowing what's what 100% easier.

    Quote Originally Posted by Dan Cardin View Post
    There are just so many items in the list. I was under the impression that the goal was to only display checkboxes for stuff that was applicable to the selected scripts. Like on the 4th tab (including the >>) if i have draynor willows selected, then would varrok east actually be a valid location that the script could work with? If so then disregard my comment
    That's actually a good point, I didn't think of that. I suppose it wouldn't be that hard to change. The valid locations for each script are stored in the TScript record, so is should actually be easy.

    Quote Originally Posted by Dan Cardin View Post
    EDIT: ohh, and fixing the loading and saving of players to have dialog boxes or at the very least, not error if the file you load doesn't exist.
    What error do you get? If the file doesn't exists and message should say "You have to save players before you can load them". And I don't know what you mean when you say they should have dialog boxes.

    Quote Originally Posted by mormonman View Post
    Out of range error when you delete the last player to empty the playerlist.
    Hm, I didn't think you could delete the last player. I'll look into that as soon as I can.

    I also updated the first post.
    Last edited by Coh3n; 12-30-2010 at 08:04 PM.

  10. #10
    Join Date
    Apr 2007
    Posts
    3,152
    Mentioned
    3 Post(s)
    Quoted
    1 Post(s)

    Default

    the load should be after because what if it turns out that you dont want to run the script at all, but you want to just put all your players into the array, save, and exit. But you have to unnecessarily load smart, SRL and MSI. I dont know if you've commited it yet, but you should load smart and srl after because they're unnecessary. MSI can wait i suppose, but i would change it if i knew how.

    I don't know what you mean. There are arrays... the point of the constants are so throughout the script you can use Images[IMG_EXIT] rather than having to remember Images[11] for the exit image. You should be able to change the constants without there being an error, and in this case I don't think you can. When the constants are setup properly, I don't know how you think they're pointless. Maybe you just don't understand them, but that's just my opinion. When used properly, it makes knowing what's what 100% easier.
    i just think its much better. Its 100% shorter too. I would rather have it that much shorter on something that wont break than longer with something easier to read. Also trying to test the form or edit it, it takes like 4 seconds to load just to tell me if i have an error or not.

    That's actually a good point, I didn't think of that. I suppose it wouldn't be that hard to change. The valid locations for each script are stored in the TScript record, so is should actually be easy.
    yay

    What error do you get? If the file doesn't exists and message should say "You have to save players before you can load them". And I don't know what you mean when you say they should have dialog boxes.
    for saving i got " "" is not a valid boolean" and for loading i cant reproduce. By dialogs i mean, when you do "save as" on any application...that, or open.

    EDIT: and from your code, all the stuff still does from IMG_TAB_NORM_1..IMG_TAB_NORM_5. I would have thought that if the >> tab was a tab it would be IMG_TAB_NORM_0..IMG_TAB_NORM_5

    but you probably cant do that so easily because its after all the other tabs in the consts. unless im seeing something wrong here.

    EDIT: and you seem to have included MSI_Form in Setup, so and msi_form includes Setup so....
    and en extra "end;" in a globals function.

    EDIT:
    SCAR Code:
    {$i MSI/MSI/Core/Setup.simba}

    const
      IMG_COUNT = 12;
        IMG_BGND          = 0;
        IMG_X_NORM        = 1;
        IMG_Q_NORM        = 2;
        IMG_LOAD_TAB_NORM = 3;
        IMG_SAVE_TAB_NORM = 4;
        IMG_TAB_NORM_1    = 5;
        IMG_TAB_NORM_2    = 6;
        IMG_TAB_NORM_3    = 7;
        IMG_TAB_NORM_4    = 8;
        IMG_TAB_NORM_5    = 9;
        IMG_TAB_NORM_0    = 10;
        IMG_RUN_NORM      = 11;

        PANEL_COUNT = 6;

      BITMAP_COUNT = 24;
        BGND            = 0;
        X_NORM          = 1;
        X_HOVER         = 2;
        Q_NORM          = 3;
        Q_HOVER         = 4;
        LOAD_TAB_NORM   = 5;
        LOAD_TAB_HOVER  = 6;
        SAVE_TAB_NORM   = 7;
        SAVE_TAB_HOVER  = 8;
        TAB_NORM_1      = 9;
        TAB_HOVER_1     = 10;
        TAB_NORM_2      = 11;
        TAB_HOVER_2     = 12;
        TAB_NORM_3      = 13;
        TAB_HOVER_3     = 14;
        TAB_NORM_4      = 15;
        TAB_HOVER_4     = 16;
        TAB_NORM_5      = 17;
        TAB_HOVER_5     = 18;
        TAB_NORM_0      = 19;
        TAB_HOVER_0     = 20;
        BGND_PANEL      = 21;
        RUN_NORM        = 22;
        RUN_HOVER       = 23;

    // Form components
    var
      MainForm: TForm;
      AnimTimer: TTimer;

      tImages: array[0..IMG_COUNT - 1] of TImage;
      frmBitmaps: array [0..BITMAP_COUNT - 1] of Integer;
      isActiveImage: array[0..IMG_COUNT - 1] of Boolean;
      isLeftTab: array[IMG_TAB_NORM_1..IMG_TAB_NORM_5] of Boolean;
      panels: array [IMG_TAB_NORM_1..IMG_TAB_NORM_1 + PANEL_COUNT - 1] of TPanel;

      Previous,Next: array [IMG_TAB_NORM_2..IMG_TAB_NORM_5] of TButton;
      ChoosePlay: array [IMG_TAB_NORM_2..IMG_TAB_NORM_5] of TCombobox;

    var
      pBoxIndex: Integer; // Stores the index of the player displayed in the combo boxes relative to the combo box, not the MSI_Players array
      ScriptReady: Boolean;

    var // Panel 1: Player Management
      checkList_Players: TCheckListBox;
      edit_User, edit_Pass, edit_Pin: TEdit;
      comboBox_Member: TComboBox;
      btn_AddPlayer, btn_DeletePlayer: TButton;
      panOne_Inst, label_Username, label_Pass, label_Pin, label_Member: TLabel;

    var // Panel 3
      CheckListBox_3: TCheckListBox;
      inst_P3: TLabel;

    var // Panel 4
      CheckListBox_4: TCheckListBox;
      inst_P4: TLabel;

    var // Panel 5
      inst_P5, timeTotal, timeBreak, loadsBreak, loadsTotal: TLabel;
      time_Total_5, time_Break_5, loads_Break_5, loads_Total_5: TEdit;

    var // Panel 6
      inst_P6: TLabel;
      ComboBox_Script_6: TComboBox;
      nScript, pScript: TButton;

    (**
     * Converts a string to an integer array; for example,
     * StrToIntArr(1,2,3,4) will result [1, 2, 3, 4]
     *)

    function StrToIntArr(Str: string): TIntegerArray;
    var
      i: Integer;
      s: TStringArray;
    begin
      if (Str = '') then
        Exit;

      s := Explode(',', Str);

      for i := 0 to High(s) do
        try
          SetLength(Result, Length(Result) + 1);
          Result[High(Result)] := StrToInt(s[i]);
          //Writeln('StrArrToIntArry['+IntToStr(High(Result))+']: '+IntToStr(Result[High(Result)]));
        except
          //Writeln('Invalid integer!');
        end;
    end;

    (**
     * Converts an integer array to a string; for example,
     * IntArrToStr([1, 2, 3, 4]) will result '1,2,3,4'
     *)

    function IntArrToStr(Int: TIntegerArray): string;
    var
      i: Integer;
    begin
      if (Length(Int) <= 0) then
      begin
        Result := '';
        Exit;
      end;

      for i := 0 to High(Int) do
        if (i = High(Int)) then
          Result := Result + IntToStr(Int[i])
        else
          Result := Result + IntToStr(Int[i]) + ',';

      //Writeln(Result);
    end;

    // Get the player index from the player's name
    function GetPlayerIndex(Username: string): Integer;
    var
      i: Integer;
    begin
      if (Username = '') then
        Exit;

      for i := 0 to High(MSI_Players) do
        if (Lowercase(MSI_Players[i].Name) = Lowercase(Username)) then
        begin
          Result := i;
          Exit;
        end;
    end;

    // Prevents people from typing in combo boxes
    procedure PreventTyping(Sender: TObject; var Key: Char);
    begin
      Key := Chr(VK_CANCEL);
    end;

    var // Intro Panel
      intro_Inst, intro_Next: TLabel;

      intro_Combos: array of TComboBox;
      intro_Edits: array of TEdit;
      intro_ComboLabels, intro_EditLabels: array of TLabel;
      s: TStringArray;

    procedure intro_CreateComponents();
    var
      i, j: Integer;
    begin
      intro_Inst := TLabel.Create(panels[IMG_TAB_NORM_0]);
      with intro_Inst do
      begin
        Parent := panels[IMG_TAB_NORM_0];
        SetBounds(70, 5, 100, 25);
        Caption := 'Setup all the different script properties';
        Font.Color := 2070783;
      end;

      intro_Next := TLabel.Create(panels[IMG_TAB_NORM_0]);
      with intro_Next do
      begin
        Parent := panels[IMG_TAB_NORM_0];
        SetBounds(25, 268, 100, 25);
        Caption := 'Click the sliding panels to reveal player setup steps >>';
        Font.Color := 2070783;
      end;

      for i := 0 to High(MSI_SetupVars) do
        case i of
          SETUP_DEBUG_SMART, SETUP_SAVE_DEBUG, SETUP_HUMAN_BREAK, SETUP_SWITCH_WORLDS:
            begin
              SetLength(intro_Combos, Length(intro_Combos) + 1);

              intro_Combos[High(intro_Combos)] := TComboBox.Create(panels[IMG_TAB_NORM_0]);
              with intro_Combos[High(intro_Combos)] do
              begin
                Parent := panels[IMG_TAB_NORM_0];
                Text := 'True';
                Items.Add('True');
                Items.Add('False');
                OnKeyPress := @PreventTyping;

                for j := 0 to High(intro_Combos) do
                  SetBounds(100, 27 + (j * 35), 60, 20);
              end;
            end;

          SETUP_BREAK_TIME, SETUP_DEBUG_LEVEL, SETUP_ANTIBAN_WAIT, SETUP_RANDOMS_WAIT,
          SETUP_STATS_ID, SETUP_STATS_PASS:
            begin
              SetLength(intro_Edits, Length(intro_Edits) + 1);

              intro_Edits[High(intro_Edits)] := TEdit.Create(panels[IMG_TAB_NORM_0]);
              with intro_Edits[High(intro_Edits)] do
              begin
                Parent := panels[IMG_TAB_NORM_0];

                for j := 0 to High(intro_Edits) do
                  SetBounds(252, 27 + (j * 35), 70, 20);
              end;
            end;
        end;

      SetLength(intro_EditLabels, Length(intro_Edits));
      s := ['Break Time', 'Level to Debug', 'Antiban Wait', 'Randoms Wait', 'World',
            'Stats ID', 'Stats Pass'];
      for i := 0 to High(intro_EditLabels) do
      begin
        intro_EditLabels[i] := TLabel.Create(panels[IMG_TAB_NORM_0]);
        with intro_EditLabels[i] do
        begin
          Parent := panels[IMG_TAB_NORM_0];
          Caption := s[i];
          Font.Color := 2070783;
          Font.Size := 8;
          SetBounds(intro_Edits[i].Left - (intro_Edits[i].Width + 12), intro_Edits[i].Top + 4, 50, 25);
        end;
      end;

      SetLength(intro_ComboLabels, Length(intro_Combos));
      s := ['Debug SMART', 'Save Debug', 'Human Breaking', 'Switch Worlds'];
      for i := 0 to High(intro_ComboLabels) do
      begin
        intro_ComboLabels[i] := TLabel.Create(panels[IMG_TAB_NORM_0]);
        with intro_ComboLabels[i] do
        begin
          Parent := panels[IMG_TAB_NORM_0];
          Caption := s[i];
          Font.Color := 2070783;
          Font.Size := 8;
          SetBounds(intro_Combos[i].Left - (intro_Combos[i].Width + 32), intro_Combos[i].Top + 4, 50, 25);
        end;
      end;

    end;

    procedure intro_Settings(Save: Boolean);
    var
      i, j: Integer;
      s: string;
    begin
      for i := 0 to High(MSI_SetupVars) do
        case i of
          SETUP_DEBUG_SMART, SETUP_SAVE_DEBUG, SETUP_HUMAN_BREAK, SETUP_SWITCH_WORLDS:
            begin
              case i of
                SETUP_DEBUG_SMART: s := 'Debug SMART';
                SETUP_SAVE_DEBUG: s := 'Save Debug';
                SETUP_HUMAN_BREAK: s := 'Human Breaking';
                SETUP_SWITCH_WORLDS: s := 'Switch Worlds';
              end;

              for j := 0 to High(intro_ComboLabels) do
                if (intro_ComboLabels[j].Caption = s) then
                  if (Save) then
                  begin
                    WriteINI('SETTINGS', s, intro_Combos[j].Text, PATH_SETTINGS);
                    MSI_SetupVars[i] := StrToBool(intro_Combos[j].Text);
                    //Writeln('SetupVar['+IntToStr(i)+'] := '+ToStr(MSI_SetupVars[i]));
                  end else
                    intro_Combos[j].Text := ReadINI('SETTINGS', s, PATH_SETTINGS);
            end;

          SETUP_BREAK_TIME, SETUP_DEBUG_LEVEL, SETUP_ANTIBAN_WAIT, SETUP_RANDOMS_WAIT,
          SETUP_STATS_ID, SETUP_STATS_PASS:
            begin
              case i of
                SETUP_BREAK_TIME: s := 'Break Time';
                SETUP_DEBUG_LEVEL: s := 'Level to Debug';
                SETUP_ANTIBAN_WAIT: s := 'Antiban Wait';
                SETUP_RANDOMS_WAIT: s := 'Randoms Wait';
                SETUP_STATS_ID: s := 'Stats ID';
                SETUP_STATS_PASS: s := 'Stats Pass';
              end;

              for j := 0 to High(intro_EditLabels) do
                if (intro_EditLabels[j].Caption = s) then
                  if (Save) then
                  begin
                    WriteINI('SETTINGS', s, intro_Edits[j].Text, PATH_SETTINGS);

                    if (i = SETUP_STATS_ID) or (i = SETUP_STATS_PASS) then
                      MSI_SetupVars[i] := intro_Edits[j].Text
                    else
                      MSI_SetupVars[i] := StrToInt(intro_Edits[j].Text);

                    //Writeln('SetupVar['+IntToStr(i)+'] := '+ToStr(MSI_SetupVars[i]));
                  end else
                    intro_Edits[j].Text := ReadINI('SETTINGS', s, PATH_SETTINGS);

            end;
        end;
    end;

    (*
       SCRIPT SETUP COMPONENTS & OTHER
       ===============================

       Written by: Coh3n
    *)


    (**
     * Used to for TScriptSetup for each player
     *)

    const
      LIST_COUNT = 6;
        LIST_ROCKS     = 0;
        LIST_TREES     = 1;
        LIST_FISHSPOTS = 2;
        LIST_SPELLS    = 3;
        LIST_STAFFS    = 4;
        LIST_DROP      = 5;

      EDIT_COUNT = 6;
        EDIT_LOADS      = 0;
        EDIT_TIME       = 1;
        EDIT_LEVEL      = 2;
        EDIT_EXCEPTIONS = 3;
        EDIT_ALCH_SLOTS = 4;
        EDIT_PRIORITY   = 5;

    var
      script_ListTexts, script_EditTexts: TStringArray;
      script_Lists: array[0..LIST_COUNT - 1] of TCheckListBox;
      script_ListLabels: array[0..LIST_COUNT - 1] of TLabel;
      script_Edits: array[0..EDIT_COUNT - 1] of TEdit;
      script_EditLabels: array[0..EDIT_COUNT - 1] of TLabel;
      script_StaffType: TComboBox;

    procedure script_CreateComponents(PanelIndex: Integer);
    var
      i, j: Integer;
    begin
      // TCheckListBoxes
      for i := 0 to High(script_Lists) do
      begin
        script_Lists[i] := TCheckListBox.Create(Panels[PanelIndex]);
        with script_Lists[i] do
        begin
          Parent := Panels[PanelIndex];
          Width := 140;
          Height := 80;
          Left := 20;
          Top := 75;
          Visible := False;

          case i of
            LIST_ROCKS:
              begin
              end;

            LIST_TREES:
              begin
              end;

            LIST_FISHSPOTS:
              begin
              end;

            LIST_SPELLS:
              begin
              end;

            LIST_STAFFS:
              begin
                Left := 20 + Width + 15;
              end;

            LIST_DROP:
              begin
                Left := 20 + Width + 15;

                for i := 0 to High(MSI_Items) do
                begin
                  if (MSI_Items[i].Name = '') then
                    Continue;

                  Items.Append(Capitalize(MSI_Items[i].Name));
                end;
              end;
          end;
        end;
      end;

      // TLabels
      script_ListTexts := ['Rocks', 'Trees', 'Fishing Spots', 'Spells', 'Staffs', 'Don''t Drop/Bank'];
      for i := 0 to High(script_ListLabels) do
      begin
        script_ListLabels[i] := TLabel.Create(Panels[PanelIndex]);
        with script_ListLabels[i] do
        begin
          Parent := Panels[PanelIndex];
          Height := 25;
          Width := script_Lists[i].Width;
          Left := script_Lists[i].Left;
          Top := script_Lists[i].Top - (Height - 5);
          Caption := script_ListTexts[i];
          Font.Color := 2070783;
          Visible := script_Lists[i].Visible;
        end;
      end;

      // TEdits
      for i := 0 to High(script_Edits) do
      begin
        script_Edits[i] := TEdit.Create(Panels[PanelIndex]);
        with script_Edits[i] do
        begin
          Parent := Panels[PanelIndex];
          Height := 20;
          Visible := False;

          case i of
            EDIT_LOADS, EDIT_TIME, EDIT_LEVEL:
              begin
                Width := 40;
                Left := (script_Lists[0].Left + script_Lists[0].Width - (Width + 40));
                Top := (script_Lists[0].Top + script_Lists[0].Height + 20) + ((15 + Height) * i);
                Text := '0';
                Enabled := False;
              end;

            EDIT_EXCEPTIONS, EDIT_ALCH_SLOTS, EDIT_PRIORITY:
              begin
                Width := 80;
                Left := script_Lists[LIST_DROP].Left + (Width - 40);
                Top := (script_Lists[0].Top + script_Lists[0].Height + 20) + ((15 + Height) * (i - 3));
              end;
          end;
        end;
      end;

      // Edit TLabels
      script_EditTexts := ['Loads', 'Time', 'Level', 'Exceptions', 'Alching Slots', 'Priority'];
      for i := 0 to High(script_EditLabels) do
      begin
        script_EditLabels[i] := TLabel.Create(Panels[PanelIndex]);
        with script_EditLabels[i] do
        begin
          Parent := Panels[PanelIndex];
          Height := 25;
          Width := (script_Edits[i].Width);
          Left := script_Edits[i].Left - Width;
          Top := (script_Edits[i].Top + 4);
          Caption := script_EditTexts[i];
          Font.Color := 2070783;
          Visible := script_Edits[i].Visible;
        end;
      end;
    end;

    procedure script_HideComponents();
    var
      i: Integer;
    begin
      for i := 0 to High(script_Lists) do
        script_Lists[i].Visible := False;

      for i := 0 to High(script_Edits) do
        script_Edits[i].Visible := False;

      for i := 0 to High(script_ListLabels) do
        script_ListLabels[i].Visible := False;

      for i := 0 to High(script_EditLabels) do
        script_EditLabels[i].Visible := False;
    end;

    procedure script_ShowComponents();
    var
      i, j, k: Integer;
      default, lists, edits: TIntegerArray;
      mode, index: Integer;
    begin
      script_HideComponents();

      for i := 0 to High(MSI_Scripts) do
        if (MSI_Scripts[i].Name = comboBox_Script_6.Text) then
        begin
          case MSI_Scripts[i].SkillConst of
            SKILL_WOODCUTTING, SKILL_MINING, SKILL_FISHING:
              begin
                case MSI_Scripts[i].SkillConst of
                  SKILL_WOODCUTTING:
                    begin
                      lists :=[LIST_TREES, LIST_DROP];
                      default := MSI_Scripts[i].Defaults.Trees;
                    end;

                  SKILL_MINING:
                    begin
                      lists :=[LIST_ROCKS, LIST_DROP];
                      default := MSI_Scripts[i].Defaults.Rocks;
                    end;

                  SKILL_FISHING:
                    begin
                      lists :=[LIST_FISHSPOTS, LIST_DROP];
                      default := MSI_Scripts[i].Defaults.FishSpots;
                    end;
                end;

                // Lists and edits for Woodcutting, Mining and Woodcutting
                edits := [EDIT_LOADS, EDIT_TIME, EDIT_EXCEPTIONS, EDIT_PRIORITY, EDIT_LEVEL];

                script_Lists[lists[0]].CLEAR;

                // Add the default objects to the TCheckListBox
                for j := 0 to High(default) do
                  for k := 0 to High(MSI_Objects) do
                    if (default[j] = k) then
                      script_Lists[lists[0]].Items.Append(Capitalize(MSI_Objects[k].Name));

                // Make lists visible
                for j := 0 to High(lists) do
                begin
                  script_Lists[lists[j]].Visible := True;
                  script_ListLabels[lists[j]].Visible := True;
                end;

                // Make edit boxes visible
                for j := 0 to High(edits) do
                begin
                  script_Edits[edits[j]].Visible := True;
                  script_EditLabels[edits[j]].Visible := True;
                end;
              end;

            SKILL_MAGIC:
              begin
                // Sets up spells if not already done so
                if (not SpellSetup) then
                  SetupSpells;

                script_Lists[LIST_SPELLS].CLEAR;
                script_Lists[LIST_STAFFS].CLEAR;

                // Adds all the spells to the Spells list
                for j := 0 to High(MSI_Scripts[i].Defaults.Spells) do
                begin
                  mode := MSI_GetSpellMode(MSI_Scripts[i].Defaults.Spells[j], index);
                  script_Lists[LIST_SPELLS].Items.Append(Capitalize(SpellModes[mode][index].Name));
                end;

                // Adds all the staffs to the Staff list
                for j := 0 to High(MSI_Items) do
                  if (Pos('staff', Lowercase(MSI_Items[j].Name)) > 0) then
                    script_Lists[LIST_STAFFS].Items.Append(Capitalize(MSI_Items[j].Name));

                // Makes all the required components visible
                script_Lists[LIST_SPELLS].Visible := True;
                script_Lists[LIST_STAFFS].Visible := True;
                script_ListLabels[LIST_SPELLS].Visible := True;
                script_ListLabels[LIST_STAFFS].Visible := True;
                script_Edits[EDIT_TIME].Visible := True;
                script_EditLabels[EDIT_TIME].Visible := True;
                script_EditLabels[EDIT_ALCH_SLOTS].Visible := True;
                script_Edits[EDIT_ALCH_SLOTS].Visible := True;
              end;
          end;
        end;
    end;

    procedure script_FillComponents(pIndex: Integer); // OnChange
    var
      i, j, k, lIndex, sIndex, skill, mode, index: Integer;
      objects: TIntegerArray;
    begin
      for i := 0 to High(MSI_Scripts) do
        if (comboBox_Script_6.Text = MSI_Scripts[i].Name) then
        begin
          sIndex := comboBox_Script_6.ITEMS.IndexOf(comboBox_Script_6.Text);
          skill := MSI_Scripts[i].SkillConst;
          //Writeln('Skill: '+MSI_Scripts[i].SkillName);
          Break;
        end;

      //Writeln('Script Index: '+IntToStr(sIndex));

      case skill of
        SKILL_WOODCUTTING, SKILL_MINING, SKILL_FISHING:
          begin
            case skill of
              SKILL_WOODCUTTING:
                begin
                  lIndex := LIST_TREES;
                  objects := MSI_Players[pIndex].Scripts[sIndex].Trees;
                end;

              SKILL_MINING:
                begin
                  lIndex := LIST_ROCKS;
                  objects := MSI_Players[pIndex].Scripts[sIndex].Rocks;
                end;

              SKILL_FISHING:
                begin
                  lIndex := LIST_FISHSPOTS;
                  objects := MSI_Players[pIndex].Scripts[sIndex].FishSpots;
                end;
            end;

            // Check off the objects in the list
            //Writeln(ToStr(objects));
            for i := 0 to High(objects) do
              for j := 0 to (script_Lists[lIndex].Items.Count - 1) do
                if (Lowercase(script_Lists[lIndex].Items.Strings[j]) = Lowercase(MSI_Objects[objects[i]].Name)) then
                  script_Lists[lIndex].Checked[j] := True;

            // Check off all the dont drop items
            for i := 0 to High(MSI_Players[pIndex].Scripts[sIndex].DontDrop) do
              for j := 0 to (script_Lists[LIST_DROP].Items.Count - 1) do
                if (Lowercase(script_Lists[LIST_DROP].Items.Strings[j]) = Lowercase(MSI_Items[MSI_Players[pIndex].Scripts[sIndex].DontDrop[i]].Name)) then
                  script_Lists[LIST_DROP].Checked[j] := True;

            with MSI_Players[pIndex].Scripts[sIndex] do
            begin
              script_Edits[EDIT_LOADS].Text := IntToStr(Loads);
              script_Edits[EDIT_LEVEL].Text := IntToStr(MaxLevel);
              script_Edits[EDIT_PRIORITY].Text := IntArrToStr(Priority);
              script_Edits[EDIT_EXCEPTIONS].Text := IntArrToStr(Exceptions);
            end;
          end;

        SKILL_MAGIC:
          begin
            if (not SpellSetup) then
              SetupSpells;

            with MSI_Players[pIndex].Scripts[sIndex] do
            begin
              // Check off all the spells
              for i := 0 to High(Spells) do
              begin
                mode := MSI_GetSpellMode(Spells[i], index);

                for j := 0 to (script_Lists[LIST_SPELLS].ITEMS.Count - 1) do
                  if (Lowercase(SpellModes[mode][index].Name) = Lowercase(script_Lists[LIST_SPELLS].ITEMS.Strings[j])) then
                    script_Lists[LIST_SPELLS].Checked[j] := True;
              end;

              // Check off all the staffs
              for i := 0 to High(Staffs) do
                for j := 0 to (script_Lists[LIST_STAFFS].ITEMS.Count - 1) do
                  if (Lowercase(MSI_Items[Staffs[i]].Name) = Lowercase(script_Lists[LIST_STAFFS].ITEMS.Strings[j])) then
                    script_Lists[LIST_STAFFS].Checked[j] := True;

              // Fill the AlchSlots edit
              script_Edits[EDIT_ALCH_SLOTS].Text := IntArrToStr(MSI_Players[pIndex].Scripts[sIndex].AlchSlots);
            end;
          end;
      end;

      // Time is common for every script
      with MSI_Players[pIndex].Scripts[sIndex] do
        script_Edits[EDIT_TIME].Text := IntToStr(Time);

      //Writeln('Filled Script Setup Components');
    end;

    procedure script_FillCombo();
    var
      i, pIndex: Integer;
    begin
      comboBox_Script_6.CLEAR;

      pIndex := GetPlayerIndex(ChoosePlay[IMG_TAB_NORM_5].Text);

      with MSI_Players[pIndex] do
        for i := 0 to High(Scripts) do
          comboBox_Script_6.Items.Append(MSI_Scripts[Scripts[i].Name].Name);
    end;

    (**
     * Currently sets:
     *
     *)

    procedure script_SetInfo();
    var
      i, j, skill, sIndex, pIndex, lIndex: Integer;
      objects: TIntegerArray;
    begin
      if (comboBox_Script_6.Text = '') then
        Exit;

      for i := 0 to High(MSI_Scripts) do
        if (comboBox_Script_6.Text = MSI_Scripts[i].Name) then
        begin
          sIndex := comboBox_Script_6.ITEMS.IndexOf(comboBox_Script_6.Text);
          //Writeln('Script Index: '+IntToStr(sIndex));
          skill := MSI_Scripts[i].SkillConst;
          Break;
        end;

      pIndex := GetPlayerIndex(ChoosePlay[IMG_TAB_NORM_5].Text);
      //Writeln('Player Index: '+IntToStr(pIndex));

      case skill of
        SKILL_WOODCUTTING, SKILL_MINING, SKILL_FISHING:
          begin
            case skill of
              SKILL_WOODCUTTING:
                lIndex := LIST_TREES;

              SKILL_MINING:
                lIndex := LIST_ROCKS;

              SKILL_FISHING:
                lIndex := LIST_FISHSPOTS;
            end;

            // Set the Trees, Rocks, and FishSpots depending on the skill
            for i := 0 to script_Lists[lIndex].ITEMS.Count - 1 do
              if (script_Lists[lIndex].Checked[i]) then
                for j := 0 to High(MSI_Objects) do
                  if (Lowercase(MSI_Objects[j].Name) = Lowercase(script_Lists[lIndex].Items.Strings[i])) then
                  begin
                    case skill of
                      SKILL_WOODCUTTING:
                        with MSI_Players[pIndex].Scripts[sIndex] do
                        begin
                          SetLength(Trees, Length(Trees) + 1);
                          Trees[High(Trees)] := j;
                          ClearSameIntegers(Trees);
                          //Writeln('Player '+IntToStr(pIndex)+' Trees: '+ToStr(Trees));
                        end;

                      SKILL_MINING:
                        with MSI_Players[pIndex].Scripts[sIndex] do
                        begin
                          SetLength(Rocks, Length(Rocks) + 1);
                          Rocks[High(Rocks)] := j;
                          ClearSameIntegers(Rocks);
                          //Writeln('Player '+IntToStr(pIndex)+' Rocks: '+ToStr(Rocks));
                        end;

                      SKILL_FISHING:
                        with MSI_Players[pIndex].Scripts[sIndex] do
                        begin
                          SetLength(FishSpots, Length(FishSpots) + 1);
                          FishSpots[High(FishSpots)] := j;
                          ClearSameIntegers(FishSpots);
                          //Writeln('Player '+IntToStr(pIndex)+' FishSpots: '+ToStr(FishSpots));
                        end;
                    end;
                  end;

            // Set the items to exclude from dropping/banking
            for i := 0 to (script_Lists[LIST_DROP].ITEMS.Count - 1) do
              if (script_Lists[LIST_DROP].Checked[i]) then
                for j := 0 to High(MSI_Items) do
                  if (Lowercase(script_Lists[LIST_DROP].Items.Strings[i]) = Lowercase(MSI_Items[j].Name)) then
                    with MSI_Players[pIndex].Scripts[sIndex] do
                    begin
                      SetLength(DontDrop, Length(DontDrop) + 1);
                      DontDrop[High(DontDrop)] := j;
                      ClearSameIntegers(DontDrop);
                    end;

            // Set the other script information
            with MSI_Players[pIndex].Scripts[sIndex] do
            begin
              try
                MaxLevel := StrToInt(script_Edits[EDIT_LEVEL].Text);
              except
                ShowMessage('Invalid max level! Please enter a number.');
              end;

              try
                Loads := StrToInt(script_Edits[EDIT_LOADS].Text);
              except
                ShowMessage('Invalid loads! Please enter a number.');
              end;

              try
                Time := StrToInt(script_Edits[EDIT_LOADS].Text);
              except
                ShowMessage('Invalid AnimTimer! Please enter a number.');
              end;

              try
                Exceptions := StrToIntArr(script_Edits[EDIT_EXCEPTIONS].Text);
                ClearSameIntegers(Exceptions);
              except
                ShowMessage('Invalid exceptions input!');
              end;

              try
                Priority := StrToIntArr(script_Edits[EDIT_PRIORITY].Text);
                ClearSameIntegers(Priority);
              except
                ShowMessage('Invalid priority input!');
              end;
            end;
          end;

        SKILL_MAGIC:
          begin
            if (not SpellSetup) then
              SetupSpells;

            // Set the Spells
            for i := 0 to script_Lists[LIST_SPELLS].ITEMS.Count - 1 do
              if (script_Lists[LIST_SPELLS].Checked[i]) then
                with MSI_Players[pIndex].Scripts[sIndex] do
                begin
                  SetLength(Spells, Length(Spells) + 1);
                  Spells[High(Spells)] := MSI_StrToSpell(script_Lists[LIST_SPELLS].ITEMS.Strings[i]);
                  ClearSameIntegers(Spells);
                  //Writeln('Player '+IntToStr(pIndex)+' Spells: '+ToStr(Spells));
                end;

            // Set the staffs
            for i := 0 to script_Lists[LIST_STAFFS].ITEMS.Count - 1 do
              if (script_Lists[LIST_STAFFS].Checked[i]) then
                for j := 0 to High(MSI_Items) do
                  if (Lowercase(MSI_Items[j].Name) = Lowercase(script_Lists[LIST_STAFFS].ITEMS.Strings[i])) then
                    with MSI_Players[pIndex].Scripts[sIndex] do
                    begin
                      SetLength(Staffs, Length(Staffs) + 1);
                      Staffs[High(Staffs)] := j;
                      ClearSameIntegers(Staffs);
                      //Writeln('Player '+IntToStr(pIndex)+' Staffs: '+ToStr(Staffs));
                    end;

            // Set the Alching Slots
            MSI_Players[pIndex].Scripts[sIndex].AlchSlots := StrToIntArr(script_Edits[EDIT_ALCH_SLOTS].Text);
          end;
      end;

      with MSI_Players[pIndex].Scripts[sIndex] do
        try
          Time := StrToInt(script_Edits[EDIT_TIME].Text);
        except
          ShowMessage('Invalid AnimTimer! Please enter a number.');
        end;
    end;

    (*
       END OF SCRIPT SETUP COMPONENTS
       ==============================
    *)


    procedure CheckOffScripts(PlayerIndex: Integer);
    var
      j, k: Integer;
    begin
      for j := 0 to High(MSI_Players[PlayerIndex].Scripts) do
        for k := 0 to (CheckListBox_3.Items.Count - 1) do
          if (Lowercase(MSI_Scripts[MSI_Players[PlayerIndex].Scripts[j].Name].Name) = Lowercase(CheckListBox_3.Items.Strings[k])) then
            CheckListBox_3.Checked[k] := True;
    end;

    procedure CheckOffLocs(PlayerIndex: Integer);
    var
      j, k: Integer;
    begin
      with MSI_Players[PlayerIndex] do
        for k := 0 to (CheckListBox_4.Items.Count - 1) do
          if (Lowercase(MSI_Locations[Location].Name) = Lowercase(CheckListBox_4.Items.Strings[k])) then
          begin
            CheckListBox_4.Checked[k] := True;
            Break;
          end;
    end;

    procedure LoadOther(pIndex: Integer);
    begin
      time_Total_5.Text := IntToStr(MSI_Players[pIndex].TotalTime);
      time_Break_5.Text := IntToStr(MSI_Players[pIndex].BreakTime);
      loads_Break_5.Text := IntToStr(MSI_Players[pIndex].BreakLoads);
      loads_Total_5.Text := IntToStr(MSI_Players[pIndex].TotalLoads);

      time_Total_5.Enabled := True;
      time_Break_5.Enabled := True;
      loads_Break_5.Enabled := True;
      loads_Total_5.Enabled := True;
    end;

    procedure LoadPlayersToPanels(s: string);
    var
      i, j, k, pIndex: Integer;
    begin
      s := Capitalize(s);

      for i := IMG_TAB_NORM_2 to IMG_TAB_NORM_5 do
      ChoosePlay[i].Items.Append(s);
    end;

    function SetScriptConsts(): TIntegerArray;
    var
      i, j: Integer;
    begin
      for i := 0 to (CheckListBox_3.Items.Count - 1) do
        if (CheckListBox_3.Checked[i]) then
          for j := 0 to High(MSI_Scripts) do
          begin
            if (MSI_Scripts[j].Name = '') then
              Continue;

            if (Lowercase(CheckListBox_3.Items.Strings[i]) = Lowercase(MSI_Scripts[j].Name)) then
            begin
              SetLength(Result, Length(Result) + 1);
              Result[High(Result)] := MSI_Scripts[j].Constant;
            end;
          end;

      for i := 0 to High(MSI_Players) do
        if (Lowercase(ChoosePlay[IMG_TAB_NORM_2].Text) = Lowercase(MSI_Players[i].Name)) then
        begin
          SetLength(MSI_Players[i].Scripts, Length(Result));

          for j := 0 to High(MSI_Players[i].Scripts) do
          begin
            MSI_Players[i].Scripts[j].Name := Result[j];
            //Writeln(IntToStr(MSI_Players[i].Scripts[j].Name));
          end;

          Break;
        end;

      //Writeln('Scripts: ' + ToStr(Result));
    end;

    function SetLocConsts(): Integer;
    var
      i, j: Integer;
    begin
      for i := 0 to (CheckListBox_4.Items.Count - 1) do
        if (CheckListBox_4.Checked[i]) then
          for j := 0 to High(MSI_Locations) do
          begin
            if (MSI_Locations[j].Name = '') then
              Continue;

            if (Lowercase(ChoosePlay[IMG_TAB_NORM_3].Items.Strings[i]) = Lowercase(MSI_Locations[j].Name)) then
            begin
              Result := MSI_Locations[j].Constant;
              Break;
            end;
          end;

      for i := 0 to High(MSI_Players) do
        if (Lowercase(ChoosePlay[IMG_TAB_NORM_3].Text) = Lowercase(MSI_Players[i].Name)) then
        begin
          MSI_Players[i].Location := Result;
          //Writeln('Location: ' + ToStr(MSI_Players[i].Location));
          Break;
        end;

    end;

    procedure SetOther();
    var
      i: Integer;
    begin
      for i := 0 to High(MSI_Players) do
        if (Lowercase(ChoosePlay[IMG_TAB_NORM_4].Text) = Lowercase(MSI_Players[i].Name)) then
          with MSI_Players[i] do
          begin
            try
              TotalTime := StrToInt(time_Total_5.Text);
            except
              ShowMessage('Total AnimTimer must be a number!');
              Exit;
            end;

            try
              BreakTime := StrToInt(time_Break_5.Text);
            except
              ShowMessage('Break after (AnimTimer) must be a number!');
              Exit;
            end;

            try
              BreakLoads := StrToInt(loads_Break_5.Text);
            except
              ShowMessage('Break after (loads) must be a number!');
              Exit;
            end;

            try
              TotalLoads := StrToInt(loads_Total_5.Text);
            except
              ShowMessage('Total loads must be a number!');
              Exit;
            end;

            Break;
          end;

      //Writeln('Others set!');
    end;

    procedure SavePlayers();
    var
      i, j, k: Integer;
      s: string;
    begin
      intro_Settings(True);

      WriteINI('Number of Players', 'NumberOfPlayers', IntToStr(Length(MSI_Players)), PATH_PLAYER);

      for i := 0 to High(MSI_Players) do
        with MSI_Players[i] do
        begin
          s := '';
          Active := checkList_Players.Checked[i];
          SetLocConsts;
          script_SetInfo;

          WriteINI(IntToStr(i), 'Name', Name, PATH_PLAYER);
          WriteINI(IntToStr(i), 'Pass', Pass, PATH_PLAYER);
          WriteINI(IntToStr(i), 'Nick', Nick, PATH_PLAYER);
          WriteINI(IntToStr(i), 'Pin', Pin, PATH_PLAYER);
          WriteINI(IntToStr(i), 'Active', BoolToStr(Active), PATH_PLAYER);
          WriteINI(IntToStr(i), 'Member', BoolToStr(Member), PATH_PLAYER);
          WriteINI(IntToStr(i), 'Location', IntToStr(Location), PATH_PLAYER);
          WriteINI(IntToStr(i), 'BreakTime', IntToStr(BreakTime), PATH_PLAYER);
          WriteINI(IntToStr(i), 'BreakLoads', IntToStr(BreakLoads), PATH_PLAYER);
          WriteINI(IntToStr(i), 'TotalTime', IntToStr(TotalTime), PATH_PLAYER);
          WriteINI(IntToStr(i), 'TotalLoads', IntToStr(TotalLoads), PATH_PLAYER);

          WriteINI(IntToStr(i), 'NumberOfScripts', IntToStr(Length(Scripts)), PATH_PLAYER);
          for j := 0 to High(Scripts) do
          begin
            // Set for all skills
            WriteINI(IntToStr(i), 'Script'+IntToStr(j)+'.Name', IntToStr(Scripts[j].Name), PATH_PLAYER);
            WriteINI(IntToStr(i), 'Script'+IntToStr(j)+'.Time', IntToStr(Scripts[j].Time), PATH_PLAYER);

            case MSI_Scripts[Scripts[j].Name].SkillConst of
              SKILL_WOODCUTTING, SKILL_FISHING, SKILL_MINING:
                begin
                  // DontDrop
                  if (Length(Scripts[j].DontDrop) > 0) then
                    WriteINI(IntToStr(i), 'Script'+IntToStr(j)+'.DontDrop', IntArrToStr(Scripts[j].DontDrop), PATH_PLAYER);

                  // Exceoptions
                  if (Length(Scripts[j].Exceptions) > 0) then
                    WriteINI(IntToStr(i), 'Script'+IntToStr(j)+'.Exceptions', IntArrToStr(Scripts[j].Exceptions), PATH_PLAYER);

                  // Priority
                  if (Length(Scripts[j].Priority) > 0) then
                    WriteINI(IntToStr(i), 'Script'+IntToStr(j)+'.Priority', IntArrToStr(Scripts[j].Priority), PATH_PLAYER);

                  // Level and Loads
                  WriteINI(IntToStr(i), 'Script'+IntToStr(j)+'.MaxLevel', IntToStr(Scripts[j].MaxLevel), PATH_PLAYER);
                  WriteINI(IntToStr(i), 'Script'+IntToStr(j)+'.Loads', IntToStr(Scripts[j].Loads), PATH_PLAYER);

                  // Trees, Rocks, and FishSpots
                  case MSI_Scripts[Scripts[j].Name].SkillConst of
                    SKILL_WOODCUTTING:
                      WriteINI(IntToStr(i), 'Script'+IntToStr(j)+'.Trees', IntArrToStr(Scripts[j].Trees), PATH_PLAYER);

                    SKILL_MINING:
                      WriteINI(IntToStr(i), 'Script'+IntToStr(j)+'.Rocks', IntArrToStr(Scripts[j].Rocks), PATH_PLAYER);

                    SKILL_FISHING:
                      WriteINI(IntToStr(i), 'Script'+IntToStr(j)+'.FishSpots', IntArrToStr(Scripts[j].FishSpots), PATH_PLAYER);
                  end;
                end;

              SKILL_MAGIC:
                begin
                  // Staffs
                  if (Length(Scripts[j].Staffs) > 0) then
                    WriteINI(IntToStr(i), 'Script'+IntToStr(j)+'.Staffs', IntArrToStr(Scripts[j].Staffs), PATH_PLAYER);

                  // Spells
                  if (Length(Scripts[j].Spells) > 0) then
                    WriteINI(IntToStr(i), 'Script'+IntToStr(j)+'.Spells', IntArrToStr(Scripts[j].Spells), PATH_PLAYER);

                  // AlchSlots
                  if (Length(Scripts[j].AlchSlots) > 0) then
                    WriteINI(IntToStr(i), 'Script'+IntToStr(j)+'.AlchSlots', IntArrToStr(Scripts[j].AlchSlots), PATH_PLAYER);
                end;
            end;
          end;
        end;

      ShowMessage('Saved Players!');
    end;

    procedure LoadPlayers();
    var
      i, j: Integer;
      nPlayers, s, p: string;
    begin
      if (not FileExists(PATH_PLAYER)) then
      begin
        ShowMessage('Players need to be saved before they can be loaded!');
        Exit;
      end;

      nPlayers := ReadINI('Number of Players', 'NumberOfPlayers', PATH_PLAYER);
      SetLength(MSI_Players, StrToInt(nPlayers));

      for i := 0 to High(MSI_Players) do
        with MSI_Players[i] do
        begin
          Name := ReadINI(IntToStr(i), 'Name', PATH_PLAYER);
          Pass := ReadINI(IntToStr(i), 'Pass', PATH_PLAYER);
          Nick := ReadINI(IntToStr(i), 'Nick', PATH_PLAYER);
          Pin := ReadINI(IntToStr(i), 'Pin', PATH_PLAYER);
          Active := StrToBool(ReadINI(IntToStr(i), 'Active', PATH_PLAYER));
          Member := StrToBool(ReadINI(IntToStr(i), 'Member', PATH_PLAYER));
          Location := StrToInt(ReadINI(IntToStr(i), 'Location', PATH_PLAYER));
          BreakTime := StrToInt(ReadINI(IntToStr(i), 'BreakTime', PATH_PLAYER));
          BreakLoads := StrToInt(ReadINI(IntToStr(i), 'BreakLoads', PATH_PLAYER));
          TotalTime := StrToInt(ReadINI(IntToStr(i), 'TotalTime', PATH_PLAYER));
          TotalLoads := StrToInt(ReadINI(IntToStr(i), 'TotalLoads', PATH_PLAYER));

          if (Member) then
          begin
            comboBox_Member.Text := 'True';
            s := '[P2P] '
          end else begin
            comboBox_Member.Text := 'False';
            s := '[F2P] ';
          end;

          if (Pin <> '') then
            p := 'Pin';

          checkList_Players.Items.Append(s + Capitalize(Name) + ' (' + Pass + ')' + p + Pin);
          checkList_Players.Checked[i] := Active;

          LoadPlayersToPanels(Name);

          SetLength(Scripts, StrToInt(ReadINI(IntToStr(i), 'NumberOfScripts', PATH_PLAYER)));
          for j := 0 to High(Scripts) do
          begin
            Scripts[j].Name := StrToInt(ReadINI(IntToStr(i), 'Script'+IntToStr(j)+'.Name', PATH_PLAYER));
            Scripts[j].Time := StrToInt(ReadINI(IntToStr(i), 'Script'+IntToStr(j)+'.Time', PATH_PLAYER));

            try
              Scripts[j].Trees := StrToIntArr(ReadINI(IntToStr(i), 'Script'+IntToStr(j)+'.Trees', PATH_PLAYER));
              Scripts[j].Rocks := StrToIntArr(ReadINI(IntToStr(i), 'Script'+IntToStr(j)+'.Rocks', PATH_PLAYER));
              Scripts[j].FishSpots := StrToIntArr(ReadINI(IntToStr(i), 'Script'+IntToStr(j)+'.FishSpots', PATH_PLAYER));
              Scripts[j].Spells := StrToIntArr(ReadINI(IntToStr(i), 'Script'+IntToStr(j)+'.Spells', PATH_PLAYER));
              Scripts[j].DontDrop := StrToIntArr(ReadINI(IntToStr(i), 'Script'+IntToStr(j)+'.DontDrop', PATH_PLAYER));
              Scripts[j].Exceptions := StrToIntArr(ReadINI(IntToStr(i), 'Script'+IntToStr(j)+'.Exceptions', PATH_PLAYER));
              Scripts[j].Priority := StrToIntArr(ReadINI(IntToStr(i), 'Script'+IntToStr(j)+'.Priority', PATH_PLAYER));
              Scripts[j].AlchSlots := StrToIntArr(ReadINI(IntToStr(i), 'Script'+IntToStr(j)+'.AlchSlots', PATH_PLAYER));
              Scripts[j].Loads := StrToInt(ReadINI(IntToStr(i), 'Script'+IntToStr(j)+'.Loads', PATH_PLAYER));
              Scripts[j].MaxLevel := StrToInt(ReadINI(IntToStr(i), 'Script'+IntToStr(j)+'.MaxLevel', PATH_PLAYER));
            except
              //Writeln('INI Doesn''t Exist!');
            end;
          end;
        end;

      tImages[IMG_LOAD_TAB_NORM].Enabled := False;
      btn_DeletePlayer.Enabled := (Length(MSI_Players) > 1);
      ShowMessage('Loaded Players!');
    end;

    procedure OnMouseMove(Sender: TObject; Shift: TShiftState; x, y: Integer);
    var
      x1, y1, hi, i, j, bmp, xdif, ydif, h: Integer;
      BoundL, BoundT: Extended;
      imgSwap, bmpArr, imgArr: Array of Integer;
    begin
      bmpArr := [ X_NORM, Q_NORM, LOAD_TAB_NORM,
                  SAVE_TAB_NORM, TAB_NORM_1, TAB_NORM_2,
                  TAB_NORM_3, TAB_NORM_4, TAB_NORM_5, TAB_NORM_0, RUN_NORM ];

      imgArr := [ IMG_X_NORM, IMG_Q_NORM, IMG_LOAD_TAB_NORM,
                  IMG_SAVE_TAB_NORM, IMG_TAB_NORM_1, IMG_TAB_NORM_2,
                  IMG_TAB_NORM_3, IMG_TAB_NORM_4, IMG_TAB_NORM_5, IMG_TAB_NORM_0, IMG_RUN_NORM ];

      hi := High(bmpArr);
      case Sender of
        tImages[IMG_BGND], Panels[IMG_TAB_NORM_1],
        Panels[IMG_TAB_NORM_2], Panels[IMG_TAB_NORM_3], Panels[IMG_TAB_NORM_4],
        Panels[IMG_TAB_NORM_5], Panels[IMG_TAB_NORM_0]:
          begin
            for i := 0 to hi do
            begin
              if (not isActiveImage[imgArr[i]]) then
                Continue;

              bmp := frmBitmaps[bmpArr[i]];
              DrawBitmap(bmp, tImages[imgArr[i]].Canvas, 0, 0);
              isActiveImage[imgArr[i]] := False;
            end;
          end;
      end;

      for h := 0 to hi do
        case Sender of
          tImages[imgArr[h]]:
            begin
              imgSwap := [imgArr[h], frmBitmaps[bmpArr[h] + 1]];
              if (not isActiveImage[imgSwap[0]]) then
              begin
                DrawBitmap(imgSwap[1],tImages[imgSwap[0]].Canvas,0,0);
                isActiveImage[imgSwap[0]] := True;
                for i := 0 to hi do
                begin
                  if (Sender = tImages[imgArr[i]]) then
                    Continue;

                  if (not isActiveImage[imgArr[i]]) then
                    Continue;

                  if (i = imgSwap[0] - 1) then
                    Continue;

                  bmp := frmBitmaps[bmpArr[i]];
                  DrawBitmap(bmp, tImages[imgArr[i]].Canvas, 0, 0);
                  isActiveImage[imgArr[i]] := False;
                end;
              end;
          end;
      end;
    end;

    const
      MAX_MOVE = 315;

    var
      accel, pMoved, senderTab, pan: integer;
      onLeft: Boolean;

    procedure OnTimerEnabled(Sender: TObject);
    var
      i, e, d, hi, lo: Integer;
    begin
      accel := accel + 2;
      pMoved := pMoved + accel;

      if (senderTab = IMG_TAB_NORM_0) then
      begin
        panels[IMG_TAB_NORM_0].Width := panels[IMG_TAB_NORM_0].Width + accel;

        for i := IMG_TAB_NORM_1 to IMG_TAB_NORM_5 do
        begin
          if (not isLeftTab[i]) then
            Continue;

          tImages[i].Left := tImages[i].Left + accel;

          if (pMoved >= MAX_MOVE) then
          begin
            isLeftTab[i] := False;
            AnimTimer.Enabled := False;
            tImages[i].Left := tImages[i].Left - 5;
          end;
        end;
      end else
      begin
        if (onLeft) then
          for i := senderTab to IMG_TAB_NORM_5 do
          begin
            if (i = senderTab) or (not isLeftTab[i]) then
              Continue;

            tImages[i].Left := tImages[i].Left + accel;

            if (pMoved >= MAX_MOVE) then
            begin
              isLeftTab[i] := False;
              AnimTimer.Enabled := False;
              tImages[i].Left := tImages[i].Left - 5;
            end;

            //Writeln(BoolToStr(isLeftTab[i]));
          end
        else begin
          panels[IMG_TAB_NORM_0].Width := panels[IMG_TAB_NORM_0].Width - accel;

          for i := senderTab downto IMG_TAB_NORM_1 do
          begin
            if (isLeftTab[i]) then
              Continue;

            tImages[i].Left := tImages[i].Left - accel;

            if (pMoved >= MAX_MOVE) then
            begin
              isLeftTab[i] := True;
              AnimTimer.Enabled := False;
              tImages[i].Left := tImages[i].Left + 5;
            end;

          end;
        end;
      end;

      for i := IMG_TAB_NORM_1 to IMG_TAB_NORM_5 do
      begin
        panels[i].left := tImages[i].left + tImages[i].width + 2
        if i <> IMG_TAB_NORM_5 then
          panels[i].width := tImages[i + 1].left - panels[i].left - 2
        else
          panels[i].width := MainForm.width - panels[i].left - 10;
      end;

      if (senderTab = IMG_TAB_NORM_0) then
        if (pMoved >= MAX_MOVE) then
          panels[IMG_TAB_NORM_0].Width := panels[IMG_TAB_NORM_0].Width - 10;
    end;

    procedure OnTabClick(Sender: TObject);
    var
      i: integer;
    begin
      if not AnimTimer.ENABLED then
      begin
        accel := 0;
        pMoved := 0;
        AnimTimer.enabled := true;
        pan := senderTab;

        if (Sender = tImages[IMG_TAB_NORM_0]) then
          senderTab := IMG_TAB_NORM_0;

        for i := IMG_TAB_NORM_1 to IMG_TAB_NORM_5 do
          if (Sender = tImages[i]) then
          begin
            senderTab := i;
            if (isLeftTab[senderTab]) then
              onLeft := True
            else
              onLeft := False;
          end;
      end;
    end;

    procedure OnClickEvents(Sender: TObject); // OnClick
    var
      i, j, t: integer;
      bmpArr, tScripts: TIntegerArray;
    begin
      for i := IMG_TAB_NORM_1 to IMG_TAB_NORM_5 do
        if (isLeftTab[i]) then
          Inc(t);

      for i := IMG_TAB_NORM_1 to IMG_TAB_NORM_5 do
        case Sender of
          tImages[i]:
            begin
              if (isLeftTab[i]) then
                if (t <= (i - (IMG_TAB_NORM_5 - IMG_TAB_NORM_1))) then
                  Exit;

              OnTabClick(Sender);

              if (not isLeftTab[i]) then
              begin
                bmpArr := [TAB_NORM_1, TAB_NORM_2, TAB_NORM_3, TAB_NORM_4, TAB_NORM_5];
                DrawBitmap(frmBitmaps[bmpArr[i-IMG_TAB_NORM_1]], tImages[i].Canvas, 0, 0);
              end;
            end;
        end;

      case Sender of
        tImages[IMG_X_NORM]:
          begin
            for i := 0 to BITMAP_COUNT - 1 do
              FreeBitmap(frmBitmaps[i]);

            MainForm.ModalResult := mrOk;
          end;

        tImages[IMG_Q_NORM]: OpenWebPage('http://villavu.com/forum/showthread.php?t=57723');

        tImages[IMG_TAB_NORM_0]:
          begin
            if (t <= 0) then
              Exit;

            OnTabClick(Sender);
          end;

        tImages[IMG_SAVE_TAB_NORM]:
          begin
            DrawBitmap(frmBitmaps[SAVE_TAB_NORM],tImages[IMG_SAVE_TAB_NORM].Canvas, 0, 0);
            SetScriptConsts;
            SetLocConsts;
            SetOther;
            SavePlayers;
          end;

        tImages[IMG_LOAD_TAB_NORM]:
          begin
            DrawBitmap(frmBitmaps[LOAD_TAB_NORM],tImages[IMG_LOAD_TAB_NORM].Canvas, 0, 0);
            LoadPlayers;
          end;

        tImages[IMG_RUN_NORM]:
          begin
            ScriptReady := True;

            intro_Settings(True);
            script_SetInfo();
            SetScriptConsts();
            SetLocConsts();
            SetOther();
            SavePlayers();

            MainForm.ModalResult := mrOk;
          end;
        comboBox_Script_6:
          script_SetInfo;
      end;
    end;

    {******************************************************************************}
    { Name: function GenerateNick(Username: string): string;                       }
    { By: Coh3n                                                                    }
    { Description: Generates the players nickname based on their username          }
    {******************************************************************************}
    function GenerateNick(Username: string): string;
    var
      i, j: Integer;
      s: TStringArray;
    begin
      s := Explode(' ', Username);
      for i := 0 to High(s) do
        if (Length(s[i]) >= 4) then
        begin
          for j := 2 to 4 do
            Result := Result + s[i][j];

          Break;
        end;

      //Writeln('Username: ' + Username);
      //Writeln('Nickname: ' + Result);
    end;

    {******************************************************************************}
    { Name: procedure AddPlayer();                                                 }
    { By: Coh3n                                                                    }
    { Description: Adds a player to the player array. Called when the Add Player   }
    {              button is pressed                                               }
    {******************************************************************************}
    procedure AddPlayer();
    var
      h: Integer;
    begin
      SetLength(MSI_Players, Length(MSI_Players) + 1);
      btn_DeletePlayer.Enabled := (Length(MSI_Players) > 1);

      h := High(MSI_Players);
      with MSI_Players[h] do
      begin
        Name   := edit_User.Text;
        Pass   := edit_Pass.Text;
        Nick   := GenerateNick(Name);
        Pin    := edit_Pin.Text;
        Active := checkList_Players.Checked[checkList_Players.ItemIndex];
        Member := StrToBool(comboBox_Member.Text);

        //Writeln(Name);
        //Writeln(Pass);
        //Writeln(Nick);
        //Writeln(Pin);
        //Writeln(BoolToStr(Active));
        //Writeln(BoolToStr(Member));
      end;

      //Writeln('Player Length: ' + IntToStr(Length(MSI_Players)));
    end;

    {******************************************************************************}
    { Name: procedure RemovePlayer();                                              }
    { By: Masterkill & Coh3n                                                       }
    { Description: Removes a player from the player array. Called when the Remove  }
    {              Player button is pressed                                        }
    {******************************************************************************}
    procedure RemovePlayer();
    var
      i: Integer;
    begin
      //Writeln(IntToStr(checkList_Players.ItemIndex));
      if (not (checkList_Players.ItemIndex = High(MSI_Players))) then
        if (checkList_Players.ItemIndex + 1 = High(MSI_Players)) then
          MSI_Players[checkList_Players.ItemIndex] := MSI_Players[High(MSI_Players)]
        else
          for i := checkList_Players.ItemIndex to High(MSI_Players) - 1 do
            MSI_Players[i] := MSI_Players[i + 1];

      btn_DeletePlayer.Enabled := (Length(MSI_Players) > 1);

      SetLength(MSI_Players, Length(MSI_Players) - 1);
      //Writeln('Player Length: ' + IntToStr(Length(MSI_Players)));
    end;

    procedure PanelOneClicks(Sender: TObject); // OnChange
    var
      sel, i: integer;
      s, p: string;
    begin
      case sender of
        btn_AddPlayer:
          begin
            if (StrToBool(comboBox_Member.Text)) then
              s := '[P2P] '
            else
              s := '[F2P] ';

            if (edit_Pin.Text <> '') then
              p := 'Pin';

            checkList_Players.Items.Append(s + Capitalize(edit_User.Text) + ' (' + edit_Pass.Text + ')' + p + edit_Pin.Text);

            // Add player to the combo box on other panels
            LoadPlayersToPanels(edit_User.Text);

            checkList_Players.Checked[checkList_Players.items.Count - 1] := true;
            checkList_Players.ItemIndex := checkList_Players.Items.Count - 1;

            AddPlayer();

            edit_User.Text := '';
            edit_Pass.Text := '';
            edit_Pin.Text := '';
         end;

        btn_DeletePlayer:
          begin
            if checkList_Players.ItemIndex >= 0 then
              sel := checkList_Players.ItemIndex;
            checkList_Players.Items.Delete(sel);
            for i := IMG_TAB_NORM_2 to IMG_TAB_NORM_5 do
              ChoosePlay[i].Items.Delete(sel);
            if sel = 0 then
              sel := 1;
            checkList_Players.ItemIndex := sel - 1;

            RemovePlayer();

            edit_User.Text := '';
            edit_Pass.Text := '';
            edit_Pin.Text := '';
          end;
      end;
    end;

    procedure PanelFiveClicks(Sender: TObject); // OnChange
    var
      pIndex, i: Integer;
    begin
      case sender of
        ComboBox_Script_6:
          begin
            script_ShowComponents();

            for i := 0 to script_Lists[LIST_DROP].ITEMS.Count - 1 do
              if (script_Lists[LIST_DROP].Checked[i]) then
                script_Lists[LIST_DROP].Checked[i] := False;

            pIndex := GetPlayerIndex(ChoosePlay[IMG_TAB_NORM_5].Text);
            script_FillComponents(pIndex);
          end;

        nScript:
          if ComboBox_Script_6.ITEMINDEX < ComboBox_Script_6.ITEMS.Count then
            ComboBox_Script_6.ItemIndex := ComboBox_Script_6.ItemIndex + 1;

        pScript:
          if ComboBox_Script_6.ITEMINDEX > 0 then
            ComboBox_Script_6.ItemIndex := ComboBox_Script_6.ItemIndex - 1;
      end;
    end;



    procedure PlayerControls(Sender: TObject);
    var i, pIndex: integer;
    begin
      for i := IMG_TAB_NORM_2 to IMG_TAB_NORM_5 do
        case sender of
          ChoosePlay[i]: pBoxIndex := ChoosePlay[i].ItemIndex;
          Previous[i]: if ChoosePlay[i].ItemIndex > 0 then
                         ChoosePlay[i].ItemIndex := ChoosePlay[i].ItemIndex - 1;
          Next[i]: if ChoosePlay[i].ItemIndex < ChoosePlay[i].Items.Count then
                     ChoosePlay[i].ItemIndex := ChoosePlay[i].ItemIndex + 1;
        end;
      case sender of
        ChoosePlay[IMG_TAB_NORM_2]: SetScriptConsts;
        ChoosePlay[IMG_TAB_NORM_3]: SetLocConsts;
        ChoosePlay[IMG_TAB_NORM_4]: SetOther();
        ChoosePlay[IMG_TAB_NORM_5]: script_SetInfo();
        Next[IMG_TAB_NORM_2]:
          if ChoosePlay[IMG_TAB_NORM_2].ItemIndex < ChoosePlay[IMG_TAB_NORM_2].Items.Count then
          begin
            pBoxIndex := ChoosePlay[IMG_TAB_NORM_2].ItemIndex;
            SetScriptConsts;
            pIndex := GetPlayerIndex(ChoosePlay[IMG_TAB_NORM_2].Items.Strings[pBoxIndex]);
            CheckOffScripts(pIndex);

            ChoosePlay[IMG_TAB_NORM_2].ItemIndex := ChoosePlay[IMG_TAB_NORM_2].ItemIndex + 1;

            for i := 0 to CheckListBox_3.Items.Count - 1 do
              CheckListBox_3.Checked[i] := False;
          end;
      end;
    end;

    procedure PlayerCUpdate(Sender: TObject);
    var i, pIndex: integer;
    begin
    case sender of
        ChoosePlay[IMG_TAB_NORM_2]:
          begin
            for i := 0 to CheckListBox_3.ITEMS.Count - 1 do
              CheckListBox_3.Checked[i] := False;

            pIndex := GetPlayerIndex(ChoosePlay[IMG_TAB_NORM_2].Text);
            CheckOffScripts(pIndex);
            CheckListBox_3.Enabled := True;
          end;
        ChoosePlay[IMG_TAB_NORM_3]:
          begin
            for i := 0 to CheckListBox_4.ITEMS.Count - 1 do
              CheckListBox_4.Checked[i] := False;

            pIndex := GetPlayerIndex(ChoosePlay[IMG_TAB_NORM_3].Text);

            CheckOffLocs(pIndex);
            CheckListBox_4.Enabled := True;
          end;
        ChoosePlay[IMG_TAB_NORM_4]:
          begin
            pIndex := GetPlayerIndex(ChoosePlay[IMG_TAB_NORM_4].Text);
            LoadOther(pIndex);
          end;
        ChoosePlay[IMG_TAB_NORM_5]:
          begin
            SetScriptConsts();
            script_FillCombo();
            script_HideComponents();
          end;
          end;
    end;



    // Used to display a background image on the panels
    var
      bgndPanel: TImage;
      a, b: Integer;

    procedure InitForm;
    var
      i, pan: Integer;
      consts: TintegerArray;
      bmpArr: TStringArray;
      xy: TPointArray;
      visibl: array of boolean;
      wh: TPoint;
    begin
      bmpArr := ['BGND','X_NORM','X_HOVER','Q_NORM','Q_HOVER','LOAD_TAB_NORM','LOAD_TAB_HOVER','SAVE_TAB_NORM','SAVE_TAB_HOVER','TAB_NORM_1','TAB_HOVER_1','TAB_NORM_2','TAB_HOVER_2','TAB_NORM_3','TAB_HOVER_3','TAB_NORM_4','TAB_HOVER_4','TAB_NORM_5','TAB_HOVER_5','TAB_NORM_0','TAB_HOVER_0', 'BGND_PANEL', 'RUN_NORM', 'RUN_HOVER'];
      for i := 0 to High(frmBitmaps) do
        frmBitmaps[i] := LoadBitmap(ScriptPath + 'Bitmaps\' + bmpArr[i] + '.png');

      MainForm := TForm.Create(nil);
      MainForm.SetBounds({L} 100, {T} 100, {W} 600, {H} 400);
      MainForm.Position := poScreenCenter;
      MainForm.BorderStyle := bsNone;

      AnimTimer := TTimer.Create(MainForm);
      with AnimTimer do
      begin
        ONTIMER := @OnTimerEnabled;
        INTERVAL := 10;
        ENABLED := false;
      end;

      xy     := [Point(0, 0), Point(575, 7), Point(557, 7), Point(7, 69),   Point(81, 69),  Point(386, 100), Point(427, 100), Point(468, 100), Point(509, 100), Point(550, 100), Point(8, 222), Point(519, 69) ];
      SetArrayLength(visibl, GetArrayLength(xy));
      consts := [BGND,        X_NORM,        Q_NORM,        LOAD_TAB_NORM,  SAVE_TAB_NORM,  TAB_NORM_1,      TAB_NORM_2,      TAB_NORM_3,      TAB_NORM_4,      TAB_NORM_5,      TAB_NORM_0,    RUN_NORM       ];

      for i := 0 to IMG_COUNT - 1 do
      begin
        tImages[i] := TImage.Create(MainForm)
        with tImages[i] do
        begin
          Parent := MainForm;
          GetBitmapSize(frmBitmaps[consts[i]], wh.x, wh.y);
          SetBounds(xy[i].x, xy[i].y, wh.x, wh.y);
          OnMouseMove := @OnMouseMove;
          OnClick := @OnClickEvents;
          isActiveImage[i] := False;
        end;
        DrawBitmap(frmBitmaps[consts[i]], tImages[i].canvas, 0, 0);
      end;

      for i := low(panels) to high(panels) do
      begin
        panels[i] := TPanel.Create(MainForm);
        panels[i].parent := MainForm;
        GetBitmapSize(frmBitmaps[consts[i]], wh.x, wh.y);
        panels[i].SetBounds(xy[i].x + wh.x, xy[i].y, 0, wh.y);
        panels[i].BevelWidth := 0;

        if (i = High(panels)) then
          panels[i].SetBounds(10 + tImages[IMG_TAB_NORM_0].Width, 100,
                              tImages[IMG_TAB_NORM_1].Left - (tImages[IMG_TAB_NORM_0].Left + tImages[IMG_TAB_NORM_0].Width) - 4,
                              tImages[IMG_TAB_NORM_1].Height);

        bgndPanel := TImage.Create(panels[i]);
        bgndPanel.Parent := panels[i];
        bgndPanel.Visible := True;
        GetBitmapSize(frmBitmaps[BGND_PANEL], a, b);
        bgndPanel.SetBounds(0, 0, a, b);
        DrawBitmap(frmBitmaps[BGND_PANEL], bgndPanel.Canvas, 0, 0);
      end;

      pan := IMG_TAB_NORM_1;

      checkList_Players := TCheckListBox.Create(panels[pan]);
      checkList_Players.Parent := panels[pan];
      checkList_Players.SetBounds(10, 55, 225, 220);

      label_Username := TLabel.Create(panels[pan]);
      label_Username.Parent := panels[pan];
      label_Username.Setbounds(245,55,50,13);
      label_Username.Caption := 'Username';
      label_Username.Font.Color := 2070783;

      edit_User := TEdit.Create(panels[pan]);
      edit_User.Parent := panels[pan];
      edit_User.SetBounds(label_Username.left,label_Username.top + label_Username.height + 5,83,21);

      label_Pass := TLabel.Create(panels[pan]);
      label_Pass.Parent := panels[pan];
      label_Pass.Setbounds(label_Username.left, edit_User.top + edit_User.height + 10,32,13);
      label_Pass.Caption := 'Password';
      label_Pass.Font.Color := 2070783;

      edit_Pass := TEdit.Create(panels[pan]);
      edit_Pass.Parent := panels[pan];
      edit_Pass.SetBounds(label_Username.left,label_Pass.top + label_Pass.height + 5,83,21);

      label_Pin := TLabel.Create(panels[pan]);
      label_Pin.Parent := panels[pan];
      label_Pin.Setbounds(label_Username.left, edit_Pass.top + edit_Pass.height + 10,32,13);
      label_Pin.Caption := 'Pin';
      label_Pin.Font.Color := 2070783;

      edit_Pin := TEdit.Create(panels[pan]);
      edit_Pin.Parent := panels[pan];
      edit_Pin.SetBounds(label_Username.left, label_Pin.top + label_Pin.height + 5, 83, 21);
      edit_Pin.MaxLength := 4;

      label_Member := TLabel.Create(panels[pan]);
      label_Member.Parent := panels[pan];
      label_Member.Setbounds(label_Username.left, edit_Pin.top + edit_Pin.height + 10,32,13);
      label_Member.Caption := 'Members';
      label_Member.Font.Color := 2070783;

      comboBox_Member := TComboBox.Create(panels[pan]);
      comboBox_Member.Parent := panels[pan];
      comboBox_Member.SetBounds(label_Username.left, label_Member.top + label_Member.height + 5, 83, 21);
      comboBox_Member.OnKeyPress := @PreventTyping;
      comboBox_Member.Items.Add('True');
      comboBox_Member.Items.Add('False');
      comboBox_Member.Text := 'False';

      btn_AddPlayer := TButton.Create(panels[pan]);
      btn_AddPlayer.Parent := panels[pan];
      btn_AddPlayer.Setbounds(22,22,95,25);
      btn_AddPlayer.Caption := 'Add Player';
      btn_AddPlayer.ONCLICK := @PanelOneClicks;

      btn_DeletePlayer := TButton.Create(panels[pan]);
      btn_DeletePlayer.Parent := panels[pan];
      btn_DeletePlayer.SetBounds(btn_AddPlayer.left+btn_AddPlayer.width+10,btn_AddPlayer.top,btn_AddPlayer.width,btn_AddPlayer.height);
      btn_DeletePlayer.Caption := 'Remove Player';
      btn_DeletePlayer.OnClick := @PanelOneClicks;
      btn_DeletePlayer.Enabled := (Length(MSI_Players) > 1);

      panOne_Inst := TLabel.Create(panels[pan]);
      panOne_Inst.Parent := panels[pan];
      panOne_Inst.SetBounds(50,3,73,25);
      panOne_Inst.Caption := 'Input player information and click Add Player';
      panOne_Inst.Font.Color := 2070783;


      for i := low(Previous) to high(Previous) do
      begin
        Previous[i] := TButton.Create(panels[i]);
        Previous[i].Parent := panels[i];
        Previous[i].SetBounds(35,24,73,25);
        Previous[i].Caption := 'Previous';
        Previous[i].OnClick := @PlayerControls;
        //Previous[i].Visible := False;

        ChoosePlay[i] := TComboBox.Create(panels[i]);
        ChoosePlay[i].Parent := panels[i];
        ChoosePlay[i].SetBounds(Previous[i].left + Previous[i].width + 5,Previous[i].top,115,21);
        ChoosePlay[i].OnChange := @PlayerCUpdate;
        ChoosePlay[i].OnKeyPress := @PreventTyping;
        ChoosePlay[i].OnClick := @PlayerControls;

        Next[i] := TButton.Create(panels[i]);
        Next[i].Parent := panels[i];
        Next[i].SetBounds(ChoosePlay[i].left + ChoosePlay[i].width + 5, ChoosePlay[i].top,75,25);
        Next[i].Caption := 'Next';
        Next[i].OnClick := @PlayerControls;
        //Next[i].Visible := False;
      end;


      pan := IMG_TAB_NORM_2;

      inst_P3 := TLabel.Create(panels[pan]);
      inst_P3.Parent := panels[pan];
      inst_P3.SetBounds(60,3,73,25);
      inst_P3.Caption := 'Choose a script(s) for each player to use';
      inst_P3.Font.Color := 2070783;

      CheckListBox_3 := TCheckListBox.Create(panels[pan]);
      CheckListBox_3.Parent := panels[pan];
      CheckListBox_3.SetBounds(10, 55, 315, 220);
      for i := 0 to High(MSI_Scripts) do
      begin
        if (MSI_Scripts[i].Name = '') then
          Continue;

        CheckListBox_3.Items.Add(Capitalize(MSI_Scripts[i].Name));
      end;

      CheckListBox_3.Enabled := False;




      pan := IMG_TAB_NORM_3;

      CheckListBox_4 := TCheckListBox.Create(panels[pan]);
      CheckListBox_4.Parent := panels[pan];
      CheckListBox_4.SetBounds(10, 55, 315, 220);
      for i := 0 to High(MSI_Locations) do
      begin
        if (MSI_Locations[i].Name = '') or (MSI_Locations[i].Name = 'Lost') then
          Continue;

        CheckListBox_4.Items.Append(Capitalize(MSI_Locations[i].Name));
      end;
      CheckListBox_4.Enabled := False;

      inst_P4 := TLabel.Create(panels[pan]);
      inst_P4.Parent := panels[pan];
      inst_P4.SetBounds(85, 3, 73, 25);
      inst_P4.Caption := 'Set a location for each player';
      inst_P4.Font.Color := 2070783;




      pan := IMG_TAB_NORM_4;

      inst_P5 := TLabel.Create(panels[pan]);
      inst_P5.Parent := panels[pan];
      inst_P5.SetBounds(38, 3, 73, 25);
      inst_P5.Caption := 'Set all other required information for each player';
      inst_P5.Font.Color := 2070783;

      time_Total_5 := TEdit.Create(panels[pan]);
      time_Total_5.Parent := panels[pan];
      time_Total_5.SetBounds(180, 60, 83, 21);
      time_Total_5.Text := '0';
      time_Total_5.Enabled := False;

      loads_Total_5 := TEdit.Create(panels[pan]);
      with loads_Total_5 do
      begin
        Parent := panels[pan];
        SetBounds(time_Total_5.Left, time_Total_5.Top + time_Total_5.Height + 10, 83, 21);
        Text := '0';
        Enabled := False;
      end;

      time_Break_5 := TEdit.Create(panels[pan]);
      time_Break_5.Parent := panels[pan];
      time_Break_5.SetBounds(time_Total_5.Left, loads_Total_5.Top + loads_Total_5.Height + 10, 83, 21);
      time_Break_5.Text := '0';
      time_Break_5.Enabled := False;

      loads_Break_5 := TEdit.Create(panels[pan]);
      loads_Break_5.Parent := panels[pan];
      loads_Break_5.SetBounds(time_Total_5.Left, time_Break_5.Top + time_Break_5.Height + 10, 83, 21);
      loads_Break_5.Text := '0';
      loads_Break_5.Enabled := False;

      timeTotal := TLabel.Create(panels[pan]);
      timeTotal.Parent := panels[pan];
      timeTotal.Setbounds(55, 63,32,13);
      timeTotal.Caption := 'Total Time (minutes)';
      timeTotal.Font.Color := 2070783;

      loadsTotal := TLabel.Create(panels[pan]);
      with loadsTotal do
      begin
        Parent := panels[pan];
        Setbounds(timeTotal.Left, timeTotal.Top + time_total_5.height + 10,32,13);
        Caption := 'Total Loads';
        Font.Color := 2070783;
      end;

      timeBreak := TLabel.Create(panels[pan]);
      timeBreak.Parent := panels[pan];
      timeBreak.Setbounds(timeTotal.Left, loadsTotal.Top + loads_total_5.height + 10,32,13);
      timeBreak.Caption := 'Break After (minutes)';
      timeBreak.Font.Color := 2070783;

      loadsBreak := TLabel.Create(panels[pan]);
      loadsBreak.Parent := panels[pan];
      loadsBreak.Setbounds(timeTotal.Left, timeBreak.Top + time_Break_5.Height+10,32,13);
      loadsBreak.Caption := 'Break After (loads)';
      loadsBreak.Font.Color := 2070783;



      pan := IMG_TAB_NORM_5;

      script_CreateComponents(pan);

      nScript := TButton.Create(panels[pan]);
      nScript.Parent := panels[pan];
      nScript.SetBounds(Previous[pan].Left, Previous[pan].Top + Previous[pan].Height + 10, 73, 25);
      nScript.Caption := 'Previous';
      nScript.OnClick := @PanelFiveClicks;
      nScript.Visible := False;

      ComboBox_Script_6 := TComboBox.Create(panels[pan]);
      ComboBox_Script_6.Parent := panels[pan];
      ComboBox_Script_6.SetBounds(175, ChoosePlay[pan].top, 115, 21);
      ComboBox_Script_6.OnChange := @PanelFiveClicks;
      ComboBox_Script_6.OnKeyPress := @PreventTyping;
      ComboBox_Script_6.OnClick := @OnClickEvents;

      pScript := TButton.Create(panels[pan]);
      pScript.Parent := panels[pan];
      pScript.SetBounds(ComboBox_Script_6.left + ComboBox_Script_6.width + 5,nScript.top,75,25);
      pScript.Caption := 'Next';
      pScript.OnClick := @PanelFiveClicks;
      pScript.Visible := False;

      inst_P6 := TLabel.Create(panels[pan]);
      inst_P6.Parent := panels[pan];
      inst_P6.SetBounds(75, 3, 73, 25);
      inst_P6.Caption := 'Setup each script for each player';
      inst_P6.Font.Color := 2070783;

      intro_CreateComponents;
      intro_Settings(False);
    end;

    procedure SafeInitForm;
    var
      v: TVariantArray;
    begin
      SetArrayLength(v, 0);
      ThreadSafeCall('InitForm', v);
    end;

    procedure ShowFormModal;
    begin
      MainForm.ShowModal;
    end;

    procedure SafeShowFormModal;
    var
      v: TVariantArray;
    begin
      SetArrayLength(v, 0);
      ThreadSafeCall('ShowFormModal', v);
    end;
    that's with the next/previous stuff done. It compiles, but the combobox stuff doesnt update correctly with all of them. I'm not sure what's wrong because i didn't write any of those and I dont know what they do exactly.
    Last edited by Dan Cardin; 12-31-2010 at 12:10 AM.
    SCAR Tutorials: The Form Tutorial | Types, Arrays, and Classes
    Programming Projects: NotePad | Tetris | Chess


  11. #11
    Join Date
    Apr 2008
    Location
    Marquette, MI
    Posts
    15,252
    Mentioned
    138 Post(s)
    Quoted
    680 Post(s)

    Default

    Quote Originally Posted by Dan Cardin View Post
    the load should be after because what if it turns out that you dont want to run the script at all, but you want to just put all your players into the array, save, and exit. But you have to unnecessarily load smart, SRL and MSI. I dont know if you've commited it yet, but you should load smart and srl after because they're unnecessary. MSI can wait i suppose, but i would change it if i knew how.
    I would change it too if there was an effective way of doing it without rewriting everything. And honestly, how many people are going to do what you just said? I don't feel it's worth the trouble. E: I just got an idea, I'll try it out as soon as I can and let you know.

    Quote Originally Posted by Dan Cardin View Post
    i just think its much better. Its 100% shorter too. I would rather have it that much shorter on something that wont break than longer with something easier to read. Also trying to test the form or edit it, it takes like 4 seconds to load just to tell me if i have an error or not.
    So many people are hung up on having short code when it's much smarter to have something that works the exact same, but is much easier to read and understand. But again, I guess it's personal opinion. The Form will be staying the way it is as that's how the rest of MSI is, plus it's working perfectly fine (excluding small errors that occur with every initial release).

    Quote Originally Posted by Dan Cardin View Post
    for saving i got " "" is not a valid boolean" and for loading i cant reproduce. By dialogs i mean, when you do "save as" on any application...that, or open.
    Oh this is because you didn't fill out one of the script settings combo boxes. I forgot to commit the Settings.txt file that fills out the default settings. Update your MSI and you'll have that file. I'll add that to the bugs though. The part that checks the combo box's text should in a try statement so you don't get that error. Also, I don't have a clue of how to do a "Save As" type thing, or if it's possible, but I like the idea.

    Quote Originally Posted by Dan Cardin View Post
    EDIT: and from your code, all the stuff still does from IMG_TAB_NORM_1..IMG_TAB_NORM_5. I would have thought that if the >> tab was a tab it would be IMG_TAB_NORM_0..IMG_TAB_NORM_5

    but you probably cant do that so easily because its after all the other tabs in the consts. unless im seeing something wrong here.
    That's what I tried to do originally, but I couldn't get it working properly for some reason, so I just added it to the end of the array. It's all working fine now, so I'm not too concerned about this.

    I'm pretty sure it was an issue with the constants (I know you'll probably flame me for saying that). When done right, using constants are beautiful for scripting efficiency. I'm not sure where, but it seems somewhere they got messed up. I've never really looked to try to find it. I just wanted it to work.

    Quote Originally Posted by Dan Cardin View Post
    EDIT: and you seem to have included MSI_Form in Setup, so and msi_form includes Setup so....
    The form doesn't include Setup.simba? It's commented out.

    Quote Originally Posted by Dan Cardin View Post
    and en extra "end;" in a globals function.
    What?
    Last edited by Coh3n; 12-31-2010 at 12:13 AM.

  12. #12
    Join Date
    Apr 2007
    Posts
    3,152
    Mentioned
    3 Post(s)
    Quoted
    1 Post(s)

    Default

    ahh, i must have accidentally commented it.

    And i tried running the form and it told me "function srl_InFight: Boolean;" had an extra end.

    see my above post. hopefully you'll know what's wrong.
    SCAR Tutorials: The Form Tutorial | Types, Arrays, and Classes
    Programming Projects: NotePad | Tetris | Chess


  13. #13
    Join Date
    Apr 2008
    Location
    Marquette, MI
    Posts
    15,252
    Mentioned
    138 Post(s)
    Quoted
    680 Post(s)

    Default

    Quote Originally Posted by Dan Cardin View Post
    that's with the next/previous stuff done. It compiles, but the combobox stuff doesnt update correctly with all of them. I'm not sure what's wrong because i didn't write any of those and I dont know what they do exactly.
    Do the Next/Previous buttons work? I couldn't get them to work properly for some reason. For the combo boxes are you talking about the player ones on each tab? I'll have to see what you changed cause they were working fine.

    E: You have an old version of the form. I stopped committing to the form repository. It's all in the MSI repository now. Sorry I didn't mention that earlier.
    Last edited by Coh3n; 12-31-2010 at 06:21 AM.

  14. #14
    Join Date
    Apr 2007
    Posts
    3,152
    Mentioned
    3 Post(s)
    Quoted
    1 Post(s)

    Default

    I really hope that doesnt change much in the stuff pertaining to what i changed.

    EDIT: and it looks to me like the buttons work. It just doesnt enable the checkboxlist on the first tab with it, and it errors when you try to onclick an comboboxitem on the 2nd page
    Last edited by Dan Cardin; 12-31-2010 at 02:55 AM.
    SCAR Tutorials: The Form Tutorial | Types, Arrays, and Classes
    Programming Projects: NotePad | Tetris | Chess


  15. #15
    Join Date
    Apr 2008
    Location
    Marquette, MI
    Posts
    15,252
    Mentioned
    138 Post(s)
    Quoted
    680 Post(s)

    Default

    Quote Originally Posted by Dan Cardin View Post
    I really hope that doesnt change much in the stuff pertaining to what i changed.

    EDIT: and it looks to me like the buttons work. It just doesnt enable the checkboxlist on the first tab with it, and it errors when you try to onclick an comboboxitem on the 2nd page
    That's odd, I'll have to look into it when I get more time.

    E: Committed a couple things: fixed the out of range when deleting the last player in the list and added some hints to the first panel.

    E2: Okay Dan, I looked at the stuff you changed. For the most part, what I've changed in newer versions won't effect what you've changed, I'll just have to manually make your changes rather than apply a patch. Everything you've done looks great, nice work; however, the last tab (5) won't work properly the way you have it because of the way I've set it up.


    I put them side by side because I was kind of pressed for space (we planned out the form incorrectly; we should have placed all the components and then made images around them). What I think the best option would be is to "stack" the combo boxes and Previous/Next buttons. So, it would look something like this:


    Since Tab 5 is tight for space, we could have a form like this pop up that has all the script's setup components. And we could just have "OK" and "Cancel" buttons on the setup form (which I could make in Photoshop in a couple minutes; we could also just use the "X" image again).


    What do you think? It would also leave plenty of room for additions as they come.

  16. #16
    Join Date
    Apr 2007
    Posts
    3,152
    Mentioned
    3 Post(s)
    Quoted
    1 Post(s)

    Default

    Yea, i wanted to fix that in mine cuz the combobox was overlapping and screwed up, but i forgot. Hmm. Is a lot of stuff planned to go in there? I would rather not have a pop up, but if you really cant fit everything in the space without making it look cramped, then it looks like the next best thing.

    Did you see what was wrong with the checkboxelists?

    EDIT: looks like you fixed the error, and but the next button seems to skippp.

    EDIT: maybe not....I'm not sure which file im supposed to run to run the form any more. Or to start msi for that matter

    EDIT: so, i had to recheckout the repo for it to add my RunMe file and when i do it tells me

    [Error] C:\Documents and Settings\Owner\Desktop\simba\Includes\MSI/MSI/Core/Reports.simba(98:107): Unknown identifier 'RandomsResult' at line 97

    EDIT: i think im good. but you havent applied my changes yet, so ill wait. I can try making patches instead of just posting my version of the script from now on.
    Last edited by Dan Cardin; 12-31-2010 at 04:50 PM.
    SCAR Tutorials: The Form Tutorial | Types, Arrays, and Classes
    Programming Projects: NotePad | Tetris | Chess


  17. #17
    Join Date
    Apr 2008
    Location
    Marquette, MI
    Posts
    15,252
    Mentioned
    138 Post(s)
    Quoted
    680 Post(s)

    Default

    Quote Originally Posted by Dan Cardin View Post
    Yea, i wanted to fix that in mine cuz the combobox was overlapping and screwed up, but i forgot. Hmm. Is a lot of stuff planned to go in there? I would rather not have a pop up, but if you really cant fit everything in the space without making it look cramped, then it looks like the next best thing.
    Yeah I would rather avoid it too; however, if we stack the last tab, even if we crammed the components in there I don't think there would be enough room. Plus with a pop up, there's tons of space for additions (and we make additions all the time).

    Quote Originally Posted by Dan Cardin View Post
    Did you see what was wrong with the checkboxelists?

    EDIT: looks like you fixed the error, and but the next button seems to skippp.

    EDIT: maybe not....I'm not sure which file im supposed to run to run the form any more. Or to start msi for that matter
    Yeah no, I haven't made any of your changes yet; just looked through them. And no, I didn't see the error; but I'm sure I'll find it when I start making the changes.

    And sorry for the confusion. To run the form (and MSI) all you have to do is download MSI to you includes folder via SVN (http://www.villavu.com/repositories/msi), and open and run RunMe.simba. Yes, you'll have to wait for SMART to load, but I'm going to try to fix that right now.

  18. #18
    Join Date
    Apr 2007
    Posts
    3,152
    Mentioned
    3 Post(s)
    Quoted
    1 Post(s)

    Default

    so, i had to recheckout the repo for it to add my RunMe file (because updating wouldnt add it before) and when i do it tells me

    [Error] C:\Documents and Settings\Owner\Desktop\simba\Includes\MSI/MSI/Core/Reports.simba(98:107): Unknown identifier 'RandomsResult' at line 97

    i think im good. but you havent applied my changes yet, so ill wait. I can try making patches instead of just posting my version of the script from now on.

    EDIT: and it didn't seem like i had the error anymore, but if you're going to apply my changes, use this -
    SCAR Code:
    {$i MSI/MSI/Core/Setup.simba}

    const
      IMG_COUNT = 12;
        IMG_BGND          = 0;
        IMG_X_NORM        = 1;
        IMG_Q_NORM        = 2;
        IMG_LOAD_TAB_NORM = 3;
        IMG_SAVE_TAB_NORM = 4;
        IMG_TAB_NORM_1    = 5;
        IMG_TAB_NORM_2    = 6;
        IMG_TAB_NORM_3    = 7;
        IMG_TAB_NORM_4    = 8;
        IMG_TAB_NORM_5    = 9;
        IMG_TAB_NORM_0    = 10;
        IMG_RUN_NORM      = 11;

        PANEL_COUNT = 6;

      BITMAP_COUNT = 24;
        BGND            = 0;
        X_NORM          = 1;
        X_HOVER         = 2;
        Q_NORM          = 3;
        Q_HOVER         = 4;
        LOAD_TAB_NORM   = 5;
        LOAD_TAB_HOVER  = 6;
        SAVE_TAB_NORM   = 7;
        SAVE_TAB_HOVER  = 8;
        TAB_NORM_1      = 9;
        TAB_HOVER_1     = 10;
        TAB_NORM_2      = 11;
        TAB_HOVER_2     = 12;
        TAB_NORM_3      = 13;
        TAB_HOVER_3     = 14;
        TAB_NORM_4      = 15;
        TAB_HOVER_4     = 16;
        TAB_NORM_5      = 17;
        TAB_HOVER_5     = 18;
        TAB_NORM_0      = 19;
        TAB_HOVER_0     = 20;
        BGND_PANEL      = 21;
        RUN_NORM        = 22;
        RUN_HOVER       = 23;

    // Form components
    var
      MainForm: TForm;
      AnimTimer: TTimer;

      tImages: array[0..IMG_COUNT - 1] of TImage;
      frmBitmaps: array [0..BITMAP_COUNT - 1] of Integer;
      isActiveImage: array[0..IMG_COUNT - 1] of Boolean;
      isLeftTab: array[IMG_TAB_NORM_1..IMG_TAB_NORM_5] of Boolean;
      panels: array [IMG_TAB_NORM_1..IMG_TAB_NORM_1 + PANEL_COUNT - 1] of TPanel;

      Previous,Next: array [IMG_TAB_NORM_2..IMG_TAB_NORM_5] of TButton;
      ChoosePlay: array [IMG_TAB_NORM_2..IMG_TAB_NORM_5] of TCombobox;

    var
      pBoxIndex: Integer; // Stores the index of the player displayed in the combo boxes relative to the combo box, not the MSI_Players array
      ScriptReady: Boolean;

    var // Panel 1: Player Management
      checkList_Players: TCheckListBox;
      edit_User, edit_Pass, edit_Pin: TEdit;
      comboBox_Member: TComboBox;
      btn_AddPlayer, btn_DeletePlayer: TButton;
      panOne_Inst, label_Username, label_Pass, label_Pin, label_Member: TLabel;

    var // Panel 3
      CheckListBox_3: TCheckListBox;
      inst_P3: TLabel;

    var // Panel 4
      CheckListBox_4: TCheckListBox;
      inst_P4: TLabel;

    var // Panel 5
      inst_P5, timeTotal, timeBreak, loadsBreak, loadsTotal: TLabel;
      time_Total_5, time_Break_5, loads_Break_5, loads_Total_5: TEdit;

    var // Panel 6
      inst_P6: TLabel;
      ComboBox_Script_6: TComboBox;
      nScript, pScript: TButton;

    (**
     * Converts a string to an integer array; for example,
     * StrToIntArr(1,2,3,4) will result [1, 2, 3, 4]
     *)

    function StrToIntArr(Str: string): TIntegerArray;
    var
      i: Integer;
      s: TStringArray;
    begin
      if (Str = '') then
        Exit;

      s := Explode(',', Str);

      for i := 0 to High(s) do
        try
          SetLength(Result, Length(Result) + 1);
          Result[High(Result)] := StrToInt(s[i]);
          //Writeln('StrArrToIntArry['+IntToStr(High(Result))+']: '+IntToStr(Result[High(Result)]));
        except
          //Writeln('Invalid integer!');
        end;
    end;

    (**
     * Converts an integer array to a string; for example,
     * IntArrToStr([1, 2, 3, 4]) will result '1,2,3,4'
     *)

    function IntArrToStr(Int: TIntegerArray): string;
    var
      i: Integer;
    begin
      if (Length(Int) <= 0) then
      begin
        Result := '';
        Exit;
      end;

      for i := 0 to High(Int) do
        if (i = High(Int)) then
          Result := Result + IntToStr(Int[i])
        else
          Result := Result + IntToStr(Int[i]) + ',';

      //Writeln(Result);
    end;

    // Get the player index from the player's name
    function GetPlayerIndex(Username: string): Integer;
    var
      i: Integer;
    begin
      if (Username = '') then
        Exit;

      for i := 0 to High(MSI_Players) do
        if (Lowercase(MSI_Players[i].Name) = Lowercase(Username)) then
        begin
          Result := i;
          Exit;
        end;
    end;

    // Prevents people from typing in combo boxes
    procedure PreventTyping(Sender: TObject; var Key: Char);
    begin
      Key := Chr(VK_CANCEL);
    end;

    var // Intro Panel
      intro_Inst, intro_Next: TLabel;

      intro_Combos: array of TComboBox;
      intro_Edits: array of TEdit;
      intro_ComboLabels, intro_EditLabels: array of TLabel;
      s: TStringArray;

    procedure intro_CreateComponents();
    var
      i, j: Integer;
    begin
      intro_Inst := TLabel.Create(panels[IMG_TAB_NORM_0]);
      with intro_Inst do
      begin
        Parent := panels[IMG_TAB_NORM_0];
        SetBounds(70, 5, 100, 25);
        Caption := 'Setup all the different script properties';
        Font.Color := 2070783;
      end;

      intro_Next := TLabel.Create(panels[IMG_TAB_NORM_0]);
      with intro_Next do
      begin
        Parent := panels[IMG_TAB_NORM_0];
        SetBounds(25, 268, 100, 25);
        Caption := 'Click the sliding panels to reveal player setup steps >>';
        Font.Color := 2070783;
      end;

      for i := 0 to High(MSI_SetupVars) do
        case i of
          SETUP_DEBUG_SMART, SETUP_SAVE_DEBUG, SETUP_HUMAN_BREAK, SETUP_SWITCH_WORLDS:
            begin
              SetLength(intro_Combos, Length(intro_Combos) + 1);

              intro_Combos[High(intro_Combos)] := TComboBox.Create(panels[IMG_TAB_NORM_0]);
              with intro_Combos[High(intro_Combos)] do
              begin
                Parent := panels[IMG_TAB_NORM_0];
                Text := 'True';
                Items.Add('True');
                Items.Add('False');
                OnKeyPress := @PreventTyping;

                for j := 0 to High(intro_Combos) do
                  SetBounds(100, 27 + (j * 35), 60, 20);
              end;
            end;

          SETUP_BREAK_TIME, SETUP_DEBUG_LEVEL, SETUP_ANTIBAN_WAIT, SETUP_RANDOMS_WAIT,
          SETUP_STATS_ID, SETUP_STATS_PASS:
            begin
              SetLength(intro_Edits, Length(intro_Edits) + 1);

              intro_Edits[High(intro_Edits)] := TEdit.Create(panels[IMG_TAB_NORM_0]);
              with intro_Edits[High(intro_Edits)] do
              begin
                Parent := panels[IMG_TAB_NORM_0];

                for j := 0 to High(intro_Edits) do
                  SetBounds(252, 27 + (j * 35), 70, 20);
              end;
            end;
        end;

      SetLength(intro_EditLabels, Length(intro_Edits));
      s := ['Break Time', 'Level to Debug', 'Antiban Wait', 'Randoms Wait', 'World',
            'Stats ID', 'Stats Pass'];
      for i := 0 to High(intro_EditLabels) do
      begin
        intro_EditLabels[i] := TLabel.Create(panels[IMG_TAB_NORM_0]);
        with intro_EditLabels[i] do
        begin
          Parent := panels[IMG_TAB_NORM_0];
          Caption := s[i];
          Font.Color := 2070783;
          Font.Size := 8;
          SetBounds(intro_Edits[i].Left - (intro_Edits[i].Width + 12), intro_Edits[i].Top + 4, 50, 25);
        end;
      end;

      SetLength(intro_ComboLabels, Length(intro_Combos));
      s := ['Debug SMART', 'Save Debug', 'Human Breaking', 'Switch Worlds'];
      for i := 0 to High(intro_ComboLabels) do
      begin
        intro_ComboLabels[i] := TLabel.Create(panels[IMG_TAB_NORM_0]);
        with intro_ComboLabels[i] do
        begin
          Parent := panels[IMG_TAB_NORM_0];
          Caption := s[i];
          Font.Color := 2070783;
          Font.Size := 8;
          SetBounds(intro_Combos[i].Left - (intro_Combos[i].Width + 32), intro_Combos[i].Top + 4, 50, 25);
        end;
      end;

    end;

    procedure intro_Settings(Save: Boolean);
    var
      i, j: Integer;
      s: string;
    begin
      for i := 0 to High(MSI_SetupVars) do
        case i of
          SETUP_DEBUG_SMART, SETUP_SAVE_DEBUG, SETUP_HUMAN_BREAK, SETUP_SWITCH_WORLDS:
            begin
              case i of
                SETUP_DEBUG_SMART: s := 'Debug SMART';
                SETUP_SAVE_DEBUG: s := 'Save Debug';
                SETUP_HUMAN_BREAK: s := 'Human Breaking';
                SETUP_SWITCH_WORLDS: s := 'Switch Worlds';
              end;

              for j := 0 to High(intro_ComboLabels) do
                if (intro_ComboLabels[j].Caption = s) then
                  if (Save) then
                  begin
                    WriteINI('SETTINGS', s, intro_Combos[j].Text, PATH_SETTINGS);
                    MSI_SetupVars[i] := StrToBool(intro_Combos[j].Text);
                    //Writeln('SetupVar['+IntToStr(i)+'] := '+ToStr(MSI_SetupVars[i]));
                  end else
                    intro_Combos[j].Text := ReadINI('SETTINGS', s, PATH_SETTINGS);
            end;

          SETUP_BREAK_TIME, SETUP_DEBUG_LEVEL, SETUP_ANTIBAN_WAIT, SETUP_RANDOMS_WAIT,
          SETUP_STATS_ID, SETUP_STATS_PASS:
            begin
              case i of
                SETUP_BREAK_TIME: s := 'Break Time';
                SETUP_DEBUG_LEVEL: s := 'Level to Debug';
                SETUP_ANTIBAN_WAIT: s := 'Antiban Wait';
                SETUP_RANDOMS_WAIT: s := 'Randoms Wait';
                SETUP_STATS_ID: s := 'Stats ID';
                SETUP_STATS_PASS: s := 'Stats Pass';
              end;

              for j := 0 to High(intro_EditLabels) do
                if (intro_EditLabels[j].Caption = s) then
                  if (Save) then
                  begin
                    WriteINI('SETTINGS', s, intro_Edits[j].Text, PATH_SETTINGS);

                    if (i = SETUP_STATS_ID) or (i = SETUP_STATS_PASS) then
                      MSI_SetupVars[i] := intro_Edits[j].Text
                    else
                      MSI_SetupVars[i] := StrToInt(intro_Edits[j].Text);

                    //Writeln('SetupVar['+IntToStr(i)+'] := '+ToStr(MSI_SetupVars[i]));
                  end else
                    intro_Edits[j].Text := ReadINI('SETTINGS', s, PATH_SETTINGS);

            end;
        end;
    end;

    (*
       SCRIPT SETUP COMPONENTS & OTHER
       ===============================

       Written by: Coh3n
    *)


    (**
     * Used to for TScriptSetup for each player
     *)

    const
      LIST_COUNT = 6;
        LIST_ROCKS     = 0;
        LIST_TREES     = 1;
        LIST_FISHSPOTS = 2;
        LIST_SPELLS    = 3;
        LIST_STAFFS    = 4;
        LIST_DROP      = 5;

      EDIT_COUNT = 6;
        EDIT_LOADS      = 0;
        EDIT_TIME       = 1;
        EDIT_LEVEL      = 2;
        EDIT_EXCEPTIONS = 3;
        EDIT_ALCH_SLOTS = 4;
        EDIT_PRIORITY   = 5;

    var
      script_ListTexts, script_EditTexts: TStringArray;
      script_Lists: array[0..LIST_COUNT - 1] of TCheckListBox;
      script_ListLabels: array[0..LIST_COUNT - 1] of TLabel;
      script_Edits: array[0..EDIT_COUNT - 1] of TEdit;
      script_EditLabels: array[0..EDIT_COUNT - 1] of TLabel;
      script_StaffType: TComboBox;

    procedure script_CreateComponents(PanelIndex: Integer);
    var
      i, j: Integer;
    begin
      // TCheckListBoxes
      for i := 0 to High(script_Lists) do
      begin
        script_Lists[i] := TCheckListBox.Create(Panels[PanelIndex]);
        with script_Lists[i] do
        begin
          Parent := Panels[PanelIndex];
          Width := 140;
          Height := 80;
          Left := 20;
          Top := 75;
          Visible := False;

          case i of
            LIST_ROCKS:
              begin
              end;

            LIST_TREES:
              begin
              end;

            LIST_FISHSPOTS:
              begin
              end;

            LIST_SPELLS:
              begin
              end;

            LIST_STAFFS:
              begin
                Left := 20 + Width + 15;
              end;

            LIST_DROP:
              begin
                Left := 20 + Width + 15;

                for i := 0 to High(MSI_Items) do
                begin
                  if (MSI_Items[i].Name = '') then
                    Continue;

                  Items.Append(Capitalize(MSI_Items[i].Name));
                end;
              end;
          end;
        end;
      end;

      // TLabels
      script_ListTexts := ['Rocks', 'Trees', 'Fishing Spots', 'Spells', 'Staffs', 'Don''t Drop/Bank'];
      for i := 0 to High(script_ListLabels) do
      begin
        script_ListLabels[i] := TLabel.Create(Panels[PanelIndex]);
        with script_ListLabels[i] do
        begin
          Parent := Panels[PanelIndex];
          Height := 25;
          Width := script_Lists[i].Width;
          Left := script_Lists[i].Left;
          Top := script_Lists[i].Top - (Height - 5);
          Caption := script_ListTexts[i];
          Font.Color := 2070783;
          Visible := script_Lists[i].Visible;
        end;
      end;

      // TEdits
      for i := 0 to High(script_Edits) do
      begin
        script_Edits[i] := TEdit.Create(Panels[PanelIndex]);
        with script_Edits[i] do
        begin
          Parent := Panels[PanelIndex];
          Height := 20;
          Visible := False;

          case i of
            EDIT_LOADS, EDIT_TIME, EDIT_LEVEL:
              begin
                Width := 40;
                Left := (script_Lists[0].Left + script_Lists[0].Width - (Width + 40));
                Top := (script_Lists[0].Top + script_Lists[0].Height + 20) + ((15 + Height) * i);
                Text := '0';
                Enabled := False;
              end;

            EDIT_EXCEPTIONS, EDIT_ALCH_SLOTS, EDIT_PRIORITY:
              begin
                Width := 80;
                Left := script_Lists[LIST_DROP].Left + (Width - 40);
                Top := (script_Lists[0].Top + script_Lists[0].Height + 20) + ((15 + Height) * (i - 3));
              end;
          end;
        end;
      end;

      // Edit TLabels
      script_EditTexts := ['Loads', 'Time', 'Level', 'Exceptions', 'Alching Slots', 'Priority'];
      for i := 0 to High(script_EditLabels) do
      begin
        script_EditLabels[i] := TLabel.Create(Panels[PanelIndex]);
        with script_EditLabels[i] do
        begin
          Parent := Panels[PanelIndex];
          Height := 25;
          Width := (script_Edits[i].Width);
          Left := script_Edits[i].Left - Width;
          Top := (script_Edits[i].Top + 4);
          Caption := script_EditTexts[i];
          Font.Color := 2070783;
          Visible := script_Edits[i].Visible;
        end;
      end;
    end;

    procedure script_HideComponents();
    var
      i: Integer;
    begin
      for i := 0 to High(script_Lists) do
        script_Lists[i].Visible := False;

      for i := 0 to High(script_Edits) do
        script_Edits[i].Visible := False;

      for i := 0 to High(script_ListLabels) do
        script_ListLabels[i].Visible := False;

      for i := 0 to High(script_EditLabels) do
        script_EditLabels[i].Visible := False;
    end;

    procedure script_ShowComponents();
    var
      i, j, k: Integer;
      default, lists, edits: TIntegerArray;
      mode, index: Integer;
    begin
      script_HideComponents();

      for i := 0 to High(MSI_Scripts) do
        if (MSI_Scripts[i].Name = comboBox_Script_6.Text) then
        begin
          case MSI_Scripts[i].SkillConst of
            SKILL_WOODCUTTING, SKILL_MINING, SKILL_FISHING:
              begin
                case MSI_Scripts[i].SkillConst of
                  SKILL_WOODCUTTING:
                    begin
                      lists :=[LIST_TREES, LIST_DROP];
                      default := MSI_Scripts[i].Defaults.Trees;
                    end;

                  SKILL_MINING:
                    begin
                      lists :=[LIST_ROCKS, LIST_DROP];
                      default := MSI_Scripts[i].Defaults.Rocks;
                    end;

                  SKILL_FISHING:
                    begin
                      lists :=[LIST_FISHSPOTS, LIST_DROP];
                      default := MSI_Scripts[i].Defaults.FishSpots;
                    end;
                end;

                // Lists and edits for Woodcutting, Mining and Woodcutting
                edits := [EDIT_LOADS, EDIT_TIME, EDIT_EXCEPTIONS, EDIT_PRIORITY, EDIT_LEVEL];

                script_Lists[lists[0]].CLEAR;

                // Add the default objects to the TCheckListBox
                for j := 0 to High(default) do
                  for k := 0 to High(MSI_Objects) do
                    if (default[j] = k) then
                      script_Lists[lists[0]].Items.Append(Capitalize(MSI_Objects[k].Name));

                // Make lists visible
                for j := 0 to High(lists) do
                begin
                  script_Lists[lists[j]].Visible := True;
                  script_ListLabels[lists[j]].Visible := True;
                end;

                // Make edit boxes visible
                for j := 0 to High(edits) do
                begin
                  script_Edits[edits[j]].Visible := True;
                  script_EditLabels[edits[j]].Visible := True;
                end;
              end;

            SKILL_MAGIC:
              begin
                // Sets up spells if not already done so
                if (not SpellSetup) then
                  SetupSpells;

                script_Lists[LIST_SPELLS].CLEAR;
                script_Lists[LIST_STAFFS].CLEAR;

                // Adds all the spells to the Spells list
                for j := 0 to High(MSI_Scripts[i].Defaults.Spells) do
                begin
                  mode := MSI_GetSpellMode(MSI_Scripts[i].Defaults.Spells[j], index);
                  script_Lists[LIST_SPELLS].Items.Append(Capitalize(SpellModes[mode][index].Name));
                end;

                // Adds all the staffs to the Staff list
                for j := 0 to High(MSI_Items) do
                  if (Pos('staff', Lowercase(MSI_Items[j].Name)) > 0) then
                    script_Lists[LIST_STAFFS].Items.Append(Capitalize(MSI_Items[j].Name));

                // Makes all the required components visible
                script_Lists[LIST_SPELLS].Visible := True;
                script_Lists[LIST_STAFFS].Visible := True;
                script_ListLabels[LIST_SPELLS].Visible := True;
                script_ListLabels[LIST_STAFFS].Visible := True;
                script_Edits[EDIT_TIME].Visible := True;
                script_EditLabels[EDIT_TIME].Visible := True;
                script_EditLabels[EDIT_ALCH_SLOTS].Visible := True;
                script_Edits[EDIT_ALCH_SLOTS].Visible := True;
              end;
          end;
        end;
    end;

    procedure script_FillComponents(pIndex: Integer); // OnChange
    var
      i, j, k, lIndex, sIndex, skill, mode, index: Integer;
      objects: TIntegerArray;
    begin
      for i := 0 to High(MSI_Scripts) do
        if (comboBox_Script_6.Text = MSI_Scripts[i].Name) then
        begin
          sIndex := comboBox_Script_6.ITEMS.IndexOf(comboBox_Script_6.Text);
          skill := MSI_Scripts[i].SkillConst;
          //Writeln('Skill: '+MSI_Scripts[i].SkillName);
          Break;
        end;

      //Writeln('Script Index: '+IntToStr(sIndex));

      case skill of
        SKILL_WOODCUTTING, SKILL_MINING, SKILL_FISHING:
          begin
            case skill of
              SKILL_WOODCUTTING:
                begin
                  lIndex := LIST_TREES;
                  objects := MSI_Players[pIndex].Scripts[sIndex].Trees;
                end;

              SKILL_MINING:
                begin
                  lIndex := LIST_ROCKS;
                  objects := MSI_Players[pIndex].Scripts[sIndex].Rocks;
                end;

              SKILL_FISHING:
                begin
                  lIndex := LIST_FISHSPOTS;
                  objects := MSI_Players[pIndex].Scripts[sIndex].FishSpots;
                end;
            end;

            // Check off the objects in the list
            //Writeln(ToStr(objects));
            for i := 0 to High(objects) do
              for j := 0 to (script_Lists[lIndex].Items.Count - 1) do
                if (Lowercase(script_Lists[lIndex].Items.Strings[j]) = Lowercase(MSI_Objects[objects[i]].Name)) then
                  script_Lists[lIndex].Checked[j] := True;

            // Check off all the dont drop items
            for i := 0 to High(MSI_Players[pIndex].Scripts[sIndex].DontDrop) do
              for j := 0 to (script_Lists[LIST_DROP].Items.Count - 1) do
                if (Lowercase(script_Lists[LIST_DROP].Items.Strings[j]) = Lowercase(MSI_Items[MSI_Players[pIndex].Scripts[sIndex].DontDrop[i]].Name)) then
                  script_Lists[LIST_DROP].Checked[j] := True;

            with MSI_Players[pIndex].Scripts[sIndex] do
            begin
              script_Edits[EDIT_LOADS].Text := IntToStr(Loads);
              script_Edits[EDIT_LEVEL].Text := IntToStr(MaxLevel);
              script_Edits[EDIT_PRIORITY].Text := IntArrToStr(Priority);
              script_Edits[EDIT_EXCEPTIONS].Text := IntArrToStr(Exceptions);
            end;
          end;

        SKILL_MAGIC:
          begin
            if (not SpellSetup) then
              SetupSpells;

            with MSI_Players[pIndex].Scripts[sIndex] do
            begin
              // Check off all the spells
              for i := 0 to High(Spells) do
              begin
                mode := MSI_GetSpellMode(Spells[i], index);

                for j := 0 to (script_Lists[LIST_SPELLS].ITEMS.Count - 1) do
                  if (Lowercase(SpellModes[mode][index].Name) = Lowercase(script_Lists[LIST_SPELLS].ITEMS.Strings[j])) then
                    script_Lists[LIST_SPELLS].Checked[j] := True;
              end;

              // Check off all the staffs
              for i := 0 to High(Staffs) do
                for j := 0 to (script_Lists[LIST_STAFFS].ITEMS.Count - 1) do
                  if (Lowercase(MSI_Items[Staffs[i]].Name) = Lowercase(script_Lists[LIST_STAFFS].ITEMS.Strings[j])) then
                    script_Lists[LIST_STAFFS].Checked[j] := True;

              // Fill the AlchSlots edit
              script_Edits[EDIT_ALCH_SLOTS].Text := IntArrToStr(MSI_Players[pIndex].Scripts[sIndex].AlchSlots);
            end;
          end;
      end;

      // Time is common for every script
      with MSI_Players[pIndex].Scripts[sIndex] do
        script_Edits[EDIT_TIME].Text := IntToStr(Time);

      //Writeln('Filled Script Setup Components');
    end;

    procedure script_FillCombo();
    var
      i, pIndex: Integer;
    begin
      comboBox_Script_6.CLEAR;

      pIndex := GetPlayerIndex(ChoosePlay[IMG_TAB_NORM_5].Text);

      with MSI_Players[pIndex] do
        for i := 0 to High(Scripts) do
          comboBox_Script_6.Items.Append(MSI_Scripts[Scripts[i].Name].Name);
    end;

    (**
     * Currently sets:
     *
     *)

    procedure script_SetInfo();
    var
      i, j, skill, sIndex, pIndex, lIndex: Integer;
      objects: TIntegerArray;
    begin
      if (comboBox_Script_6.Text = '') then
        Exit;

      for i := 0 to High(MSI_Scripts) do
        if (comboBox_Script_6.Text = MSI_Scripts[i].Name) then
        begin
          sIndex := comboBox_Script_6.ITEMS.IndexOf(comboBox_Script_6.Text);
          //Writeln('Script Index: '+IntToStr(sIndex));
          skill := MSI_Scripts[i].SkillConst;
          Break;
        end;

      pIndex := GetPlayerIndex(ChoosePlay[IMG_TAB_NORM_5].Text);
      //Writeln('Player Index: '+IntToStr(pIndex));

      case skill of
        SKILL_WOODCUTTING, SKILL_MINING, SKILL_FISHING:
          begin
            case skill of
              SKILL_WOODCUTTING:
                lIndex := LIST_TREES;

              SKILL_MINING:
                lIndex := LIST_ROCKS;

              SKILL_FISHING:
                lIndex := LIST_FISHSPOTS;
            end;

            // Set the Trees, Rocks, and FishSpots depending on the skill
            for i := 0 to script_Lists[lIndex].ITEMS.Count - 1 do
              if (script_Lists[lIndex].Checked[i]) then
                for j := 0 to High(MSI_Objects) do
                  if (Lowercase(MSI_Objects[j].Name) = Lowercase(script_Lists[lIndex].Items.Strings[i])) then
                  begin
                    case skill of
                      SKILL_WOODCUTTING:
                        with MSI_Players[pIndex].Scripts[sIndex] do
                        begin
                          SetLength(Trees, Length(Trees) + 1);
                          Trees[High(Trees)] := j;
                          ClearSameIntegers(Trees);
                          //Writeln('Player '+IntToStr(pIndex)+' Trees: '+ToStr(Trees));
                        end;

                      SKILL_MINING:
                        with MSI_Players[pIndex].Scripts[sIndex] do
                        begin
                          SetLength(Rocks, Length(Rocks) + 1);
                          Rocks[High(Rocks)] := j;
                          ClearSameIntegers(Rocks);
                          //Writeln('Player '+IntToStr(pIndex)+' Rocks: '+ToStr(Rocks));
                        end;

                      SKILL_FISHING:
                        with MSI_Players[pIndex].Scripts[sIndex] do
                        begin
                          SetLength(FishSpots, Length(FishSpots) + 1);
                          FishSpots[High(FishSpots)] := j;
                          ClearSameIntegers(FishSpots);
                          //Writeln('Player '+IntToStr(pIndex)+' FishSpots: '+ToStr(FishSpots));
                        end;
                    end;
                  end;

            // Set the items to exclude from dropping/banking
            for i := 0 to (script_Lists[LIST_DROP].ITEMS.Count - 1) do
              if (script_Lists[LIST_DROP].Checked[i]) then
                for j := 0 to High(MSI_Items) do
                  if (Lowercase(script_Lists[LIST_DROP].Items.Strings[i]) = Lowercase(MSI_Items[j].Name)) then
                    with MSI_Players[pIndex].Scripts[sIndex] do
                    begin
                      SetLength(DontDrop, Length(DontDrop) + 1);
                      DontDrop[High(DontDrop)] := j;
                      ClearSameIntegers(DontDrop);
                    end;

            // Set the other script information
            with MSI_Players[pIndex].Scripts[sIndex] do
            begin
              try
                MaxLevel := StrToInt(script_Edits[EDIT_LEVEL].Text);
              except
                ShowMessage('Invalid max level! Please enter a number.');
              end;

              try
                Loads := StrToInt(script_Edits[EDIT_LOADS].Text);
              except
                ShowMessage('Invalid loads! Please enter a number.');
              end;

              try
                Time := StrToInt(script_Edits[EDIT_LOADS].Text);
              except
                ShowMessage('Invalid AnimTimer! Please enter a number.');
              end;

              try
                Exceptions := StrToIntArr(script_Edits[EDIT_EXCEPTIONS].Text);
                ClearSameIntegers(Exceptions);
              except
                ShowMessage('Invalid exceptions input!');
              end;

              try
                Priority := StrToIntArr(script_Edits[EDIT_PRIORITY].Text);
                ClearSameIntegers(Priority);
              except
                ShowMessage('Invalid priority input!');
              end;
            end;
          end;

        SKILL_MAGIC:
          begin
            if (not SpellSetup) then
              SetupSpells;

            // Set the Spells
            for i := 0 to script_Lists[LIST_SPELLS].ITEMS.Count - 1 do
              if (script_Lists[LIST_SPELLS].Checked[i]) then
                with MSI_Players[pIndex].Scripts[sIndex] do
                begin
                  SetLength(Spells, Length(Spells) + 1);
                  Spells[High(Spells)] := MSI_StrToSpell(script_Lists[LIST_SPELLS].ITEMS.Strings[i]);
                  ClearSameIntegers(Spells);
                  //Writeln('Player '+IntToStr(pIndex)+' Spells: '+ToStr(Spells));
                end;

            // Set the staffs
            for i := 0 to script_Lists[LIST_STAFFS].ITEMS.Count - 1 do
              if (script_Lists[LIST_STAFFS].Checked[i]) then
                for j := 0 to High(MSI_Items) do
                  if (Lowercase(MSI_Items[j].Name) = Lowercase(script_Lists[LIST_STAFFS].ITEMS.Strings[i])) then
                    with MSI_Players[pIndex].Scripts[sIndex] do
                    begin
                      SetLength(Staffs, Length(Staffs) + 1);
                      Staffs[High(Staffs)] := j;
                      ClearSameIntegers(Staffs);
                      //Writeln('Player '+IntToStr(pIndex)+' Staffs: '+ToStr(Staffs));
                    end;

            // Set the Alching Slots
            MSI_Players[pIndex].Scripts[sIndex].AlchSlots := StrToIntArr(script_Edits[EDIT_ALCH_SLOTS].Text);
          end;
      end;

      with MSI_Players[pIndex].Scripts[sIndex] do
        try
          Time := StrToInt(script_Edits[EDIT_TIME].Text);
        except
          ShowMessage('Invalid AnimTimer! Please enter a number.');
        end;
    end;

    (*
       END OF SCRIPT SETUP COMPONENTS
       ==============================
    *)


    procedure CheckOffScripts(PlayerIndex: Integer);
    var
      j, k: Integer;
    begin
      for j := 0 to High(MSI_Players[PlayerIndex].Scripts) do
        for k := 0 to (CheckListBox_3.Items.Count - 1) do
          if (Lowercase(MSI_Scripts[MSI_Players[PlayerIndex].Scripts[j].Name].Name) = Lowercase(CheckListBox_3.Items.Strings[k])) then
            CheckListBox_3.Checked[k] := True;
    end;

    procedure CheckOffLocs(PlayerIndex: Integer);
    var
      j, k: Integer;
    begin
      with MSI_Players[PlayerIndex] do
        for k := 0 to (CheckListBox_4.Items.Count - 1) do
          if (Lowercase(MSI_Locations[Location].Name) = Lowercase(CheckListBox_4.Items.Strings[k])) then
          begin
            CheckListBox_4.Checked[k] := True;
            Break;
          end;
    end;

    procedure LoadOther(pIndex: Integer);
    begin
      time_Total_5.Text := IntToStr(MSI_Players[pIndex].TotalTime);
      time_Break_5.Text := IntToStr(MSI_Players[pIndex].BreakTime);
      loads_Break_5.Text := IntToStr(MSI_Players[pIndex].BreakLoads);
      loads_Total_5.Text := IntToStr(MSI_Players[pIndex].TotalLoads);

      time_Total_5.Enabled := True;
      time_Break_5.Enabled := True;
      loads_Break_5.Enabled := True;
      loads_Total_5.Enabled := True;
    end;

    procedure LoadPlayersToPanels(s: string);
    var
      i, j, k, pIndex: Integer;
    begin
      s := Capitalize(s);

      for i := IMG_TAB_NORM_2 to IMG_TAB_NORM_5 do
      ChoosePlay[i].Items.Append(s);
    end;

    function SetScriptConsts(): TIntegerArray;
    var
      i, j: Integer;
    begin
      for i := 0 to (CheckListBox_3.Items.Count - 1) do
        if (CheckListBox_3.Checked[i]) then
          for j := 0 to High(MSI_Scripts) do
          begin
            if (MSI_Scripts[j].Name = '') then
              Continue;

            if (Lowercase(CheckListBox_3.Items.Strings[i]) = Lowercase(MSI_Scripts[j].Name)) then
            begin
              SetLength(Result, Length(Result) + 1);
              Result[High(Result)] := MSI_Scripts[j].Constant;
            end;
          end;

      for i := 0 to High(MSI_Players) do
        if (Lowercase(ChoosePlay[IMG_TAB_NORM_2].Text) = Lowercase(MSI_Players[i].Name)) then
        begin
          SetLength(MSI_Players[i].Scripts, Length(Result));

          for j := 0 to High(MSI_Players[i].Scripts) do
          begin
            MSI_Players[i].Scripts[j].Name := Result[j];
            //Writeln(IntToStr(MSI_Players[i].Scripts[j].Name));
          end;

          Break;
        end;

      //Writeln('Scripts: ' + ToStr(Result));
    end;

    function SetLocConsts(): Integer;
    var
      i, j: Integer;
    begin
      for i := 0 to (CheckListBox_4.Items.Count - 1) do
        if (CheckListBox_4.Checked[i]) then
          for j := 0 to High(MSI_Locations) do
          begin
            if (MSI_Locations[j].Name = '') then
              Continue;

            if (Lowercase(ChoosePlay[IMG_TAB_NORM_3].Items.Strings[i]) = Lowercase(MSI_Locations[j].Name)) then
            begin
              Result := MSI_Locations[j].Constant;
              Break;
            end;
          end;

      for i := 0 to High(MSI_Players) do
        if (Lowercase(ChoosePlay[IMG_TAB_NORM_3].Text) = Lowercase(MSI_Players[i].Name)) then
        begin
          MSI_Players[i].Location := Result;
          //Writeln('Location: ' + ToStr(MSI_Players[i].Location));
          Break;
        end;

    end;

    procedure SetOther();
    var
      i: Integer;
    begin
      for i := 0 to High(MSI_Players) do
        if (Lowercase(ChoosePlay[IMG_TAB_NORM_4].Text) = Lowercase(MSI_Players[i].Name)) then
          with MSI_Players[i] do
          begin
            try
              TotalTime := StrToInt(time_Total_5.Text);
            except
              ShowMessage('Total AnimTimer must be a number!');
              Exit;
            end;

            try
              BreakTime := StrToInt(time_Break_5.Text);
            except
              ShowMessage('Break after (AnimTimer) must be a number!');
              Exit;
            end;

            try
              BreakLoads := StrToInt(loads_Break_5.Text);
            except
              ShowMessage('Break after (loads) must be a number!');
              Exit;
            end;

            try
              TotalLoads := StrToInt(loads_Total_5.Text);
            except
              ShowMessage('Total loads must be a number!');
              Exit;
            end;

            Break;
          end;

      //Writeln('Others set!');
    end;

    procedure SavePlayers();
    var
      i, j, k: Integer;
      s: string;
    begin
      intro_Settings(True);

      WriteINI('Number of Players', 'NumberOfPlayers', IntToStr(Length(MSI_Players)), PATH_PLAYER);

      for i := 0 to High(MSI_Players) do
        with MSI_Players[i] do
        begin
          s := '';
          Active := checkList_Players.Checked[i];
          SetLocConsts;
          script_SetInfo;

          WriteINI(IntToStr(i), 'Name', Name, PATH_PLAYER);
          WriteINI(IntToStr(i), 'Pass', Pass, PATH_PLAYER);
          WriteINI(IntToStr(i), 'Nick', Nick, PATH_PLAYER);
          WriteINI(IntToStr(i), 'Pin', Pin, PATH_PLAYER);
          WriteINI(IntToStr(i), 'Active', BoolToStr(Active), PATH_PLAYER);
          WriteINI(IntToStr(i), 'Member', BoolToStr(Member), PATH_PLAYER);
          WriteINI(IntToStr(i), 'Location', IntToStr(Location), PATH_PLAYER);
          WriteINI(IntToStr(i), 'BreakTime', IntToStr(BreakTime), PATH_PLAYER);
          WriteINI(IntToStr(i), 'BreakLoads', IntToStr(BreakLoads), PATH_PLAYER);
          WriteINI(IntToStr(i), 'TotalTime', IntToStr(TotalTime), PATH_PLAYER);
          WriteINI(IntToStr(i), 'TotalLoads', IntToStr(TotalLoads), PATH_PLAYER);

          WriteINI(IntToStr(i), 'NumberOfScripts', IntToStr(Length(Scripts)), PATH_PLAYER);
          for j := 0 to High(Scripts) do
          begin
            // Set for all skills
            WriteINI(IntToStr(i), 'Script'+IntToStr(j)+'.Name', IntToStr(Scripts[j].Name), PATH_PLAYER);
            WriteINI(IntToStr(i), 'Script'+IntToStr(j)+'.Time', IntToStr(Scripts[j].Time), PATH_PLAYER);

            case MSI_Scripts[Scripts[j].Name].SkillConst of
              SKILL_WOODCUTTING, SKILL_FISHING, SKILL_MINING:
                begin
                  // DontDrop
                  if (Length(Scripts[j].DontDrop) > 0) then
                    WriteINI(IntToStr(i), 'Script'+IntToStr(j)+'.DontDrop', IntArrToStr(Scripts[j].DontDrop), PATH_PLAYER);

                  // Exceoptions
                  if (Length(Scripts[j].Exceptions) > 0) then
                    WriteINI(IntToStr(i), 'Script'+IntToStr(j)+'.Exceptions', IntArrToStr(Scripts[j].Exceptions), PATH_PLAYER);

                  // Priority
                  if (Length(Scripts[j].Priority) > 0) then
                    WriteINI(IntToStr(i), 'Script'+IntToStr(j)+'.Priority', IntArrToStr(Scripts[j].Priority), PATH_PLAYER);

                  // Level and Loads
                  WriteINI(IntToStr(i), 'Script'+IntToStr(j)+'.MaxLevel', IntToStr(Scripts[j].MaxLevel), PATH_PLAYER);
                  WriteINI(IntToStr(i), 'Script'+IntToStr(j)+'.Loads', IntToStr(Scripts[j].Loads), PATH_PLAYER);

                  // Trees, Rocks, and FishSpots
                  case MSI_Scripts[Scripts[j].Name].SkillConst of
                    SKILL_WOODCUTTING:
                      WriteINI(IntToStr(i), 'Script'+IntToStr(j)+'.Trees', IntArrToStr(Scripts[j].Trees), PATH_PLAYER);

                    SKILL_MINING:
                      WriteINI(IntToStr(i), 'Script'+IntToStr(j)+'.Rocks', IntArrToStr(Scripts[j].Rocks), PATH_PLAYER);

                    SKILL_FISHING:
                      WriteINI(IntToStr(i), 'Script'+IntToStr(j)+'.FishSpots', IntArrToStr(Scripts[j].FishSpots), PATH_PLAYER);
                  end;
                end;

              SKILL_MAGIC:
                begin
                  // Staffs
                  if (Length(Scripts[j].Staffs) > 0) then
                    WriteINI(IntToStr(i), 'Script'+IntToStr(j)+'.Staffs', IntArrToStr(Scripts[j].Staffs), PATH_PLAYER);

                  // Spells
                  if (Length(Scripts[j].Spells) > 0) then
                    WriteINI(IntToStr(i), 'Script'+IntToStr(j)+'.Spells', IntArrToStr(Scripts[j].Spells), PATH_PLAYER);

                  // AlchSlots
                  if (Length(Scripts[j].AlchSlots) > 0) then
                    WriteINI(IntToStr(i), 'Script'+IntToStr(j)+'.AlchSlots', IntArrToStr(Scripts[j].AlchSlots), PATH_PLAYER);
                end;
            end;
          end;
        end;

      ShowMessage('Saved Players!');
    end;

    procedure LoadPlayers();
    var
      i, j: Integer;
      nPlayers, s, p: string;
    begin
      if (not FileExists(PATH_PLAYER)) then
      begin
        ShowMessage('Players need to be saved before they can be loaded!');
        Exit;
      end;

      nPlayers := ReadINI('Number of Players', 'NumberOfPlayers', PATH_PLAYER);
      SetLength(MSI_Players, StrToInt(nPlayers));

      for i := 0 to High(MSI_Players) do
        with MSI_Players[i] do
        begin
          Name := ReadINI(IntToStr(i), 'Name', PATH_PLAYER);
          Pass := ReadINI(IntToStr(i), 'Pass', PATH_PLAYER);
          Nick := ReadINI(IntToStr(i), 'Nick', PATH_PLAYER);
          Pin := ReadINI(IntToStr(i), 'Pin', PATH_PLAYER);
          Active := StrToBool(ReadINI(IntToStr(i), 'Active', PATH_PLAYER));
          Member := StrToBool(ReadINI(IntToStr(i), 'Member', PATH_PLAYER));
          Location := StrToInt(ReadINI(IntToStr(i), 'Location', PATH_PLAYER));
          BreakTime := StrToInt(ReadINI(IntToStr(i), 'BreakTime', PATH_PLAYER));
          BreakLoads := StrToInt(ReadINI(IntToStr(i), 'BreakLoads', PATH_PLAYER));
          TotalTime := StrToInt(ReadINI(IntToStr(i), 'TotalTime', PATH_PLAYER));
          TotalLoads := StrToInt(ReadINI(IntToStr(i), 'TotalLoads', PATH_PLAYER));

          if (Member) then
          begin
            comboBox_Member.Text := 'True';
            s := '[P2P] '
          end else begin
            comboBox_Member.Text := 'False';
            s := '[F2P] ';
          end;

          if (Pin <> '') then
            p := 'Pin';

          checkList_Players.Items.Append(s + Capitalize(Name) + ' (' + Pass + ')' + p + Pin);
          checkList_Players.Checked[i] := Active;

          LoadPlayersToPanels(Name);

          SetLength(Scripts, StrToInt(ReadINI(IntToStr(i), 'NumberOfScripts', PATH_PLAYER)));
          for j := 0 to High(Scripts) do
          begin
            Scripts[j].Name := StrToInt(ReadINI(IntToStr(i), 'Script'+IntToStr(j)+'.Name', PATH_PLAYER));
            Scripts[j].Time := StrToInt(ReadINI(IntToStr(i), 'Script'+IntToStr(j)+'.Time', PATH_PLAYER));

            try
              Scripts[j].Trees := StrToIntArr(ReadINI(IntToStr(i), 'Script'+IntToStr(j)+'.Trees', PATH_PLAYER));
              Scripts[j].Rocks := StrToIntArr(ReadINI(IntToStr(i), 'Script'+IntToStr(j)+'.Rocks', PATH_PLAYER));
              Scripts[j].FishSpots := StrToIntArr(ReadINI(IntToStr(i), 'Script'+IntToStr(j)+'.FishSpots', PATH_PLAYER));
              Scripts[j].Spells := StrToIntArr(ReadINI(IntToStr(i), 'Script'+IntToStr(j)+'.Spells', PATH_PLAYER));
              Scripts[j].DontDrop := StrToIntArr(ReadINI(IntToStr(i), 'Script'+IntToStr(j)+'.DontDrop', PATH_PLAYER));
              Scripts[j].Exceptions := StrToIntArr(ReadINI(IntToStr(i), 'Script'+IntToStr(j)+'.Exceptions', PATH_PLAYER));
              Scripts[j].Priority := StrToIntArr(ReadINI(IntToStr(i), 'Script'+IntToStr(j)+'.Priority', PATH_PLAYER));
              Scripts[j].AlchSlots := StrToIntArr(ReadINI(IntToStr(i), 'Script'+IntToStr(j)+'.AlchSlots', PATH_PLAYER));
              Scripts[j].Loads := StrToInt(ReadINI(IntToStr(i), 'Script'+IntToStr(j)+'.Loads', PATH_PLAYER));
              Scripts[j].MaxLevel := StrToInt(ReadINI(IntToStr(i), 'Script'+IntToStr(j)+'.MaxLevel', PATH_PLAYER));
            except
              //Writeln('INI Doesn''t Exist!');
            end;
          end;
        end;

      tImages[IMG_LOAD_TAB_NORM].Enabled := False;
      btn_DeletePlayer.Enabled := (Length(MSI_Players) > 1);
      ShowMessage('Loaded Players!');
    end;

    procedure OnMouseMove(Sender: TObject; Shift: TShiftState; x, y: Integer);
    var
      x1, y1, hi, i, j, bmp, xdif, ydif, h: Integer;
      BoundL, BoundT: Extended;
      imgSwap, bmpArr, imgArr: Array of Integer;
    begin
      bmpArr := [ X_NORM, Q_NORM, LOAD_TAB_NORM,
                  SAVE_TAB_NORM, TAB_NORM_1, TAB_NORM_2,
                  TAB_NORM_3, TAB_NORM_4, TAB_NORM_5, TAB_NORM_0, RUN_NORM ];

      imgArr := [ IMG_X_NORM, IMG_Q_NORM, IMG_LOAD_TAB_NORM,
                  IMG_SAVE_TAB_NORM, IMG_TAB_NORM_1, IMG_TAB_NORM_2,
                  IMG_TAB_NORM_3, IMG_TAB_NORM_4, IMG_TAB_NORM_5, IMG_TAB_NORM_0, IMG_RUN_NORM ];

      hi := High(bmpArr);
      case Sender of
        tImages[IMG_BGND], Panels[IMG_TAB_NORM_1],
        Panels[IMG_TAB_NORM_2], Panels[IMG_TAB_NORM_3], Panels[IMG_TAB_NORM_4],
        Panels[IMG_TAB_NORM_5], Panels[IMG_TAB_NORM_0]:
          begin
            for i := 0 to hi do
            begin
              if (not isActiveImage[imgArr[i]]) then
                Continue;

              bmp := frmBitmaps[bmpArr[i]];
              DrawBitmap(bmp, tImages[imgArr[i]].Canvas, 0, 0);
              isActiveImage[imgArr[i]] := False;
            end;
          end;
      end;

      for h := 0 to hi do
        case Sender of
          tImages[imgArr[h]]:
            begin
              imgSwap := [imgArr[h], frmBitmaps[bmpArr[h] + 1]];
              if (not isActiveImage[imgSwap[0]]) then
              begin
                DrawBitmap(imgSwap[1],tImages[imgSwap[0]].Canvas,0,0);
                isActiveImage[imgSwap[0]] := True;
                for i := 0 to hi do
                begin
                  if (Sender = tImages[imgArr[i]]) then
                    Continue;

                  if (not isActiveImage[imgArr[i]]) then
                    Continue;

                  if (i = imgSwap[0] - 1) then
                    Continue;

                  bmp := frmBitmaps[bmpArr[i]];
                  DrawBitmap(bmp, tImages[imgArr[i]].Canvas, 0, 0);
                  isActiveImage[imgArr[i]] := False;
                end;
              end;
          end;
      end;
    end;

    const
      MAX_MOVE = 315;

    var
      accel, pMoved, senderTab, pan: integer;
      onLeft: Boolean;

    procedure OnTimerEnabled(Sender: TObject);
    var
      i, e, d, hi, lo: Integer;
    begin
      accel := accel + 2;
      pMoved := pMoved + accel;

      if (senderTab = IMG_TAB_NORM_0) then
      begin
        panels[IMG_TAB_NORM_0].Width := panels[IMG_TAB_NORM_0].Width + accel;

        for i := IMG_TAB_NORM_1 to IMG_TAB_NORM_5 do
        begin
          if (not isLeftTab[i]) then
            Continue;

          tImages[i].Left := tImages[i].Left + accel;

          if (pMoved >= MAX_MOVE) then
          begin
            isLeftTab[i] := False;
            AnimTimer.Enabled := False;
            tImages[i].Left := tImages[i].Left - 5;
          end;
        end;
      end else
      begin
        if (onLeft) then
          for i := senderTab to IMG_TAB_NORM_5 do
          begin
            if (i = senderTab) or (not isLeftTab[i]) then
              Continue;

            tImages[i].Left := tImages[i].Left + accel;

            if (pMoved >= MAX_MOVE) then
            begin
              isLeftTab[i] := False;
              AnimTimer.Enabled := False;
              tImages[i].Left := tImages[i].Left - 5;
            end;

            //Writeln(BoolToStr(isLeftTab[i]));
          end
        else begin
          panels[IMG_TAB_NORM_0].Width := panels[IMG_TAB_NORM_0].Width - accel;

          for i := senderTab downto IMG_TAB_NORM_1 do
          begin
            if (isLeftTab[i]) then
              Continue;

            tImages[i].Left := tImages[i].Left - accel;

            if (pMoved >= MAX_MOVE) then
            begin
              isLeftTab[i] := True;
              AnimTimer.Enabled := False;
              tImages[i].Left := tImages[i].Left + 5;
            end;

          end;
        end;
      end;

      for i := IMG_TAB_NORM_1 to IMG_TAB_NORM_5 do
      begin
        panels[i].left := tImages[i].left + tImages[i].width + 2
        if i <> IMG_TAB_NORM_5 then
          panels[i].width := tImages[i + 1].left - panels[i].left - 2
        else
          panels[i].width := MainForm.width - panels[i].left - 10;
      end;

      if (senderTab = IMG_TAB_NORM_0) then
        if (pMoved >= MAX_MOVE) then
          panels[IMG_TAB_NORM_0].Width := panels[IMG_TAB_NORM_0].Width - 10;
    end;

    procedure OnTabClick(Sender: TObject);
    var
      i: integer;
    begin
      if not AnimTimer.ENABLED then
      begin
        accel := 0;
        pMoved := 0;
        AnimTimer.enabled := true;
        pan := senderTab;

        if (Sender = tImages[IMG_TAB_NORM_0]) then
          senderTab := IMG_TAB_NORM_0;

        for i := IMG_TAB_NORM_1 to IMG_TAB_NORM_5 do
          if (Sender = tImages[i]) then
          begin
            senderTab := i;
            if (isLeftTab[senderTab]) then
              onLeft := True
            else
              onLeft := False;
          end;
      end;
    end;

    procedure OnClickEvents(Sender: TObject); // OnClick
    var
      i, j, t: integer;
      bmpArr, tScripts: TIntegerArray;
    begin
      for i := IMG_TAB_NORM_1 to IMG_TAB_NORM_5 do
        if (isLeftTab[i]) then
          Inc(t);

      for i := IMG_TAB_NORM_1 to IMG_TAB_NORM_5 do
        case Sender of
          tImages[i]:
            begin
              if (isLeftTab[i]) then
                if (t <= (i - (IMG_TAB_NORM_5 - IMG_TAB_NORM_1))) then
                  Exit;

              OnTabClick(Sender);

              if (not isLeftTab[i]) then
              begin
                bmpArr := [TAB_NORM_1, TAB_NORM_2, TAB_NORM_3, TAB_NORM_4, TAB_NORM_5];
                DrawBitmap(frmBitmaps[bmpArr[i-IMG_TAB_NORM_1]], tImages[i].Canvas, 0, 0);
              end;
            end;
        end;

      case Sender of
        tImages[IMG_X_NORM]:
          begin
            for i := 0 to BITMAP_COUNT - 1 do
              FreeBitmap(frmBitmaps[i]);

            MainForm.ModalResult := mrOk;
          end;

        tImages[IMG_Q_NORM]: OpenWebPage('http://villavu.com/forum/showthread.php?t=57723');

        tImages[IMG_TAB_NORM_0]:
          begin
            if (t <= 0) then
              Exit;

            OnTabClick(Sender);
          end;

        tImages[IMG_SAVE_TAB_NORM]:
          begin
            DrawBitmap(frmBitmaps[SAVE_TAB_NORM],tImages[IMG_SAVE_TAB_NORM].Canvas, 0, 0);
            SetScriptConsts;
            SetLocConsts;
            SetOther;
            SavePlayers;
          end;

        tImages[IMG_LOAD_TAB_NORM]:
          begin
            DrawBitmap(frmBitmaps[LOAD_TAB_NORM],tImages[IMG_LOAD_TAB_NORM].Canvas, 0, 0);
            LoadPlayers;
          end;

        tImages[IMG_RUN_NORM]:
          begin
            ScriptReady := True;

            intro_Settings(True);
            script_SetInfo();
            SetScriptConsts();
            SetLocConsts();
            SetOther();
            SavePlayers();

            MainForm.ModalResult := mrOk;
          end;
        comboBox_Script_6:
          script_SetInfo;
      end;
    end;

    {******************************************************************************}
    { Name: function GenerateNick(Username: string): string;                       }
    { By: Coh3n                                                                    }
    { Description: Generates the players nickname based on their username          }
    {******************************************************************************}
    function GenerateNick(Username: string): string;
    var
      i, j: Integer;
      s: TStringArray;
    begin
      s := Explode(' ', Username);
      for i := 0 to High(s) do
        if (Length(s[i]) >= 4) then
        begin
          for j := 2 to 4 do
            Result := Result + s[i][j];

          Break;
        end;

      //Writeln('Username: ' + Username);
      //Writeln('Nickname: ' + Result);
    end;

    {******************************************************************************}
    { Name: procedure AddPlayer();                                                 }
    { By: Coh3n                                                                    }
    { Description: Adds a player to the player array. Called when the Add Player   }
    {              button is pressed                                               }
    {******************************************************************************}
    procedure AddPlayer();
    var
      h: Integer;
    begin
      SetLength(MSI_Players, Length(MSI_Players) + 1);
      btn_DeletePlayer.Enabled := (Length(MSI_Players) > 1);

      h := High(MSI_Players);
      with MSI_Players[h] do
      begin
        Name   := edit_User.Text;
        Pass   := edit_Pass.Text;
        Nick   := GenerateNick(Name);
        Pin    := edit_Pin.Text;
        Active := checkList_Players.Checked[checkList_Players.ItemIndex];
        Member := StrToBool(comboBox_Member.Text);

        //Writeln(Name);
        //Writeln(Pass);
        //Writeln(Nick);
        //Writeln(Pin);
        //Writeln(BoolToStr(Active));
        //Writeln(BoolToStr(Member));
      end;

      //Writeln('Player Length: ' + IntToStr(Length(MSI_Players)));
    end;

    {******************************************************************************}
    { Name: procedure RemovePlayer();                                              }
    { By: Masterkill & Coh3n                                                       }
    { Description: Removes a player from the player array. Called when the Remove  }
    {              Player button is pressed                                        }
    {******************************************************************************}
    procedure RemovePlayer();
    var
      i: Integer;
    begin
      //Writeln(IntToStr(checkList_Players.ItemIndex));
      if (not (checkList_Players.ItemIndex = High(MSI_Players))) then
        if (checkList_Players.ItemIndex + 1 = High(MSI_Players)) then
          MSI_Players[checkList_Players.ItemIndex] := MSI_Players[High(MSI_Players)]
        else
          for i := checkList_Players.ItemIndex to High(MSI_Players) - 1 do
            MSI_Players[i] := MSI_Players[i + 1];

      btn_DeletePlayer.Enabled := (Length(MSI_Players) > 1);

      SetLength(MSI_Players, Length(MSI_Players) - 1);
      //Writeln('Player Length: ' + IntToStr(Length(MSI_Players)));
    end;

    procedure PanelOneClicks(Sender: TObject); // OnChange
    var
      sel, i: integer;
      s, p: string;
    begin
      case sender of
        btn_AddPlayer:
          begin
            if (StrToBool(comboBox_Member.Text)) then
              s := '[P2P] '
            else
              s := '[F2P] ';

            if (edit_Pin.Text <> '') then
              p := 'Pin';

            checkList_Players.Items.Append(s + Capitalize(edit_User.Text) + ' (' + edit_Pass.Text + ')' + p + edit_Pin.Text);

            // Add player to the combo box on other panels
            LoadPlayersToPanels(edit_User.Text);

            checkList_Players.Checked[checkList_Players.items.Count - 1] := true;
            checkList_Players.ItemIndex := checkList_Players.Items.Count - 1;

            AddPlayer();

            edit_User.Text := '';
            edit_Pass.Text := '';
            edit_Pin.Text := '';
         end;

        btn_DeletePlayer:
          begin
            if checkList_Players.ItemIndex >= 0 then
              sel := checkList_Players.ItemIndex;
            checkList_Players.Items.Delete(sel);
            for i := IMG_TAB_NORM_2 to IMG_TAB_NORM_5 do
              ChoosePlay[i].Items.Delete(sel);
            if sel = 0 then
              sel := 1;
            checkList_Players.ItemIndex := sel - 1;

            RemovePlayer();

            edit_User.Text := '';
            edit_Pass.Text := '';
            edit_Pin.Text := '';
          end;
      end;
    end;

    procedure PanelFiveClicks(Sender: TObject); // OnChange
    var
      pIndex, i: Integer;
    begin
      case sender of
        ComboBox_Script_6:
          begin
            script_ShowComponents();

            for i := 0 to script_Lists[LIST_DROP].ITEMS.Count - 1 do
              if (script_Lists[LIST_DROP].Checked[i]) then
                script_Lists[LIST_DROP].Checked[i] := False;

            pIndex := GetPlayerIndex(ChoosePlay[IMG_TAB_NORM_5].Text);
            script_FillComponents(pIndex);
          end;

        nScript:
          if ComboBox_Script_6.ITEMINDEX < ComboBox_Script_6.ITEMS.Count then
            ComboBox_Script_6.ItemIndex := ComboBox_Script_6.ItemIndex + 1;

        pScript:
          if ComboBox_Script_6.ITEMINDEX > 0 then
            ComboBox_Script_6.ItemIndex := ComboBox_Script_6.ItemIndex - 1;
      end;
    end;



    procedure PlayerControls(Sender: TObject);
    var i, pIndex: integer;
    begin
      for i := IMG_TAB_NORM_2 to IMG_TAB_NORM_5 do
        case sender of
          ChoosePlay[i]: pBoxIndex := ChoosePlay[i].ItemIndex;
          Previous[i]: if ChoosePlay[i].ItemIndex > 0 then
                         ChoosePlay[i].ItemIndex := ChoosePlay[i].ItemIndex - 1;
          Next[i]: if ChoosePlay[i].ItemIndex < ChoosePlay[i].Items.Count then
                     ChoosePlay[i].ItemIndex := ChoosePlay[i].ItemIndex + 1;
        end;
      case sender of
        ChoosePlay[IMG_TAB_NORM_2]: SetScriptConsts;
        ChoosePlay[IMG_TAB_NORM_3]: SetLocConsts;
        ChoosePlay[IMG_TAB_NORM_4]: SetOther();
        ChoosePlay[IMG_TAB_NORM_5]: script_SetInfo();
        Next[IMG_TAB_NORM_2]:
          if ChoosePlay[IMG_TAB_NORM_2].ItemIndex < ChoosePlay[IMG_TAB_NORM_2].Items.Count then
          begin
            pBoxIndex := ChoosePlay[IMG_TAB_NORM_2].ItemIndex;
            SetScriptConsts;
            pIndex := GetPlayerIndex(ChoosePlay[IMG_TAB_NORM_2].Items.Strings[pBoxIndex]);
            CheckOffScripts(pIndex);

            for i := 0 to CheckListBox_3.Items.Count - 1 do
              CheckListBox_3.Checked[i] := False;
          end;
      end;
    end;

    procedure PlayerCUpdate(Sender: TObject);
    var i, pIndex: integer;
    begin
    case sender of
        ChoosePlay[IMG_TAB_NORM_2]:
          begin
            for i := 0 to CheckListBox_3.ITEMS.Count - 1 do
              CheckListBox_3.Checked[i] := False;

            pIndex := GetPlayerIndex(ChoosePlay[IMG_TAB_NORM_2].Text);
            CheckOffScripts(pIndex);
            CheckListBox_3.Enabled := True;
          end;
        ChoosePlay[IMG_TAB_NORM_3]:
          begin
            for i := 0 to CheckListBox_4.ITEMS.Count - 1 do
              CheckListBox_4.Checked[i] := False;

            pIndex := GetPlayerIndex(ChoosePlay[IMG_TAB_NORM_3].Text);

            CheckOffLocs(pIndex);
            CheckListBox_4.Enabled := True;
          end;
        ChoosePlay[IMG_TAB_NORM_4]:
          begin
            pIndex := GetPlayerIndex(ChoosePlay[IMG_TAB_NORM_4].Text);
            LoadOther(pIndex);
          end;
        ChoosePlay[IMG_TAB_NORM_5]:
          begin
            SetScriptConsts();
            script_FillCombo();
            script_HideComponents();
          end;
          end;
    end;



    // Used to display a background image on the panels
    var
      bgndPanel: TImage;
      a, b: Integer;

    procedure InitForm;
    var
      i, pan: Integer;
      consts: TintegerArray;
      bmpArr: TStringArray;
      xy: TPointArray;
      visibl: array of boolean;
      wh: TPoint;
    begin
      bmpArr := ['BGND','X_NORM','X_HOVER','Q_NORM','Q_HOVER','LOAD_TAB_NORM','LOAD_TAB_HOVER','SAVE_TAB_NORM','SAVE_TAB_HOVER','TAB_NORM_1','TAB_HOVER_1','TAB_NORM_2','TAB_HOVER_2','TAB_NORM_3','TAB_HOVER_3','TAB_NORM_4','TAB_HOVER_4','TAB_NORM_5','TAB_HOVER_5','TAB_NORM_0','TAB_HOVER_0', 'BGND_PANEL', 'RUN_NORM', 'RUN_HOVER'];
      for i := 0 to High(frmBitmaps) do
        frmBitmaps[i] := LoadBitmap(ScriptPath + 'Bitmaps\' + bmpArr[i] + '.png');

      MainForm := TForm.Create(nil);
      MainForm.SetBounds({L} 100, {T} 100, {W} 600, {H} 400);
      MainForm.Position := poScreenCenter;
      MainForm.BorderStyle := bsNone;

      AnimTimer := TTimer.Create(MainForm);
      with AnimTimer do
      begin
        ONTIMER := @OnTimerEnabled;
        INTERVAL := 10;
        ENABLED := false;
      end;

      xy     := [Point(0, 0), Point(575, 7), Point(557, 7), Point(7, 69),   Point(81, 69),  Point(386, 100), Point(427, 100), Point(468, 100), Point(509, 100), Point(550, 100), Point(8, 222), Point(519, 69) ];
      SetArrayLength(visibl, GetArrayLength(xy));
      consts := [BGND,        X_NORM,        Q_NORM,        LOAD_TAB_NORM,  SAVE_TAB_NORM,  TAB_NORM_1,      TAB_NORM_2,      TAB_NORM_3,      TAB_NORM_4,      TAB_NORM_5,      TAB_NORM_0,    RUN_NORM       ];

      for i := 0 to IMG_COUNT - 1 do
      begin
        tImages[i] := TImage.Create(MainForm)
        with tImages[i] do
        begin
          Parent := MainForm;
          GetBitmapSize(frmBitmaps[consts[i]], wh.x, wh.y);
          SetBounds(xy[i].x, xy[i].y, wh.x, wh.y);
          OnMouseMove := @OnMouseMove;
          OnClick := @OnClickEvents;
          isActiveImage[i] := False;
        end;
        DrawBitmap(frmBitmaps[consts[i]], tImages[i].canvas, 0, 0);
      end;

      for i := low(panels) to high(panels) do
      begin
        panels[i] := TPanel.Create(MainForm);
        panels[i].parent := MainForm;
        GetBitmapSize(frmBitmaps[consts[i]], wh.x, wh.y);
        panels[i].SetBounds(xy[i].x + wh.x, xy[i].y, 0, wh.y);
        panels[i].BevelWidth := 0;

        if (i = High(panels)) then
          panels[i].SetBounds(10 + tImages[IMG_TAB_NORM_0].Width, 100,
                              tImages[IMG_TAB_NORM_1].Left - (tImages[IMG_TAB_NORM_0].Left + tImages[IMG_TAB_NORM_0].Width) - 4,
                              tImages[IMG_TAB_NORM_1].Height);

        bgndPanel := TImage.Create(panels[i]);
        bgndPanel.Parent := panels[i];
        bgndPanel.Visible := True;
        GetBitmapSize(frmBitmaps[BGND_PANEL], a, b);
        bgndPanel.SetBounds(0, 0, a, b);
        DrawBitmap(frmBitmaps[BGND_PANEL], bgndPanel.Canvas, 0, 0);
      end;

      pan := IMG_TAB_NORM_1;

      checkList_Players := TCheckListBox.Create(panels[pan]);
      checkList_Players.Parent := panels[pan];
      checkList_Players.SetBounds(10, 55, 225, 220);

      label_Username := TLabel.Create(panels[pan]);
      label_Username.Parent := panels[pan];
      label_Username.Setbounds(245,55,50,13);
      label_Username.Caption := 'Username';
      label_Username.Font.Color := 2070783;

      edit_User := TEdit.Create(panels[pan]);
      edit_User.Parent := panels[pan];
      edit_User.SetBounds(label_Username.left,label_Username.top + label_Username.height + 5,83,21);

      label_Pass := TLabel.Create(panels[pan]);
      label_Pass.Parent := panels[pan];
      label_Pass.Setbounds(label_Username.left, edit_User.top + edit_User.height + 10,32,13);
      label_Pass.Caption := 'Password';
      label_Pass.Font.Color := 2070783;

      edit_Pass := TEdit.Create(panels[pan]);
      edit_Pass.Parent := panels[pan];
      edit_Pass.SetBounds(label_Username.left,label_Pass.top + label_Pass.height + 5,83,21);

      label_Pin := TLabel.Create(panels[pan]);
      label_Pin.Parent := panels[pan];
      label_Pin.Setbounds(label_Username.left, edit_Pass.top + edit_Pass.height + 10,32,13);
      label_Pin.Caption := 'Pin';
      label_Pin.Font.Color := 2070783;

      edit_Pin := TEdit.Create(panels[pan]);
      edit_Pin.Parent := panels[pan];
      edit_Pin.SetBounds(label_Username.left, label_Pin.top + label_Pin.height + 5, 83, 21);
      edit_Pin.MaxLength := 4;

      label_Member := TLabel.Create(panels[pan]);
      label_Member.Parent := panels[pan];
      label_Member.Setbounds(label_Username.left, edit_Pin.top + edit_Pin.height + 10,32,13);
      label_Member.Caption := 'Members';
      label_Member.Font.Color := 2070783;

      comboBox_Member := TComboBox.Create(panels[pan]);
      comboBox_Member.Parent := panels[pan];
      comboBox_Member.SetBounds(label_Username.left, label_Member.top + label_Member.height + 5, 83, 21);
      comboBox_Member.OnKeyPress := @PreventTyping;
      comboBox_Member.Items.Add('True');
      comboBox_Member.Items.Add('False');
      comboBox_Member.Text := 'False';

      btn_AddPlayer := TButton.Create(panels[pan]);
      btn_AddPlayer.Parent := panels[pan];
      btn_AddPlayer.Setbounds(22,22,95,25);
      btn_AddPlayer.Caption := 'Add Player';
      btn_AddPlayer.ONCLICK := @PanelOneClicks;

      btn_DeletePlayer := TButton.Create(panels[pan]);
      btn_DeletePlayer.Parent := panels[pan];
      btn_DeletePlayer.SetBounds(btn_AddPlayer.left+btn_AddPlayer.width+10,btn_AddPlayer.top,btn_AddPlayer.width,btn_AddPlayer.height);
      btn_DeletePlayer.Caption := 'Remove Player';
      btn_DeletePlayer.OnClick := @PanelOneClicks;
      btn_DeletePlayer.Enabled := (Length(MSI_Players) > 1);

      panOne_Inst := TLabel.Create(panels[pan]);
      panOne_Inst.Parent := panels[pan];
      panOne_Inst.SetBounds(50,3,73,25);
      panOne_Inst.Caption := 'Input player information and click Add Player';
      panOne_Inst.Font.Color := 2070783;


      for i := low(Previous) to high(Previous) do
      begin
        Previous[i] := TButton.Create(panels[i]);
        Previous[i].Parent := panels[i];
        Previous[i].SetBounds(35,24,73,25);
        Previous[i].Caption := 'Previous';
        Previous[i].OnClick := @PlayerControls;
        //Previous[i].Visible := False;

        ChoosePlay[i] := TComboBox.Create(panels[i]);
        ChoosePlay[i].Parent := panels[i];
        ChoosePlay[i].SetBounds(Previous[i].left + Previous[i].width + 5,Previous[i].top,115,21);
        ChoosePlay[i].OnChange := @PlayerCUpdate;
        ChoosePlay[i].OnKeyPress := @PreventTyping;
        ChoosePlay[i].OnClick := @PlayerControls;

        Next[i] := TButton.Create(panels[i]);
        Next[i].Parent := panels[i];
        Next[i].SetBounds(ChoosePlay[i].left + ChoosePlay[i].width + 5, ChoosePlay[i].top,75,25);
        Next[i].Caption := 'Next';
        Next[i].OnClick := @PlayerControls;
        //Next[i].Visible := False;
      end;


      pan := IMG_TAB_NORM_2;

      inst_P3 := TLabel.Create(panels[pan]);
      inst_P3.Parent := panels[pan];
      inst_P3.SetBounds(60,3,73,25);
      inst_P3.Caption := 'Choose a script(s) for each player to use';
      inst_P3.Font.Color := 2070783;

      CheckListBox_3 := TCheckListBox.Create(panels[pan]);
      CheckListBox_3.Parent := panels[pan];
      CheckListBox_3.SetBounds(10, 55, 315, 220);
      for i := 0 to High(MSI_Scripts) do
      begin
        if (MSI_Scripts[i].Name = '') then
          Continue;

        CheckListBox_3.Items.Add(Capitalize(MSI_Scripts[i].Name));
      end;

      CheckListBox_3.Enabled := False;




      pan := IMG_TAB_NORM_3;

      CheckListBox_4 := TCheckListBox.Create(panels[pan]);
      CheckListBox_4.Parent := panels[pan];
      CheckListBox_4.SetBounds(10, 55, 315, 220);
      for i := 0 to High(MSI_Locations) do
      begin
        if (MSI_Locations[i].Name = '') or (MSI_Locations[i].Name = 'Lost') then
          Continue;

        CheckListBox_4.Items.Append(Capitalize(MSI_Locations[i].Name));
      end;
      CheckListBox_4.Enabled := False;

      inst_P4 := TLabel.Create(panels[pan]);
      inst_P4.Parent := panels[pan];
      inst_P4.SetBounds(85, 3, 73, 25);
      inst_P4.Caption := 'Set a location for each player';
      inst_P4.Font.Color := 2070783;




      pan := IMG_TAB_NORM_4;

      inst_P5 := TLabel.Create(panels[pan]);
      inst_P5.Parent := panels[pan];
      inst_P5.SetBounds(38, 3, 73, 25);
      inst_P5.Caption := 'Set all other required information for each player';
      inst_P5.Font.Color := 2070783;

      time_Total_5 := TEdit.Create(panels[pan]);
      time_Total_5.Parent := panels[pan];
      time_Total_5.SetBounds(180, 60, 83, 21);
      time_Total_5.Text := '0';
      time_Total_5.Enabled := False;

      loads_Total_5 := TEdit.Create(panels[pan]);
      with loads_Total_5 do
      begin
        Parent := panels[pan];
        SetBounds(time_Total_5.Left, time_Total_5.Top + time_Total_5.Height + 10, 83, 21);
        Text := '0';
        Enabled := False;
      end;

      time_Break_5 := TEdit.Create(panels[pan]);
      time_Break_5.Parent := panels[pan];
      time_Break_5.SetBounds(time_Total_5.Left, loads_Total_5.Top + loads_Total_5.Height + 10, 83, 21);
      time_Break_5.Text := '0';
      time_Break_5.Enabled := False;

      loads_Break_5 := TEdit.Create(panels[pan]);
      loads_Break_5.Parent := panels[pan];
      loads_Break_5.SetBounds(time_Total_5.Left, time_Break_5.Top + time_Break_5.Height + 10, 83, 21);
      loads_Break_5.Text := '0';
      loads_Break_5.Enabled := False;

      timeTotal := TLabel.Create(panels[pan]);
      timeTotal.Parent := panels[pan];
      timeTotal.Setbounds(55, 63,32,13);
      timeTotal.Caption := 'Total Time (minutes)';
      timeTotal.Font.Color := 2070783;

      loadsTotal := TLabel.Create(panels[pan]);
      with loadsTotal do
      begin
        Parent := panels[pan];
        Setbounds(timeTotal.Left, timeTotal.Top + time_total_5.height + 10,32,13);
        Caption := 'Total Loads';
        Font.Color := 2070783;
      end;

      timeBreak := TLabel.Create(panels[pan]);
      timeBreak.Parent := panels[pan];
      timeBreak.Setbounds(timeTotal.Left, loadsTotal.Top + loads_total_5.height + 10,32,13);
      timeBreak.Caption := 'Break After (minutes)';
      timeBreak.Font.Color := 2070783;

      loadsBreak := TLabel.Create(panels[pan]);
      loadsBreak.Parent := panels[pan];
      loadsBreak.Setbounds(timeTotal.Left, timeBreak.Top + time_Break_5.Height+10,32,13);
      loadsBreak.Caption := 'Break After (loads)';
      loadsBreak.Font.Color := 2070783;



      pan := IMG_TAB_NORM_5;

      script_CreateComponents(pan);

      nScript := TButton.Create(panels[pan]);
      nScript.Parent := panels[pan];
      nScript.SetBounds(Previous[pan].Left, Previous[pan].Top + Previous[pan].Height + 10, 73, 25);
      nScript.Caption := 'Previous';
      nScript.OnClick := @PanelFiveClicks;
      nScript.Visible := False;

      ComboBox_Script_6 := TComboBox.Create(panels[pan]);
      ComboBox_Script_6.Parent := panels[pan];
      ComboBox_Script_6.SetBounds(ChoosePlay[pan].left, ChoosePlay[pan].top + ChoosePlay[pan].height + 10, 115, 21);
      ComboBox_Script_6.OnChange := @PanelFiveClicks;
      ComboBox_Script_6.OnKeyPress := @PreventTyping;
      ComboBox_Script_6.OnClick := @OnClickEvents;

      pScript := TButton.Create(panels[pan]);
      pScript.Parent := panels[pan];
      pScript.SetBounds(Next[pan].left, Next[pan].top + Next[pan].height + 10,75,25);
      pScript.Caption := 'Next';
      pScript.OnClick := @PanelFiveClicks;
      pScript.Visible := False;

      inst_P6 := TLabel.Create(panels[pan]);
      inst_P6.Parent := panels[pan];
      inst_P6.SetBounds(75, 3, 73, 25);
      inst_P6.Caption := 'Setup each script for each player';
      inst_P6.Font.Color := 2070783;

      intro_CreateComponents;
      intro_Settings(False);
    end;

    procedure SafeInitForm;
    var
      v: TVariantArray;
    begin
      SetArrayLength(v, 0);
      ThreadSafeCall('InitForm', v);
    end;

    procedure ShowFormModal;
    begin
      MainForm.ShowModal;
    end;

    procedure SafeShowFormModal;
    var
      v: TVariantArray;
    begin
      SetArrayLength(v, 0);
      ThreadSafeCall('ShowFormModal', v);
    end;
    the next button would increment twice in the previous version, and this fixes the buttons on the last tab overlappping.
    Last edited by Dan Cardin; 12-31-2010 at 04:55 PM.
    SCAR Tutorials: The Form Tutorial | Types, Arrays, and Classes
    Programming Projects: NotePad | Tetris | Chess


  19. #19
    Join Date
    Apr 2008
    Location
    Marquette, MI
    Posts
    15,252
    Mentioned
    138 Post(s)
    Quoted
    680 Post(s)

    Default

    Okay great, I'll try to add that stuff today.

    Also, I managed to have the form open before waiting for SMART; however, half the time Simba crashes and half the time I get an Invalid Opcode error during runtime. Don't even both asking me why because I have absolutely not idea, but I'm going to try to rearrange some things and see if that does anything.

  20. #20
    Join Date
    Apr 2007
    Posts
    3,152
    Mentioned
    3 Post(s)
    Quoted
    1 Post(s)

    Default

    I assume this is after, because i just moved the smart stuff and SetupSRL to after the tryfinally, that the form is in and it didnt error, though i dont follow through and try to run a script.
    SCAR Tutorials: The Form Tutorial | Types, Arrays, and Classes
    Programming Projects: NotePad | Tetris | Chess


  21. #21
    Join Date
    Apr 2008
    Location
    Marquette, MI
    Posts
    15,252
    Mentioned
    138 Post(s)
    Quoted
    680 Post(s)

    Default

    Quote Originally Posted by Dan Cardin View Post
    I assume this is after, because i just moved the smart stuff and SetupSRL to after the tryfinally, that the form is in and it didnt error, though i dont follow through and try to run a script.
    Yeah that's exactly what I did. It worked the first time, then when I closed the form and tried running it again, Simba crashed. Then I tried running a script and after it setup the player I got an invalid opcode.

    I'm going to run the script before the change to see if that's actually the reason for the invalid opcode. E: It was what caused it.

    E2: Got it working! SetupReflection needed to be called after SetupSRL. That was actually a lot easier than I thought.

    E3: Committed that (only changes to RunMe.simba) and I'll work on your changes now, Dan.

    E4: Okay so I've made all your changes, but only the combo boxes work properly. Here's why: ComboBoxes have an OnChange as well as an OnClick event, which lets us set the previous player's variables before we change to the next player. With buttons, there's only an OnClick so when I try to set the previous player's variables, it sets the next player's instead, which screws everything up. What we need is a way to set the previous player's variables before the actual OnClick procedures are called. I tried simply calling the setting procedures first in the OnClick procedure, but that didn't seem to work. This was the same problem I was running into when I tried to get the Next/Previous buttons working a while ago.

    I have to go for the day, but if you want to try and see what's wrong, I've attached my version of the form.

  22. #22
    Join Date
    Jun 2007
    Posts
    31
    Mentioned
    0 Post(s)
    Quoted
    0 Post(s)

    Default

    Not sure if this has already been suggested or if this already exists and I haven't figured out how to use it, but it would be nice if you could save different sets of character setups. From what I understand, when you save a setup, it overwrites the previously saved setup. It would be nice to be able to save multiple character setups and be able to choose which one you want to load.

  23. #23
    Join Date
    Apr 2007
    Posts
    3,152
    Mentioned
    3 Post(s)
    Quoted
    1 Post(s)

    Default

    @monkeybeer - That would be the Tsavedialogs that i want. and though i havent checked, im fairly sure they're in Simba.

    @Coh3n - what exactly goes wrong when you just call the setting proc first? Because that should work fine.

    EDIT: doesnt seem to save anything even if i change through the comboboxes.
    Last edited by Dan Cardin; 01-02-2011 at 04:37 AM.
    SCAR Tutorials: The Form Tutorial | Types, Arrays, and Classes
    Programming Projects: NotePad | Tetris | Chess


  24. #24
    Join Date
    Apr 2008
    Location
    Marquette, MI
    Posts
    15,252
    Mentioned
    138 Post(s)
    Quoted
    680 Post(s)

    Default

    Quote Originally Posted by Dan Cardin View Post
    @monkeybeer - That would be the Tsavedialogs that i want. and though i havent checked, im fairly sure they're in Simba.
    Great, then that should definitely be added. I'll add that to the suggestions list.

    Quote Originally Posted by Dan Cardin View Post
    @Coh3n - what exactly goes wrong when you just call the setting proc first? Because that should work fine.
    Say I had a character, Cohen1, that was the current player in the combo box, and the next player was Cohen2. When I hit next, it saves the current info (the info I want for Cohen1) in Cohen2 and nothing is saved for Cohen1.

    Quote Originally Posted by Dan Cardin View Post
    EDIT: doesnt seem to save anything even if i change through the comboboxes.
    Have you done it without hitting the Next/Previous buttons at all? It works for me. But nevertheless, I have an idea that should make the buttons work properly. "Should" being the key word there.

  25. #25
    Join Date
    Apr 2007
    Posts
    3,152
    Mentioned
    3 Post(s)
    Quoted
    1 Post(s)

    Default

    Well to me, putting the saving part before changing the currently selected combobox item should work. And yes, i was just selecting the people directly from the comboboxes and it wouldnt save them if i left that person and then went back. Do you save them when you switch tabs?

    EDIT: and i tried compiling part of msi with just the declaration of "aeeee: TSaveDialog;" and while it didn't give me an error like it didnt know what that was, it did in fact crash Simba even though that's all i changed. I hope that doesn't mean what i think it means.

    EDIT: I think it might be a good idea to add a "copy settings" button or something so you can put multiple players doing the same actions more easily. Or have "groups" where a group will do a specific script, and each group can have however many players in it.
    Last edited by Dan Cardin; 01-02-2011 at 08:56 PM.
    SCAR Tutorials: The Form Tutorial | Types, Arrays, and Classes
    Programming Projects: NotePad | Tetris | Chess


+ Reply to Thread
Page 1 of 6 123 ... LastLast

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may post replies
  • You may post attachments
  • You may edit your posts
  •