Page 1 of 6 123 ... LastLast
Results 1 to 25 of 144

Thread: [SRL][OSRS] Slacky's Universal Miner™

  1. #1
    Join Date
    Feb 2012
    Location
    Norway
    Posts
    995
    Mentioned
    145 Post(s)
    Quoted
    596 Post(s)

    Default [SRL][OSRS] Slacky's Universal Miner™

    Slacky's Universal Miner



    A simple universal mining bot. What you see in the video above is that in the first 2 minutes I have setup a mining-bot that runs at varrock east, after that it's the bot that takes over.
    It can be setup most places that's not a dungeon, as long as it's a straight path to the bank (deposit-boxes aren't supported).

    Requirements:


    Keywords:
    • Easy to configure
    • Works most places (no dungeons are supported)
    • Works for just about any ores (need changes for slow rocks as I've just hardcoded a 20sec limit)
    • Supports banking, and power-mining (no deposit boxes)
    • First slot can be used for a pickaxe - otherwise start with empty inv.
    • Configs can be shared with others
    • Break-handling (between 5 min and 7 hours)
    • A number of Antiban measures
    • Feels fatigue - Slows down the bot - Recharges with breaks


    Simba Code:
    program Universal_Miner_V034;
    {$DEFINE SMART}
    {$I SRL/OSR.simba}
    {$I SRL/utils/slackdebug.simba}
    {$I RSWalker/Walker.simba}
    {$H-}{$R+}{$X+}
    {$DEFINE SMARTDEBUG}
    {==============================================================================]
    | Universal Miner ™
    |
    | Steps to use:
    |   1. For longer runs you need to declare login details bellow
    |   2. Start the script at your mining site, and run setup.
    [==============================================================================}

    type
      EDropStyle = (dsRegular, dsIntense, dsAdaptive);

    const
      LOGIN_NAME   = '';
      LOGIN_PASS   = '';
      RS_WORLD     = -1;          // preferred world
      IS_MEMBER    = False;       //
      SHIFT_DROP   = True;        // use shift to drop
      INTENSE_DROP = dsRegular;   // dsIntense, and dsAdaptive = mine some drop some (Often higher XP)

      CONFIG_PATH = IncludePath+'Universal_Miner/';
      CONFIG_FILE = 'config.cfg';
      CONFIG_MAP  = 'map.png';

      INTENSITY_LEVEL = 88;
      CHANCE_OF_MISS = 1;

    type
      TClickHistory = record
        Data: TRectArray;
      end;

      TStatistics = record
        Trips: Int32;
        StartInfo: TSkillInfo;
        CurrLvl: Int32;
        Count: Int32;
        PrcToNextLvl: Int32;
        Gains,Rem,CurrXP:Double;
        XPPerOre: Int32;
        DismissedRandoms: Int32;
        Isset_XPPerOre: Boolean;
      end;

      TMiner = record
        PlayerBox: TBox;
        ConfigPath: String;

        StartTime: Int64;
        QuickDeposit: Boolean;
        BotStats: TStatistics;
        StatsDebugTick: Int64;

        RockSpots,  BankSpots: TPointArray;
        RockColors, BankColors: array of TCTS2Color;
        BankPath: TPointArray;

        ClickOrder: TClickHistory;
        ProggyArea: TBox;
        FailCount: Int32;

        Antiban: TAntiban;
      end;


    var
      Bot: TMiner;
      RSW: TRSWalker;

      NativeClient: Int32;

    // -----------------------------------------------------------------------------
    // -----------------------------------------------------------------------------
    // WIN API stuff

    const WINAPI_CC  = {$IFDEF CPU386}' stdcall'{$ELSE}' win64'{$ENDIF};
    const ffi_winapi = {$IFDEF CPU386}ffi_stdcall{$ELSE}ffi_win64{$ENDIF};

    type
      _EnumWindowsProc = function(wnd:DWORD; Param:Pointer): LongBool;
      TEnumWindowsProc = native(_EnumWindowsProc, ffi_winapi);

    function GetAsyncKeyState(vKey: Int32): Int16; external 'GetAsyncKeyState@user32.dll' + WINAPI_CC;
    function GetForegroundWindow(): PtrUInt; external 'GetForegroundWindow@user32.dll' + WINAPI_CC;
    function GetWindowThreadProcessId(wnd: PtrUInt; out dwProcessId: DWORD): DWORD; external 'GetWindowThreadProcessId@user32.dll' + WINAPI_CC;
    function EnumChildWindows(hWndParent: DWORD; func: TEnumWindowsProc; Param: Pointer): LongBool; external 'EnumChildWindows@user32.dll' + WINAPI_CC;
    function GetClientRect(wnd: DWORD; out Rect: TBox): Boolean; external 'GetClientRect@user32.dll' + WINAPI_CC;

    function GetKeyDown(): Char;
    var
      key: Word;
      keys: array of Word;
    begin

      keys := [VK_A..VK_Z];
      keys += [VK_0..VK_9];
      keys += [VK_OEM_PERIOD, VK_OEM_MINUS];
      for Key in keys do
        if GetAsyncKeyState(key) and $8000 <> 0 then
        begin
          while GetAsyncKeyState(key) and $8000 <> 0 do Wait(10);
          if key = VK_OEM_PERIOD then key := Ord('.');
          if key = VK_OEM_MINUS  then key := Ord('-');
          Exit(Char(key));
        end;
    end;

    function IsKeyDown2(vKey: Word): Boolean;
    begin
      Result := GetAsyncKeyState(vKey) and $8000 <> 0;
    end;

    function HasFocus(PID: PtrUInt): Boolean;
    var tmp: DWORD;
    begin

      GetWindowThreadProcessId(GetForegroundWindow(), tmp);
      Result := tmp = PID;
    end;

    function GetRSAppletWnd(PID: DWORD): DWORD;
      function GetNativeClient(Handle: DWORD; Param: Pointer): LongBool; static;
      var B: TBox;
      begin
        GetClientRect(handle, B);
        if (B.Width = 765+1) and (B.Height = 503+1) then
          DWORD(Param^) := handle;
        Result := True;
      end;
    var
      p: TSysProc;
      client: DWORD;
    begin
      for p in GetProcesses() do
        if p.Pid = PID then
          Break;
      EnumChildWindows(p.Handle, @GetNativeClient, @Result);
      if Result = 0 then Result := NativeClient;
    end;


    // -----------------------------------------------------------------------------
    // -----------------------------------------------------------------------------
    // UTILITY FUNCTIONS

    function StrToTPA(s:String): TPointArray;
    var
      i: Int32;
      Arr: TExtArray;
    begin
      Arr := s.ExtractNumbers();
      SetLength(Result, Length(Arr) div 2);
      for i:=0 to High(Result) do
      begin
        Result[i].x := Trunc(Arr[i*2]);
        Result[i].y := Trunc(Arr[i*2+1]);
      end;
    end;

    function StrToCTS2(s:String): array of TCTS2Color;
    var
      i: Int32;
      Arr: TExtArray;
    begin
      Arr := s.ExtractNumbers();
      SetLength(Result, Length(Arr) div 4);
      for i:=0 to High(Result) do
      begin
        Result[i].Color     := Trunc(Arr[i*4]);
        Result[i].Tolerance := Trunc(Arr[i*4+1]);
        Result[i].HueMod    := Arr[i*4+2];
        Result[i].SatMod    := Arr[i*4+3];
      end;
    end;

    procedure TMouse.Move(P: TPoint); override;
    var
      dist: Double;
      q: TPoint;
      maxSpeed := Random(20,22);
      minSpeed := Random(4,6);
    begin
      q := Self.GetPosition;
      dist := Hypot(q.x-p.x, q.y-p.y);
      self.Speed := Trunc(minSpeed + (maxSpeed-minSpeed) * Power(dist / 1000, 1/2));
      inherited;
    end;


    // -----------------------------------------------------------------------------
    // -----------------------------------------------------------------------------
    // MISC BOT FUNCTIONS

    function WorldToMSTile(Me, ObjLoc: TPoint; Height:Double=0; Offx,Offy:Double=0): TRectangle;
    var
      Angle: Double;
    begin
      ObjLoc := Point(MM2MS.MMCX, MM2MS.MMCY) + (ObjLoc - Me);
      Angle  := Minimap.GetCompassAngle(False);
      ObjLoc := ObjLoc.Rotate(Angle, Point(MM2MS.MMCX, MM2MS.MMCY));
      Result := Minimap.VecToMSRect(Vec3(ObjLoc.x - offx, ObjLoc.y - offy, Height), Angle);
    end;

    procedure TClickHistory.Push(x: TRectangle);
    begin
      Insert(x, Self.Data, 0);
    end;

    function TClickHistory.Pop(): TRectangle;
    begin
      if Length(Self.Data) < Length(Bot.RockSpots)  then
        Exit(Self.Data[High(Self.Data)]);
      Result := Self.Data[High(Self.Data)];
      SetLength(Self.Data, High(Self.Data));
    end;


    // -----------------------------------------------------------------------------
    // -----------------------------------------------------------------------------
    // OVERRIDES AND METHODS FOR FATIGUE

    procedure WaitFatigue(t: Double; Exp: Double=0.2);
    begin
      System.Wait(Trunc(2*t * (1-Power(System.Max(0.0001, Bot.Antiban.EnergyLevel/100),Exp))));
    end;

    procedure Wait(min, max:Double; weight:EWaitDir=wdMean); override;
    var t:Double;
    begin
      t := PerformanceTimer();
      inherited(min, max, weight);
      WaitFatigue(PerformanceTimer()-t,0.2);
    end;

    procedure WaitEx(mean, dev:Double); override;
    var t:Double;
    begin
      t := PerformanceTimer();
      inherited(mean, dev);
      WaitFatigue(PerformanceTimer()-t, 0.2);
    end;


    // -----------------------------------------------------------------------------
    // -----------------------------------------------------------------------------
    // MINER

    function TMiner.GetTimeRunning(): Int64;
    begin
      if Self.StartTime = 0 then Exit(0);
      Result := GetTickCount() - Self.StartTime;
    end;


    procedure TMiner.DeclarePlayers();
    begin
      with Players.New()^ do
      begin
        LoginName := LOGIN_NAME;
        Password  := LOGIN_PASS;
        IsActive  := True;
        IsMember  := IS_MEMBER;
        World     := RS_WORLD;
      end;
      Players.SetCurrent(0);
    end;

    procedure TMiner.SetupAntiban();
    begin
      Antiban.Init(SKILL_MINING);
      Antiban.AddTask([@Antiban.LoseFocus,     ONE_MINUTE*7, 0.15]);
      Antiban.AddTask([@Antiban.HoverPlayers,  ONE_MINUTE*9, 0.15]);
      Antiban.AddTask([@Antiban.CheckSkill,    ONE_MINUTE*13, 0.15]);
      Antiban.AddTask([@Antiban.CheckStats,    ONE_MINUTE*18, 0.15]);
      Antiban.AddTask([@Antiban.OpenRandomTab, ONE_MINUTE*20, 0.15]);
      Antiban.AddTask([@Antiban.RandomCompass, ONE_MINUTE*40, 0.15]);
      Antiban.AddTask([@Antiban.DoMiscStuff,   ONE_MINUTE*45, 0.15]);
      Antiban.AddTask([@Antiban.VeryShortBreak,ONE_MINUTE*50, 0.15]);

      Antiban.AddBreak([1.0 * ONE_HOUR, 05 * ONE_MINUTE, 0.33, 0.25]);
      Antiban.AddBreak([3.5 * ONE_HOUR, 40 * ONE_MINUTE, 0.85, 0.15]);
      Antiban.AddBreak([17  * ONE_HOUR, 07 * ONE_HOUR,   0.95, 0.10]);
    end;

    function TMiner.HasBanking(): Boolean;
    begin
      Result := (Self.BankColors <> []) and (Self.BankPath <> []) and (Self.BankSpots <> []);
    end;

    procedure TMiner.DoAntiban();
    begin
      if Self.Antiban.DoAntiban() then
        Players.GetCurrent()^.Login(); // if we got logged out
    end;

    procedure TMiner.PostAction(CheckAntiban: Boolean = True);
    begin
      WaitEx(500,70);
      if CheckAntiban then Self.DoAntiban;
    end;

    procedure TMiner.ProcessWhileWaiting();
    var
      n,atNextLvl,atCurrLvl:Int32;
    begin
      BotStats.Gains := BotStats.Count * BotStats.XPPerOre;
      BotStats.CurrXP  := BotStats.StartInfo.XP + BotStats.Gains;
      BotStats.CurrLvl := srl.GetLevelAtXP(Ceil(BotStats.CurrXP));
      atNextLvl := srl.GetXPAtLevel(BotStats.CurrLvl+1);
      atCurrLvl := srl.GetXPAtLevel(BotStats.CurrLvl);
      BotStats.Rem := atNextLvl - BotStats.CurrXP;
      BotStats.PrcToNextLvl := 100 - Round((BotStats.Rem / (atNextLvl - atCurrLvl)) * 100);

      if GetTickCount() - StatsDebugTick > 2000 then
      begin
        ClearDebug();
        WriteLn('+---| STATS |----------------------------------------');
        WriteLn('|- Trips / Drops       : ', BotStats.Trips);
        WriteLn('|- Ores Mined          : ', BotStats.Count);
        WriteLn('|- Experience Gained   : ', BotStats.Gains);
        WriteLn('|- Experience Per Hour : ', Round(BotStats.Gains / (GetTimeRunning()/1000/60/60)) );
        WriteLn('|- Dismissed Randoms   : ', BotStats.DismissedRandoms);
        WriteLn('|- Time Since Break    : ', SRL.MsToTime(Self.Antiban.TimeSinceBreak, Time_Short));
        WriteLn('|- Energy Level        : ', Self.Antiban.EnergyLevel);
        WriteLn('|- Script Runtime      : ', SRL.MsToTime(GetTimeRunning, Time_Short));
        WriteLn('+----------------------------------------------------');

        {$IFDEF SMARTDEBUG}
        ProggyArea := Smart.Image.DrawSkillReport([288,2], clProgBrown, Trunc(BotStats.CurrXP), Trunc(BotStats.Gains), BotStats.Count, 'Mining');
        {$ENDIF}

        StatsDebugTick := GetTickCount();
      end;
      Self.DoAntiban;
    end;


    function TMiner.Contains(R: TRectangle; Colors: array of TCTS2Color): Boolean;
    var
      TPA: TPointArray;
      i, count: Int32;
    begin
      for i:=0 to High(Colors) do
      begin
        count += srl.FindColors(TPA, Colors[i], R.Bounds);
        if count > 150 then  //XXXXXXXXXXXX
          Exit(True);
      end;
    end;


    function TMiner.Find(Locations: TPointArray): TRectArray;
    var
      i: Int32;
      me: TPoint;
      rect: TRectangle;
    begin
      me := RSW.GetMyPos();
      for i:=0 to High(Locations) do
      begin
        rect := WorldToMSTile(me, Locations[i], 0,0,0).Expand(-2);
        if MainScreen.GetBounds.Contains(rect.Bounds) then
          Result += rect;
      end;

      if (Length(Result) = 0) then
      begin
        if (Self.FailCount in [2,6]) then
          Minimap.RandomCompass(0,359)
        else if (Self.FailCount = 7) then
        begin
          WriteLn('Trying to recover from failure');
          Logout.ClickLogout();
          Wait(1000,30000,wdLeft);
          Players.GetCurrent^.Login();
          MainScreen.SetAngle(True);
          WaitEx(500,150);
        end else if (Self.FailCount > 10) then
          TerminateScript('Not close enough to objects: ('+ ToStr(me.x) +','+ToStr(me.y)+') -> '+ ToStr(locations));

        Inc(Self.FailCount);
        WaitEx(600,150);
      end else
        Self.FailCount := 0;
    end;


    function TMiner.DoWork(): Boolean;
    var
      i: Int32;
      T: TCountDown;
      TRA: TRectArray;
      next: TRectangle;
      tmpCurrXP, invCount: Int32;

      function MaybeMiss(): Boolean;
      var
        R: TRectangle;
      begin
        Result := True;
        if Random()*100 <= CHANCE_OF_MISS then
        begin
          R := Minimap.PointToMsRect(Point(MM2MS.MMCX+Random(-6,6), MM2MS.MMCY+Random(-6,6)));
          Mouse.Move(R, True);
          WaitEx(65,10);
          if MainScreen.IsUpText(['Walk here', 'Mine', 'Rocks']) then
            Exit();
          Result := False;
        end;
      end;

      function ClickRock(rect: TRectangle): Int8;
      begin
        mouse.Move(rect, Random(10) = 0);
        WaitEx(65,10);
        if not Mainscreen.IsUpText(['Mine', 'Rocks']) then
          Exit(1);

        if (not MaybeMiss()) then
          Exit(0);

        if (not ((Random() <= 0.05) and ChooseOption.Select('Mine Rocks'))) and
           (not Mouse.Click(ctRed)) then
        begin
          Wait(400,7000,wdLeft);
          Self.DoAntiban;
          WaitFatigue(Random(1500,3000), 0.6);
          Exit(0);
        end;

        ClickOrder.Push(TRA[i]);
        for 6 to Round(srl.TruncatedGauss(0,12)) do
        begin
          Mouse.Click(mouse_Left);
          WaitEx(65,10);
        end;

        WaitEx(300,60);
        Result := 2;
      end;

    begin
      invCount := Inventory.Count;
      TRA := Find(self.RockSpots);

      if (Self.BotStats.StartInfo = []) and (Self.BotStats.XPPerOre = 0) then
      begin
        Self.BotStats.StartInfo := Stats.GetSkillInfo(SKILL_MINING);
        Self.BotStats.XPPerOre  := BotStats.StartInfo.XP;
      end;

      for i:=0 to High(TRA) do
      begin
        if not Contains(TRA[i], Self.RockColors) then
          Continue;

        WaitFatigue(Random(700,1200), 0.1);
        case ClickRock(TRA[i]) of
          0: Exit;
          1: Continue;
          2: Minimap.WaitPlayerMoving(False);
        end;

        next := ClickOrder.Pop();
        if (Self.Antiban.EnergyLevel > 40) or (Random() < 0.05) then
        begin
          if(Random() > 0.05) then
            Mouse.Move(next, Random() < 0.1)
          else if(Random() < 0.05) then
          begin
             Mouse.Move(srl.DefaultClientBounds, True, rndRandom);
             WaitFatigue(5000, 0.6);
          end;
        end;

        TRA := Find(self.RockSpots); // update the TRA in case we moved
        T.Init(srl.NormalRange(20000,25000)); //XXXXXXXXXXXX
        while (not T.IsFinished) and Contains(TRA[i], Self.RockColors) do
        begin
          if(Chatbox.GotLevelUp()) then
            if(Random(9) = 0) then
              Chatbox.HandleLevelUp()
            else
              Break;

          if 'inventory is too full' in Chatbox.GetNotification() then
            Break;

          Self.ProcessWhileWaiting();
          Wait(30);
        end;

        if (Inventory.Count > invCount) then
        begin
          Inc(Self.BotStats.Count);
          if (not Self.BotStats.Isset_XPPerOre) then //XXXXXXXXXXXX
          begin
            Self.BotStats.XPPerOre := Stats.GetSkillInfo(SKILL_MINING).XP - Self.BotStats.XPPerOre;
            Self.BotStats.Isset_XPPerOre := Self.BotStats.XPPerOre > 0;
          end;
        end;

        Exit(True);
      end;
    end;


    procedure TMiner.DoBanking();
      function OpenBank(): Boolean;
      var Rect: TRectangle;
      begin
        for 0 to 3 do
        begin
          for Rect in Find(self.BankSpots) do
            if Contains(Rect, Self.BankColors) and BankScreen.OpenAt(srl.RandomPoint(Rect.Mean, Trunc(Rect.Radius))) then
              Exit(True);
          Wait(800,1300);
        end;
      end;

      function BankInventory(): Boolean;
      var
        slots: TIntArray;
        t: TCountDown;
      begin
        if Self.QuickDeposit then
          Exit(BankScreen.DepositAll);

        slots := Inventory.GetUsedSlots();
        slots.Remove(0); //reserved
        while Length(slots) > 0 do
        begin
          Inventory.MouseSlot(slots[0]);
          ChooseOption.Select('Deposit-All');
          t.Init(2000);
          while Inventory.IsSlotUsed(slots[0]) and (not t.IsFinished) do WaitEx(90,10);
          slots := Inventory.GetUsedSlots();
          slots.Remove(0);
        end;
        Wait(1, 1200, wdLeft);
        Result := not Inventory.IsFull();

        if Inventory.Count = 0 then
          Self.QuickDeposit := True;
      end;

      function Walk(path: TPointArray): Boolean;
      begin
        for 0 to 2 do
          if RSW.WalkPath(Path) then
            Exit(True)
          else
            Wait(800, 3200, wdRight);
      end;

    begin
      if(not Walk(self.BankPath)) then
        TerminateScript('Failed to walk path [1]');
      Self.DoAntiban;

      if(not OpenBank()) then
        TerminateScript('Failed to open bank');
      PostAction(False);

      if(not BankInventory()) then
        TerminateScript('Failed to deposit items');
      PostAction;

      if(not Walk(self.BankPath.Reversed)) then
        TerminateScript('Failed to walk path [2]');
      Self.DoAntiban;
    end;


    procedure TMiner.IntenseDrop(Test: function: Boolean of Object);
    var
      p: TPoint;
      Slots: TIntArray;
      n: Int32 = 3;
    begin
      if Test() then Exit;

      if Random(5) = 0 then
        n := Random(2,4);

      p := Mouse.GetPosition();
      Slots := Inventory.GetUsedSlots();
      if (Length(Slots) >= 3)then
      begin
        if(not Self.QuickDeposit) then Slots.Remove(0);

        SetLength(Slots, Min(Length(Slots), n));
        Inventory.DropItems(Inventory.ErrorPattern(Slots,2));
        Mouse.Move(p,20);
      end;
    end;

    procedure TMiner.DropInventory();
    begin
      if Self.QuickDeposit then
        Inventory.DropItems(Inventory.ErrorPattern(DROP_PATTERN_SNAKE))
      else
        Inventory.DropItemsExcept([0], Inventory.ErrorPattern(DROP_PATTERN_SNAKE));
    end;


    procedure TMiner.Run();
    var
      loc: TPoint;

      procedure TryDropWhileMining();
      begin
        if (not HasBanking) and (INTENSE_DROP in [dsIntense,dsAdaptive])  then
        begin
          if (INTENSE_DROP = dsIntense) then
            Self.IntenseDrop(@Self.DoWork)
          else if (INTENSE_DROP = dsAdaptive) and (Self.Antiban.EnergyLevel > INTENSITY_LEVEL) then
            Self.IntenseDrop(@Self.DoWork);
        end;
      end;

    begin
      Self.StartTime := GetTickCount();
      Self.SetupAntiban();
      MainScreen.SetAngle(True);

      if Inventory.Count = 0 then
        Self.QuickDeposit := True;

      if Self.HasBanking() then
      begin
        loc := RSW.GetMyPos();
        if (Distance(loc, self.BankPath[high(self.BankPath)]) < Distance(loc, self.BankPath[0])) and
           (not RSW.WalkPath(self.BankPath.Reversed)) then
          TerminateScript('Failed to walk from bank on startup');
      end;

      repeat
        if (Random(5000) <> 0) and Inventory.IsFull() then
        begin
          if HasBanking then Self.DoBanking()
          else               Self.DropInventory();
          Inc(BotStats.Trips);
        end;

        if Self.DoWork() then
        begin
          TryDropWhileMining();
          Self.DoAntiban;
        end else
          Players.GetCurrent()^.Login();
        Wait(1);
      until False;
    end;

    procedure TMiner.Init();
    var
      W, H: Integer;
    begin
      GetClientDimensions(W, H);

      self.PlayerBox := Minimap.VecToMsRect(Vec3(MM2MS.MMCX,MM2MS.MMCY,2)).Expand(7).Bounds;
      self.DeclarePlayers();
      Mouse.Speed := 10;
      Players.GetCurrent()^.Login();

      Inventory.ShiftDrop := SHIFT_DROP;
    end;



    // -----------------------------------------------------------------------------
    // -----------------------------------------------------------------------------
    // Crazy config generation

    procedure TMiner.Setup();
    var
      r: String;
      DefaultBox: TBox = [75,40, 425,140];
      client2: TClient;

    type
      TButtonBox = record
        TextTPA: TPointArray;
        Bounds: TBox;
      end;

      function SlowMSToMM(MS: TPoint): TPoint;
      var
        x,y: Int32;
        best,test: TPoint;
      begin
        for x:=MM2MS.MMCX-52 to MM2MS.MMCX+52 do
          for y:=MM2MS.MMCY-52 to MM2MS.MMCY+52 do
          begin
            test := Minimap.PointToMs([x,y],0);
            if Distance(test, MS) < Distance(best, MS) then
            begin
              best := test;
              Result := Point(x,y);
            end;
          end;
      end;

      procedure WaitReleaseKey();
      begin
        while client2.GetIOManager.IsMouseButtonDown(0) do Wait(10);
      end;

      function GetClick(out p: TPoint): Boolean;
      begin
        if not HasFocus(smart.PID) then Exit();
        if client2.GetIOManager.IsMouseButtonDown(0) then
        begin
          client2.GetIOManager.GetMousePos(p.x,p.y);
          Result := p.InBox(GetClientBounds);
          WaitReleaseKey();
        end;
      end;

      function GetButton(txt: String): TButtonBox;
      begin
        Result.TextTPA := TPAFromText(txt, StatChars07);
        Result.Bounds  := GetTPABounds(Result.TextTPA).ExpandFunc(8);
      end;

      function DrawButton(p: TPoint; var Button: TButtonBox): TButtonBox;
      begin
        Button.TextTPA.Offset(p);
        Button.Bounds.Offset(p);
        smart.Image.DrawBox(Button.Bounds, True, 2502198);
        smart.Image.DrawBox(Button.Bounds.ExpandFunc(-1), True, 4607315);
        smart.Image.DrawTPA(Button.TextTPA, $FFFFFF);
      end;

      function MessageBox(Text: String; Area:TBox=[]): string;
      var
        xstart: Int32;
        TPA: TPointArray;
        box: TBox;
      begin
        if (Area.x1 = Area.x2) then Area := chatbox.GetBounds;
        smart.Image.DrawBox(Area.ExpandFunc(-0), False, $1F2F33);
        smart.Image.DrawBox(Area.ExpandFunc(-1), False, $3F4A5A);
        smart.Image.DrawBox(Area.ExpandFunc(-2), False, $1F2F33);
        smart.Image.DrawBox(Area.ExpandFunc(-3), True,  $171D20);

        TPA := TPAFromText(Text, SmallChars07);
        box := GetTPABounds(TPA);
        xstart := (box.Width + Area.Width) div 2 - box.Width;
        OffsetTPA(TPA, Point(Area.x1+xstart, Area.y1+20));
        smart.Image.DrawTPA(TPA, $FFFFFF);
      end;

      function Query(Text: String; Alts:TStringArray; Area:TBox=[]): string;
      var
        i,xstart,CurrWidth: Int32;
        p: TPoint;
        Buttons: array of TButtonBox;
        xOffset: TIntArray;
      begin
        if (Area.x1 = Area.x2) then Area := chatbox.GetBounds;

        // query
        MessageBox(Text, Area);

        // buttons
        for i:=0 to High(Alts) do
        begin
          Buttons   += GetButton(Alts[i]);
          xOffset   += CurrWidth;
          CurrWidth += Buttons[i].Bounds.X2+20;
        end;
        CurrWidth -= 20;

        xstart := (CurrWidth + Area.Width) div 2 - CurrWidth;
        for i:=0 to High(Buttons) do
          DrawButton(Point(Area.x1+xstart+xOffset[i], Area.y1+50), Buttons[i]);

        // handling
        while True do
        begin
          if GetClick(p) then
            for i:=0 to High(Buttons) do
              if PointInBox(p, Buttons[i].Bounds) then
              begin
                smart.Image.DrawBox(Area, True, 0);
                Exit(Alts[i]);
              end;
          Wait(1);
        end;
      end;

      function QueryStr(Text: String; Area:TBox=[]): string;
      var
        i: Int32;
        pt, p: TPoint;
        chr: Char;
        B: TBox;
        TPA: TPointArray;
        Button: TButtonBox;
      begin
        if (Area.x1 = Area.x2) then
          Area := chatbox.GetBounds;

        // query
        smart.Image.DrawBox(Area.ExpandFunc(-0), False, $1F2F33);
        smart.Image.DrawBox(Area.ExpandFunc(-1), False, $3F4A5A);
        smart.Image.DrawBox(Area.ExpandFunc(-2), False, $1F2F33);
        smart.Image.DrawBox(Area.ExpandFunc(-3), True,  $171D20);

        TPA := TPAFromText(Text, SmallChars07);
        OffsetTPA(TPA, Point(Area.x1+40, Area.y1+20));
        smart.Image.DrawTPA(TPA, $FFFFFF);
        B := GetTPABounds(TPA);

        // button
        Button := GetButton('OK');
        DrawButton(Point(Area.x1+48, Area.y1+50), Button);

        // handling
        pt.x := B.x2+5;
        pt.y := Area.y1+20;
        repeat
          while not HasFocus(smart.PID) do Wait(10);

          if GetClick(p) then
            if PointInBox(p, Button.Bounds) then
            begin
              smart.Image.DrawBox(Area, True, 0);
              Exit(Result);
            end;

          chr := GetKeyDown();
          if chr <> #0 then
          begin
            Result += Lowercase(chr);
            Keyboard.PressKey(VK_BACK);
            smart.Image.DrawText(Result,'SmallChars07', pt, False, $FFCCAA);
          end;

          if IsKeyDown2(VK_BACK) and (Result <> '') then
          begin
            TPA := TPAFromText(Result, 'SmallChars07');
            TPA.Offset(pt);
            smart.Image.DrawBox(GetTPABounds(TPA), True, $171D20);
            while IsKeyDown2(VK_BACK) do Wait(50);
            SetLength(Result, Length(Result)-1);
            smart.Image.DrawText(Result, 'SmallChars07', pt, False, $FFCCAA);
          end;
        until False;
      end;

      function SetupLocations(): TPointArray;
      var
        p, me, worldPt: TPoint;
        rect: TRectangle;
      begin
        me := RSW.GetMyPos();

        while True do
        begin
          if GetClick(p) then
          begin
            worldPt := (SlowMSToMM(p) - Point(MM2MS.MMCX, MM2MS.MMCY)) + me;

            rect := WorldToMSTile(me, worldPt);
            if Mainscreen.GetBounds.Contains(rect.Bounds) then
            begin
              smart.Image.DrawTPA(rect.ToTPA.Connect, $FFFF);
              case Query('Are you happy?', ['Add more', 'Retry', 'Yes']) of
                'Retry':    smart.Image.DrawTPA(rect.ToTPA.Connect, 0);
                'Add more': Result += worldPt;
                'Yes':      begin Result += worldPt; Break; end;
              end;
            end;
          end;
          Wait(1);
        end;
        smart.Image.Clear();
      end;

      function SetupColors(Locations: TPointArray): array of TCTS2Color;
      var
        i: Int32;
        p,me: TPoint;
        IsValid: Boolean;
        R: array of TRectangle;
        Color: TCTS2Color;
        TPA: TPointArray;

        function MarkColors(Colors: array of TCTS2Color): TPointArray;
        var
          i,j: Int32;
          TPA: TPointArray;
        begin
          for i:=0 to High(Colors) do
            for j:=0 to High(R) do
              if srl.FindColors(TPA, Colors[i], R[j].Bounds.ExpandFunc(-1)) then
              begin
                TPA := R[j].Filter(TPA);
                smart.Image.DrawTPA(TPA, $FF);
                Result += TPA;
              end;
        end;
      begin
        me := RSW.GetMyPos();
        SetLength(R, Length(Locations));
        for i:=0 to High(Locations) do
        begin
          R[i] := WorldToMSTile(Me, Locations[i]);
          smart.Image.DrawTPA(R[i].ToTPA.Connect, $00FF00);
        end;

        while True do
        begin
          if GetClick(p) then
          begin
            Color := CTS2(GetColor(p), 13);
            for i:=0 to High(R) do
              if R[i].Contains(p) then
              begin
                IsValid := True;
                break;
              end;
            if(not IsValid) then
              continue;

            TPA := MarkColors(Result + Color);
            case Query('Are you happy?', ['Add more', 'Retry', 'Reset', 'Yes']) of
              'Retry':    smart.Image.DrawTPA(TPA, 0);
              'Add more': Result += Color;
              'Yes':      begin Result += Color; Break; end;
              'Reset':    begin smart.Image.DrawTPA(TPA, 0); Result := []; end;
            end;
          end;
          Wait(1);
        end;
        smart.Image.Clear();
      end;

      function RecordPath(): TPointArray;
      var
        worldPt,p: TPoint;
        t: UInt64;
      begin
        t := GetTickCount()+8000;
        while True do
        begin
          if GetClick(p) then
          begin
            t := GetTickCount()+2500;
            worldPt := RSW.GetMyPos();
            Mouse.Click(p, mouse_Left);

            Result += worldPt;
          end;

          if (GetTickCount() > t) and (not Minimap.isPlayerMoving()) then
            case Query('Are we there yet?', ['No', 'Yes']) of
              'Yes': Exit(Result+RSW.GetMyPos());
              'No' : t := GetTickCount()+2500;
            end;
          Wait(1);
        end;
      end;

      procedure GenerateMap(MapPath:String; Pad:Int32=160);
      var
        pt,sz: TPoint;
        map,slice: TMufasaBitmap;
        TPA: TPointArray;
        B: TBox;
      begin
        TPA := Self.BankPath + Self.RockSpots + Self.BankSpots;

        sz := Point(High(RSW.WorldMap[0]),High(RSW.WorldMap));
        B := TPA.Bounds.ExpandFunc(Pad);
        B.LimitTo(Box(0,0,sz.x,sz.y));

        map.Init(client.GetMBitmaps);
        map.SetSize(B.Width, B.Height);
        for pt in TPA do
        begin
          slice.Init(client.GetMBitmaps);
          slice.DrawMatrix(RSW.WorldMap.Crop(Box(
              Max(0,pt.x-Pad),
              Max(0,pt.y-Pad),
              Min(sz.x,pt.x+Pad),
              Min(sz.y,pt.y+Pad)
          )));
          slice.DrawTransparent(pt.x-B.x1-Pad,pt.y-B.y1-Pad, map);
          slice.Free();
        end;
        map.SaveToFile(MapPath);
        map.Free();

        Self.BankPath.Offset ([-B.x1,-B.y1]);
        Self.RockSpots.Offset([-B.x1,-B.y1]);
        Self.BankSpots.Offset([-B.x1,-B.y1]);
      end;

      function LoadConfig(): Boolean;
      begin
        if not FileExists(ConfigPath+CONFIG_FILE) then
          Exit(False);

        BankPath   := StrToTPA (ReadINI('settings', 'BankPath',   ConfigPath+CONFIG_FILE));
        RockSpots  := StrToTPA (ReadINI('settings', 'RockSpots',  ConfigPath+CONFIG_FILE));
        RockColors := StrToCTS2(ReadINI('settings', 'RockColors', ConfigPath+CONFIG_FILE));
        BankSpots  := StrToTPA (ReadINI('settings', 'BankSpots',  ConfigPath+CONFIG_FILE));
        BankColors := StrToCTS2(ReadINI('settings', 'BankColors', ConfigPath+CONFIG_FILE));
        Result := True;
      end;

      procedure SaveConfig();
      var
        f: PtrInt;
      begin
        CreateDirectory(CONFIG_PATH);
        CreateDirectory(ConfigPath);

        GenerateMap(ConfigPath+CONFIG_MAP);
        CloseFile(CreateFile(ConfigPath+CONFIG_FILE));

        f := RewriteFile(Self.ConfigPath+CONFIG_FILE, True);
        WriteFileString(f, '[settings]'                     + #13#10);
        WriteFileString(f, 'BankPath   = '+ToStr(BankPath)  + #13#10);
        WriteFileString(f, 'RockSpots  = '+ToStr(RockSpots) + #13#10);
        WriteFileString(f, 'RockColors = '+ToStr(RockColors)+ #13#10);
        WriteFileString(f, 'BankSpots  = '+ToStr(BankSpots) + #13#10);
        WriteFileString(f, 'BankColors = '+ToStr(BankColors)+ #13#10);
        CloseFile(f);
      end;

    label
      START, QUERY_CONFIG;

    begin
      client2.Init(PluginPath);
      client2.GetIOManager.SetTarget2(GetRSAppletWnd(SMART.PID));

    START:
      r := Query('Do you wish to run setup?', ['Yes','No'], DefaultBox);
      if r = 'No' then
      begin QUERY_CONFIG:
        Self.ConfigPath := CONFIG_PATH + QueryStr('Name of config: ', DefaultBox) + '/';

        if not LoadConfig() then
          case Query('Failed to load config, try again?', ['Yes','No'], DefaultBox) of
            'Yes': goto QUERY_CONFIG;
            'No' : goto START;
          end;

        client2.Free();
        Exit();
      end;

      r := MessageBox('Preparing, please stand by...', DefaultBox);
      minimap.SetCompassAngle(0);
      RSW.Init('world.png');

      Query('Click the rocks you wish to mine...', ['OK'], DefaultBox);
      RockSpots := SetupLocations();

      Query('Click some colors for us to use...', ['OK'], DefaultBox);
      RockColors := SetupColors(RockSpots);

      if('Banking' = Query('Select style:', ['Banking','Powermining'], DefaultBox)) then
      begin
        Query('Please walk to your bank', ['OK'], DefaultBox);
        BankPath := RecordPath();

        Query('Click valid bankers, or booths...', ['OK'], DefaultBox);
        BankSpots := SetupLocations();

        Query('Click some colors for us to use...', ['OK'], DefaultBox);
        BankColors := SetupColors(BankSpots);
      end;

      Self.ConfigPath := CONFIG_PATH + QueryStr('Save config as: ', DefaultBox) + '/';
      SaveConfig();

      RSW.Free();
      client2.Free();
    end;


    begin
      NativeClient := GetNativeWindow();

      smart.EnableDrawing := True;
      srl.Setup([]);
      srl.Options := [soDebugAntiban];
      AddOnTerminate(@smart.Free);

      Bot.Init();
      Bot.Setup();

      RSW.Init(Bot.ConfigPath+CONFIG_MAP);
      AddOnTerminate(@RSW.Free);
      //RSW.MemScanEnabled := False;

      Bot.Run();
    end.


    Other notes:
    • Video will over time probably get outdated.
    • You can keep track over changes on my GitHub
    • Remember to be max zoomed out, and max brightness.
    • You can find things that needs, or might need a fix or adjustment in the source by searching for //XXX


    WARNING: Use at your own risk.
    Last edited by slacky; 07-12-2018 at 11:00 PM. Reason: Moved debugging to SRL [Update SRL]
    !No priv. messages please

  2. #2
    Join Date
    Aug 2007
    Location
    Colorado
    Posts
    7,421
    Mentioned
    268 Post(s)
    Quoted
    1442 Post(s)

    Default

    It's about time... It's great to see some life from the include and being put to use. This script is a great example of much of what SRL (OSR) provides as powerful tool for script-writers as well as showcasing its abilities. Just watching the video and skimming through the script it's obvious the variety of fields this script touches; it's very advanced at least in my opinion. Job very well done Slacky!

    I hope this sparks some other projects featuring this include.

    Current projects:
    [ AeroGuardians (GotR minigame), Motherlode Miner, Blast furnace ]

    "I won't fall in your gravity. Open your eyes,
    you're the Earth and I'm the sky..."


  3. #3
    Join Date
    Dec 2011
    Location
    East Coast, USA
    Posts
    4,231
    Mentioned
    112 Post(s)
    Quoted
    1869 Post(s)

    Default

    Very nice release. Could do without the WinAPI dependency but other than that it looks quite slick and functional.
    GitLab projects | Simba 1.4 | Find me on IRC or Discord | ScapeRune scripts | Come play bot ScapeRune!

    <BenLand100> we're just in the transitional phase where society reclassifies guns as Bad™ before everyone gets laser pistols

  4. #4
    Join Date
    Dec 2006
    Location
    Banville
    Posts
    3,914
    Mentioned
    12 Post(s)
    Quoted
    98 Post(s)

    Default

    I have been needing something to test new Simba versions with so this is appreciated. There are no antirandoms? Do the SRL antirandoms work anymore? Or, wait, can't all randoms be turned off or ignored?

    Like KeepBotting, I agree the dependency on WinAPI is a little odd, but at least this is a script that works.
    Last edited by R0b0t1; 12-18-2017 at 04:33 AM.
    The jealous temper of mankind, ever more disposed to censure than
    to praise the work of others, has constantly made the pursuit of new
    methods and systems no less perilous than the search after unknown
    lands and seas.

  5. #5
    Join Date
    Feb 2012
    Location
    Norway
    Posts
    995
    Mentioned
    145 Post(s)
    Quoted
    596 Post(s)

    Default

    If WinAPI makes my job easier, I will use the WinAPI.
    Last edited by slacky; 12-18-2017 at 06:05 AM.
    !No priv. messages please

  6. #6
    Join Date
    Sep 2014
    Location
    C:\Simba\
    Posts
    565
    Mentioned
    9 Post(s)
    Quoted
    71 Post(s)

    Default

    @R0b0t1; yeah all randoms can be ignored. Only Ironmen will ever solve those for Unobtainable Items™.
    Scratch that or else figuring out what an Ironman is will be yet another endless project of yours
    Last edited by Joopi; 12-18-2017 at 09:22 AM.
    Feel free to ask me any questions, I will do my best to answer them!

    Previously known as YouPee.

  7. #7
    Join Date
    Jun 2015
    Posts
    35
    Mentioned
    0 Post(s)
    Quoted
    9 Post(s)

    Default

    Thank you for your time.

    Will post an update!

  8. #8
    Join Date
    Jan 2012
    Location
    Sydney, Australia
    Posts
    877
    Mentioned
    12 Post(s)
    Quoted
    368 Post(s)

  9. #9
    Join Date
    Dec 2006
    Location
    Program TEXAS home of AUTOERS
    Posts
    7,934
    Mentioned
    26 Post(s)
    Quoted
    237 Post(s)

    Default

    Awesome and creative!

  10. #10
    Join Date
    Feb 2012
    Location
    Norway
    Posts
    995
    Mentioned
    145 Post(s)
    Quoted
    596 Post(s)

    Default

    I added some basic WriteLn progress info to it just so that people can keep tabs on it.

    And here's my first run after this addition (Mining and banking copper+tin at Varrock):
    Code:
    +-- STATS -----------------------------------------------------
    |- Trips / Drops       : 115
    |- Ores Mined          : 3237
    |- Experience Gained   : 55029
    |- Experience Per Hour : 9277
    |- Script Runtime      : 5 Hours, 55 Minutes and 53 Seconds
    +--------------------------------------------------------------
    Last edited by slacky; 01-05-2018 at 01:26 PM.
    !No priv. messages please

  11. #11
    Join Date
    Oct 2007
    Posts
    187
    Mentioned
    7 Post(s)
    Quoted
    61 Post(s)

    Default

    Nice release! Too bad I don't play OSRS :/

    You say "Create your own miner". Does that mean you need to script your own paths for mining other locations or...? I'm still not fully informed on how RSWalker works.

  12. #12
    Join Date
    Feb 2012
    Location
    Norway
    Posts
    995
    Mentioned
    145 Post(s)
    Quoted
    596 Post(s)

    Default

    Quote Originally Posted by klamor View Post
    You say "Create your own miner". Does that mean you need to script your own paths for mining other locations or...? I'm still not fully informed on how RSWalker works.
    No. The bot doesn't know of any locations. In the first 2 minutes of the video posted, I created a bot that runs at varrock east, including the path. The path for banking was generated automatically from running the setup. So, there isn't any scripting involved, just run the setup.


    RSWalker works much like SPS - you usually use a regular path making tool for paths, but this bot doesn't require that.
    Last edited by slacky; 01-06-2018 at 01:59 PM.
    !No priv. messages please

  13. #13
    Join Date
    Jan 2016
    Posts
    77
    Mentioned
    0 Post(s)
    Quoted
    44 Post(s)

    Default

    Looking at the video this looks awesome, wonder if you can configure this for woodcutting as well. I would assume it would be a bit more difficult since you cant depend on color change so much.

  14. #14
    Join Date
    Feb 2012
    Location
    Norway
    Posts
    995
    Mentioned
    145 Post(s)
    Quoted
    596 Post(s)

    Default

    Quote Originally Posted by Hellzonee View Post
    Looking at the video this looks awesome, wonder if you can configure this for woodcutting as well. I would assume it would be a bit more difficult since you cant depend on color change so much.
    That can probably be done, but would require a number of tweaks and additions, and disabling certain features. I might look into making one based off the core of this if I find time for it.
    Last edited by slacky; 01-10-2018 at 02:09 PM.
    !No priv. messages please

  15. #15
    Join Date
    Oct 2007
    Posts
    187
    Mentioned
    7 Post(s)
    Quoted
    61 Post(s)

    Default

    Quote Originally Posted by slacky View Post
    No. The bot doesn't know of any locations. In the first 2 minutes of the video posted, I created a bot that runs at varrock east, including the path. The path for banking was generated automatically from running the setup. So, there isn't any scripting involved, just run the setup.


    RSWalker works much like SPS - you usually use a regular path making tool for paths, but this bot doesn't require that.
    My bad, I didn't actually get a chance to watch the video until just now. Looks amazing! Can't wait to see what you do with it next.

  16. #16
    Join Date
    Apr 2007
    Posts
    8
    Mentioned
    0 Post(s)
    Quoted
    1 Post(s)

    Default

    Thanks for the release, looks promosing!

  17. #17
    Join Date
    Jul 2015
    Posts
    13
    Mentioned
    0 Post(s)
    Quoted
    11 Post(s)

    Default

    Hello, I am trying to use your universal miner script. I am getting the error at bottom Exception in Script: Plugin(libLayer32) has not been found
    Mind helping out? I am simply wanting to power mine.

    EDIT: Have used simba many years ago. Just got back to OSRS last week. New computer as well. Thanks
    Last edited by Cooked Terd; 01-22-2018 at 07:10 AM.

  18. #18
    Join Date
    Feb 2012
    Location
    Norway
    Posts
    995
    Mentioned
    145 Post(s)
    Quoted
    596 Post(s)

    Default

    Quote Originally Posted by Cooked Terd View Post
    Hello, I am trying to use your universal miner script. I am getting the error at bottom Exception in Script: Plugin(libLayer32) has not been found
    My bad, left some traces of a test I did in the script. Fixed now
    Hopefully there aren't any other bugs left.
    !No priv. messages please

  19. #19
    Join Date
    Jul 2015
    Posts
    13
    Mentioned
    0 Post(s)
    Quoted
    11 Post(s)

    Default

    Quote Originally Posted by slacky View Post
    My bad, left some traces of a test I did in the script. Fixed now
    Hopefully there aren't any other bugs left.
    Exception in Script: Unable to find file 'SRL/OSR.simba' used from 'C:\Simba\Scripts\Universal_Miner_V020.simba'

  20. #20
    Join Date
    Feb 2012
    Location
    Norway
    Posts
    995
    Mentioned
    145 Post(s)
    Quoted
    596 Post(s)

    Default

    Quote Originally Posted by Cooked Terd View Post
    Exception in Script: Unable to find file 'SRL/OSR.simba' used from 'C:\Simba\Scripts\Universal_Miner_V020.simba'
    You wanna read the requirements, and grab the files needed.
    !No priv. messages please

  21. #21
    Join Date
    Jul 2015
    Posts
    13
    Mentioned
    0 Post(s)
    Quoted
    11 Post(s)

    Default

    Quote Originally Posted by slacky View Post
    You wanna read the requirements, and grab the files needed.
    Thought I had done all of that, i'll double check again. Must not have grabbed something or put it in right folder. Thanks.
    EDIT: Ive got RSWalker and SRL-OSR and srl6 in my includes folder, the leak fixes in my Simba folder, updated srl. Still same. Where is the SRL/OSR simba fie I am missing? I know this is bothersome to you but help would be appreciative. Followed the OSRS setup guide that is stickied.
    Last edited by Cooked Terd; 01-22-2018 at 07:57 AM.

  22. #22
    Join Date
    Feb 2012
    Location
    Norway
    Posts
    995
    Mentioned
    145 Post(s)
    Quoted
    596 Post(s)

    Default

    Quote Originally Posted by Cooked Terd View Post
    Thought I had done all of that, i'll double check again. Must not have grabbed something or put it in right folder. Thanks.
    The SRL include files is expected to be placed in C:\Simba\Includes\SRL\
    !No priv. messages please

  23. #23
    Join Date
    Jul 2015
    Posts
    13
    Mentioned
    0 Post(s)
    Quoted
    11 Post(s)

    Default

    Quote Originally Posted by slacky View Post
    The SRL include files is expected to be placed in C:\Simba\Includes\SRL\
    Man I know I'm being a pain. Which file exactly? Currently it is the srl file in your thread. I put them to Includes folder. Ive got AeroLib, Reflection, RSWalker, SRL-OSR then the ones that come upon download. Sorry to be such a bother. Its been years since ive worked with simba and I wasn't too great then but this is first time ive looked at any of this stuff in awhile.
    Last edited by Cooked Terd; 01-22-2018 at 08:14 AM.

  24. #24
    Join Date
    May 2012
    Location
    Glorious Nippon
    Posts
    1,011
    Mentioned
    50 Post(s)
    Quoted
    505 Post(s)

    Default

    Quote Originally Posted by Cooked Terd View Post
    Man I know I'm being a pain. Which file exactly? Currently it is the srl file in your thread. I put them to Includes folder. Ive got AeroLib, Reflection, RSWalker, SRL-OSR then the ones that come upon download. Sorry to be such a bother. Its been years since ive worked with simba and I wasn't too great then but this is first time ive looked at any of this stuff in awhile.
    Download SRL from the GitHub linked in the OP
    Unzip it and rename the folder to 'SRL'
    Move the folder into Simba's Includes folder.
    Finished.

  25. #25
    Join Date
    Jul 2015
    Posts
    13
    Mentioned
    0 Post(s)
    Quoted
    11 Post(s)

    Default

    Quote Originally Posted by Citrus View Post
    Download SRL from the GitHub linked in the OP
    Unzip it and rename the folder to 'SRL'
    Move the folder into Simba's Includes folder.
    Finished.
    Did exactly that. Same error line I'm getting. I'm not getting what I'm doing wrong. Obviously something. Downloaded the SRL link, extracted it, renamed to SRL, moved the folder to the Includes folder. Same error when trying to run script.

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 not post replies
  • You may not post attachments
  • You may not edit your posts
  •