All pastes #1460221 Raw Edit

WaBiCrab

public text v1 · immutable
#1460221 ·published 2009-06-14 19:01 UTC
rendered paste body
Program WaBiCrab;
{.include SRL/SRL/Misc/SMART.scar}
{.include SRL/SRL.scar}
{.include SRL/SRL/Misc/WorldSwitcher.scar}
{.include SRL/SRL/Reflection/Reflection.scar}

Var
  CrabSpot, DeAgressiveWalk : TPointArray;
  MainSpot, SpecialSpot, BackupSpot : TPoint;
  NoFight, HPLvl, HP, Running, SkipTime, CurrTraining, ReportLength, Combat, _SleepFor : Integer;
  Stats, ToLvls : Array [0..3] Of Integer;
  _NPCWeAreFighting, NPCWeWereFighting : TNPC;
  Me : TMe;
  DoNP : Boolean;

Const
  {Debug/Etc Setup}
  Debug = True; //Use debugging? [VERY HEAVY]
  {///////////////}

  {SMART Setup}
  SMARTWorld = 53; //World to load SMART in.
  SMARTSigned = True; //True = Signed SMART, False = Unsigned SMART.
  Hop = True; //Hop worlds is someone is also on the spot and attacking?
  HopStart = True; //Hop worlds to SMARTWorld at start of script?
  {///////////}

  {Regenerating Setup}
  UsePanic = False; //Use this? (explanantion at MinHP)
  MinHP = 15; //If HP is below this: Log out/regenerate it (set MinRegen to true!!)
  MinRegen = False; //Run away to safe and regen HP on MinHP.
  {//////////////////}

  {Food Setup}
  PickWeed = False; //Take seaweed?
  UseFood = False; //Use food?
  FoodID = 7497; //The ID of the food you are using.
  FoodHeal = 16; //How much does the food heal?
  {//////////}

  {Sleeping Setup}
  Sleeper = True; //Use sleeping?
  SleepTime = 20; //Sleep every (xx) minutes, random is added.
  SleepFor = 0; //Sleep for (xx) minutes (0 minutes = short log-out-and-in).
  {//////////////}

Procedure _Status(Txt: String);
Begin
  If GetStatus <> Txt Then
    Status(Txt);
End;

Procedure DeclarePlayers;
Begin
  _Status('DeclarePlayers');
  CurrentPlayer  := 0; // Starting player
  HowManyPlayers := 1; // How many players in total?
  NumberOfPlayers(HowManyPlayers);

  Players[0].Name        := '';              // Username
  Players[0].Pass        := '';              // Password
  Players[0].Nick        := '';              // Nickname, 3 - 4 letters of username
  Players[0].Active      := True;            // Use this player?
  Players[0].BoxRewards  := ['XP', 'xp'];    // Reward box reward uptext (default = lamp)
  Players[0].Integers[0] := 0;               // Attack level to train (0 = don't train)
  Players[0].Integers[1] := 99;              // Strength/Ranging level to train (0 = don't train)
  Players[0].Integers[2] := 0;               // Defence level to train (0 = don't train)
  Players[0].Strings[0]  := 'ranging';       // What kind of weapon? ('melee' / 'ranging')
                                             // STATS ARE TRAINED IN THIS ORDER: ATTACK ~ STRENGTH/RANGING ~ DEFENCE.
End;

Function DoSpecialSpot: Boolean; Forward;

Procedure Write(Txt, TxtType: String);
Begin
  _Status('Write');
  If Debug Then
    WriteLn('[DEBUG]['+ TxtType +']: '+ Txt);
End;

Function GetHP(MM: Boolean): Integer;
Begin
  If Not LoggedIn Then
    Exit;
  _Status('GetHP');
  Case MM Of
    True: Result := R_GetMMLevels('hitpoints');
    False: Result := GetMySkill(3, True);
  End;
End;

{*******************************************************************************
Function WalkToTileEx(Tile: TPoint): Boolean;
By: Wizzup and TheGuyWhoGotOn
Description: Walks to the tile using minimap.
*******************************************************************************}
Function WalkToTileEx(Tile: TPoint): Boolean;

Var
   wTile: TPoint;
   t: Integer;

Begin
  If Not LoggedIn Then
    Exit;
  _Status('WalkToTileEx');
  Tile := Point(Tile.X, Tile.Y);
  wTile := TileToMM(Tile);
  If Not rs_OnMiniMap(wTile.X, wTile.Y) Then
    Exit;
  MFNF(wTile.x, wTile.y, -1, -1);
  Wait(RandomRange(80, 100));
  t := getsystemtime;
  FFlag(10);
  Wait(500 + Random(250));
  Result := (GetSystemTime - t) < 60000;
End;

Function ConvertTimeEx(MS : Integer): String;
Var
  h, m, s : Integer;
Begin
  ConvertTime(MS, h, m, s);
  If (h > 0) And (m > 0) And (s > 0) Then
    Result := IntToStr(h) +' Hour[s] and '+ IntToStr(m) +' Minute[s] and ' + IntToStr(s) +' Second[s]'
  Else
  If (m > 0) And (s > 0) Then
    Result := IntToStr(m) +' Minute[s] and ' + IntToStr(s) +' Second[s]'
  Else
  If s > 0 Then
    Result := IntToStr(s) +' Second[s]'
  Else
    Result := '0 Second[s]'
End;

{*******************************************************************************
Function R_XpTillNextLevelEx(Skill : Integer): Integer;
By: Floor66
Description: Returns the XP to the next level of Skill in a different way.
*******************************************************************************}
Function R_XpTillNextLevelEx(Skill : Integer): Integer;
Var
  CurrLevel, i, x : Integer;
Begin
  CurrLevel := GetMySkill(Skill, True);
  For i := 1 To CurrLevel Do
    x := x + Trunc(i + 300 * Pow(2, i / 7));
  Result := ((x / 4) - GetMySkill(Skill, False));
End;

Function GetNPCAt(Tile : TPoint): TNPC;
Var
  N : Array Of TNPC;
  i : Integer;
Begin
  If Not LoggedIn Then
    Exit;
  _Status('GetNPCAt');
  N := GetNPCs;
  If Length(N) = 0 Then
    Exit;
  For i := 0 To High(N) Do
  Begin
    If N[i].Tile.X = Tile.X Then
      If N[i].Tile.Y = Tile.Y Then
        Result := N[i];
  End;
End;

Function NPCWeAreFighting: Boolean;
Begin
  If Not LoggedIn Then
    Exit;
  _Status('NPCWeAreFighting');
  AreWeInteracting(NPCWeWereFighting);
  Result := (_NPCWeAreFighting.Index <> NPCWeWereFighting.Index);
End;

Procedure AntiBan;
Begin
  If Not LoggedIn Then
    Exit;
  _Status('AntiBan');
  Case Random(175) Of
    0..30: Begin
             SleepAndMoveMouse(3500 + Random(1500));
             Inc(Players[CurrentPlayer].Integers[10]);
           End;
    31..35: Begin
              RandomMovement;
              Inc(Players[CurrentPlayer].Integers[10]);
            End;
    36..40: Begin
              GameTab(1 + Random(12));
              Inc(Players[CurrentPlayer].Integers[10]);
            End;
  End;
  MakeCompass('N');
End;

Function DoRandoms: Boolean;
Begin
  If R_FindRandoms Then
    Result := True;
  If FindNormalRandoms Then
    Result := True;
  If FindDead Then
    DoNP := True;
End;

Function Calibrate: Boolean;
Begin
  If DoRandoms Then
    Exit;
  Me := GetMe;
  If (Me.Tile.x > 2552) Or (Me.Tile.y < 3741) Then
  Begin
    Write('Player is completely lost.', 'ERROR');
    Result := False;
    DoNP := True;
    Exit;
  End;
  If Not WalkToTileEx(DeAgressiveWalk[0]) Then
  Begin
    Write('DeAgressiveWalk[0] (Calibrate) failed.', 'ERROR');
    If Not WalkToTileEx(DeAgressiveWalk[1]) Then
    Begin
      Write('DeAgressiveWalk[1] (Calibrate) failed.', 'ERROR');
      If Not WalkToTileEx(DeAgressiveWalk[2]) Then
      Begin
        Write('DeAgressiveWalk[2] (Calibrate) failed.', 'ERROR');
        Result := False;
        DoNP := True;
        Exit;
      End Else
      Begin
        If Not WalkToTileEx(DeAgressiveWalk[1]) Then
        Begin
          Write('DeAgressiveWalk[1] (Calibrate) failed.', 'ERROR');
          Result := False;
          DoNP := True;
          Exit;
        End Else
        Begin
          If Not WalkToTileEx(DeAgressiveWalk[0]) Then
          Begin
            Write('DeAgressiveWalk[0] (Calibrate) failed.', 'ERROR');
            Result := False;
            DoNP := True;
            Exit;
          End Else
          Begin
            Result := True;
            Inc(Players[CurrentPlayer].Integers[11]);
            DoSpecialSpot;
            Exit;
          End;
        End;
      End;
    End Else
    Begin
      If Not WalkToTileEx(DeAgressiveWalk[0]) Then
      Begin
        Write('DeAgressiveWalk[0] (Calibrate) failed.', 'ERROR');
        Result := False;
        DoNP := True;
        Exit;
      End Else
      Begin
        Result := True;
        Inc(Players[CurrentPlayer].Integers[11]);
        DoSpecialSpot;
        Exit;
      End;
    End;
  End Else
  Begin
    Result := True;
    Inc(Players[CurrentPlayer].Integers[11]);
    DoSpecialSpot;
    Exit;
  End;
End;

procedure NextPlayer2(Active: Boolean);
begin
  if RandomPlayer then
    RandomNextPlayer(Active)
  else
  begin
    WriteLn('NextPlayer2(Active: ' + BoolToStr(Active)+ ');');
    Players[CurrentPlayer].Active := Active;
    Logout;
    if (SRL_Procs[srl_OnNextPlayer] <> nil) then
      SRL_Procs[srl_OnNextPlayer]();
    PlayerCurTime := (GetSystemTime div 1000);
    Players[CurrentPlayer].Worked := Players[CurrentPlayer].Worked +
      ((PlayerCurTime - PlayerStartTime) / 60);
    CurrentPlayer := (CurrentPlayer + 1) mod Length(Players);
    while Players[CurrentPlayer].Active = False do
    begin
      CurrentPlayer := (CurrentPlayer + 1) mod Length(Players);
      if (AllPlayersInactive) then
        TerminateScript;
    end;
    SRL_Logs := SRL_Logs + 1;
    LoginPlayer;
  end;
end;

Procedure ToMain;
Begin
  If Not LoggedIn Then
    Exit;
  _Status('ToMain');
  DoRandoms;
  Me := GetMe;
  If (Me.Tile.X <> MainSpot.x) Or (Me.Tile.y <> MainSpot.y) Then
  Begin
    Write('Walking to Main spot.', 'MESSAGE');
    If Not WalkToTileEx(MainSpot) Then
    Begin
      Write('Failed walking to Main spot.', 'ERROR');
      If Not Calibrate Then
        Exit
      Else
      Begin
        ToMain;
        Exit;
      End;
    End Else
      Write('At Main spot.', 'MESSAGE');
  End;
End;

Function AllLeveled: Boolean;
Var
  i, c : Integer;
Begin
  For i := 0 To 2 Do
  Begin
    If Players[CurrentPlayer].Integers[i] = 0 Then
      Inc(c);
  End;
  If c = 3 Then
    Result := True;
End;

Function CrabsRocked: Integer;
Var
  N : Array Of TNPC;
  xs : TIntegerArray;
  ys : TIntegerArray;
  i : Integer;
Begin
  If Not LoggedIn Then
    Exit;
  _Status('CrabsRocked');
  ToMain;
  N := GetNPCs;
  SetLength(xs, Length(N));
  SetLength(ys, Length(N));
  For i := 0 To High(N) Do
    If (N[i].NPCType = 1268) And (N[i].Tile.x > 2510) And (N[i].Tile.x < 2516) Then
      Inc(Result);
End;

Procedure Progress;
Begin
  _Status('Progress');
  ClearReport;
  AddToReport(' '+ Replicate('-', (ReportLength + 2)));
  AddToReport('| '+ Padr('WaBiCrab by Floor66:', ReportLength) +' |');
  AddToReport('| '+ Padr('Running for '+ TimeRunning +'.', ReportLength) +' |');
  AddToReport(' '+ Replicate('-', (ReportLength + 2)));
  AddToReport('| '+ Padr('Killed '+ IntToStr(Players[CurrentPlayer].Integers[3]) +' Rock Crab[s].', ReportLength) +' |');
  AddToReport('| '+ Padr('Re-Agressive''d '+ IntToStr(Players[CurrentPlayer].Integers[4]) +' Time[s].', ReportLength) +' |');
  AddToReport('| '+ Padr('Ate food '+ IntToStr(Players[CurrentPlayer].Integers[5]) +' Time[s].', ReportLength) +' |');
  AddToReport('| '+ Padr('Hopped worlds '+ IntToStr(Players[CurrentPlayer].Integers[6]) +' Time[s].', ReportLength) +' |');
  AddToReport('| '+ Padr('Regenerated HP '+ IntToStr(Players[CurrentPlayer].Integers[7]) +' Time[s].', ReportLength) +' |');
  AddToReport('| '+ Padr('Slept '+ IntToStr(Players[CurrentPlayer].Integers[8]) +' Time[s].', ReportLength) +' |');
  AddToReport('| '+ Padr('Slept a total of '+ ConvertTimeEx(Players[CurrentPlayer].Integers[9]) +'.', ReportLength) +' |');
  AddToReport('| '+ Padr('Did AntiBan '+ IntToStr(Players[CurrentPlayer].Integers[10]) +' Time[s].', ReportLength) +' |');
  AddToReport('| '+ Padr('Calibrated '+ IntToStr(Players[CurrentPlayer].Integers[11]) +' Time[s].', ReportLength) +' |');
  AddToReport(' '+ Replicate('-', (ReportLength + 2)));
  AddToReport('| '+ Padr(Capitalize(Players[CurrentPlayer].Name) +' | Combat level '+ IntToStr(Combat) +' | Stats:', ReportLength) +' |');
  AddToReport('| '+ Padr('Hitpoints level: '+ IntToStr(Stats[3]) +' | ['+ IntToStr(ToLvls[3]) +'xp to Level].', ReportLength) +' |');
  If Players[CurrentPlayer].Strings[0] = 'melee' Then
  Begin
    AddToReport('| '+ Padr('Attack level: '+ IntToStr(Stats[0]) +' | ['+ IntToStr(ToLvls[0]) +'xp to Level].', ReportLength) +' |');
    AddToReport('| '+ Padr('Strength level: '+ IntToStr(Stats[1]) +' | ['+ IntToStr(ToLvls[1]) +'xp to Level].', ReportLength) +' |')
  End Else
    AddToReport('| '+ Padr('Ranging level: '+ IntToStr(Stats[1]) +' | ['+ IntToStr(ToLvls[1]) +'xp to Level].', ReportLength) +' |');
  AddToReport('| '+ Padr('Defence level: '+ IntToStr(Stats[2]) +' | ['+ IntToStr(ToLvls[2]) +'xp to Level].', ReportLength) +' |');
  AddToReport(' '+ Replicate('-', (ReportLength + 2)));
End;

Function DoSpecialSpot: Boolean;
Var
  t : Integer;
  N : TNPC;
Begin
  If Not LoggedIn Then
    Exit;
  _Status('DoSpecialSpot');
  DoRandoms;
  Me := GetMe;
  If (Me.Tile.X = MainSpot.x) And (Me.Tile.y = MainSpot.y) Then
  Begin
    Result := True;
    Exit;
  End;
  Write('Walking to the Main Spot.', 'MESSAGE');
  If Not TileOnMM(MainSpot) Then
  Begin
    Write('Couldn''t find the Main Spot.', 'ERROR');
    If Not Calibrate Then
      Exit
    Else
    Begin
      DoSpecialSpot;
      Exit;
    End;
  End;
  Me := GetMe;
  If Me.Tile.X >= SpecialSpot.X Then
  Begin
    Write('Walking to SpecialSpot to prevent crab-popping.', 'MESSAGE');
    If Not WalkToTileEx(SpecialSpot) Then
    Begin
      Write('Walking to Special spot failed.', 'ERROR');
      If Not Calibrate Then
        Exit;
    End Else
      Write('At Special spot.', 'SUCCESS');
    N := GetNPCAt(CrabSpot[2]);
    If N.NPCType < 1265 Then
    Begin
      If Not WalkToTileEx(MainSpot) Then
      Begin
        Write('Walking to Main spot failed.', 'ERROR');
        If Not Calibrate Then
          Exit
        Else
        Begin
          DoSpecialSpot;
          Exit;
        End;
      End Else
      Begin
        Write('At Main spot.', 'SUCCESS');
        Result := True;
        Exit;
      End;
    End;
    Write('Waiting for a crab to attack.', 'MESSAGE');
    MarkTime(t);
    Repeat
      Wait(10);
      Me := GetMe;
      If Me.InFight Then
      Begin
        Write('A crab attacked.', 'SUCCESS');
        Result := True;
        AreWeInteracting(_NPCWeAreFighting);
        Break;
      End;
      If TimeFromMark(t) >= (5 * 1000) Then
      Begin
        Write('Not being attacked by crab.', 'SUCCESS');
        Result := True;
        Break;
      End;
    Until(False);
    If Result Then
    Begin
      If Not WalkToTileEx(MainSpot) Then
      Begin
        Write('Walking to Main spot failed.', 'ERROR');
        If Not Calibrate Then
        Begin
          Result := False;
          Exit;
        End Else
        Begin
          DoSpecialSpot;
          Exit;
        End;
      End Else
        Write('At Main spot.', 'SUCCESS');
    End;
  End Else
  Begin
    Write('Walking to Main spot.', 'MESSAGE');
    If Not WalkToTileEx(MainSpot) Then
    Begin
      Write('Walking to Main spot failed.', 'ERROR');
      If Not Calibrate Then
      Begin
        Result := False;
        Exit;
      End Else
      Begin
        DoSpecialSpot;
        Exit;
      End;
    End Else
      Write('At Main spot.', 'SUCCESS');
  End;
End;

Function FindSeaweed: Boolean;
Var
  Tga : Array Of TGroundItem;
  i : Integer;
  j : TPoint;
Begin
  If Not LoggedIn Then
    Exit;
  If Not PickWeed Then
    Exit;
  If InvFull Then
    Exit;
  _Status('FindSeaweed');
  DoRandoms;
  FindGroundItems(Tga, [403], 3);
  For i := 0 To High(Tga) Do
  Begin
    If Tga[i].ID = 403 Then
    Begin
      Retaliate(False);
      Write('Edible seaweed found on ground, picking up.', 'MESSAGE');
      j := TileToMS(Tga[i].Tile, 0);
      Mouse(j.x, j.y, 4, 4, False);
      Wait(100 + Random(50));
      If ChooseOption('dible') Then
      Begin
        Write('Picked up an Edible seaweed.', 'SUCCESS');
        Wait(1500 + Random(500));
      End Else
        Write('Failed to pick up Edible seaweed.', 'ERROR');
    End;
  End;
  Retaliate(True);
  If WalkToTileEx(MainSpot) Then
    Result := True
  Else
    Write('Failed to walk back to Main spot.', 'ERROR');
  If Not Result Then
    Write('No seaweed found on ground.', 'MESSAGE');
End;

Function Eat: Boolean;
Var
  i, tID, x, j : Integer;
  Item : TItemArray;
  t : TPoint;
Begin
  If Not LoggedIn Then
    Exit;
  If Not UseFood Then
    Exit;
  _Status('Eat');
  DoRandoms;
  GameTab(4);
  HP := GetHP(True);
  If (HPLvl - 4) >= HP Then
  Begin
    tID := 404;
    x := 4;
  End Else If (HPLvl - FoodHeal) >= HP Then
  Begin
    tID := FoodID;
    x := FoodHeal;
  End Else
  Begin
    Result := True;
    Write('No eating needed.', 'MESSAGE');
    Exit;
  End;
  Item := GetInventoryItemsEx;
  For i := 0 To High(Item) Do
  Begin
    If (Item[i].ID = tID) Then
    Begin
      HP := GetHP(True);
      If (HPLvl - x) >= HP Then
      Begin
        t := ItemCoords(i + 1);
        Mouse(t.x, t.y, 3, 3, True);
        Inc(Players[CurrentPlayer].Integers[5]);
        j := GetHP(True);
        While HP = j Do
          j := GetHP(True);
        HP := GetHP(True);
        If (HPLvl - x) >= HP Then
        Begin
          Result := True;
          Write('Eating another.', 'MESSAGE');
          Eat;
          Exit;
        End Else
          Exit;
      End;
    End;
  End;
  Write('No food eaten, but there is need to eat.', 'ERROR');
  Result := False;
End;

Procedure _Hop(S : Boolean);
Var
  Ws : TIntegerArray;
  j : Integer;
Begin
  If Not SMARTSigned Then
    Exit;
  If Not S Then
  Begin
    If Not Hop Then
      Exit;
  End;
  _Status('_Hop');
  Ws := [ //Some empty member worlds.
         99, 132, 48, 144, 114,
         46, 31, 39, 27, 91,
         42, 151, 100, 110, 70,
         68, 66, 130, 51, 60,
         156, 164
        ]
  Logout;
  If S Then
  Begin
    j := SMARTWorld
    If Not SelectWorld(j) Then
      Write('Failed to hop.', 'ERROR')
    Else
      Write('Hopped to World '+ IntToStr(j) +'.', 'SUCCESS');
  End Else
  Begin
    j := Random(Length(Ws));
    If Not SelectWorld(Ws[j]) Then
      Write('Failed to hop.', 'ERROR')
    Else
      Write('Hopped to World '+ IntToStr(Ws[j]) +'.', 'SUCCESS');
  End;
End;

Procedure CheckPlayers;
Var
  T : Array Of TPlayer;
  i : Integer;
Begin
  If Not LoggedIn Then
    Exit;
  If Not Hop Then
    Exit;
  _Status('CheckPlayers');
  DoRandoms;
  T := GetPlayers;
  If Length(T) = 0 Then
    Exit;
  For i := 0 To High(T) Do
  Begin
    If T[i].Tile.X = MainSpot.x Then
      If T[i].Tile.Y = MainSpot.Y Then
        If T[i].Animation <> -1 Then
        Begin
          Write('Someone is on the Main spot.', 'MESSAGE');
          If Not WalkToTileEx(BackupSpot) Then
          Begin
            Write('Walking to Backup spot failed.', 'ERROR');
            If Not Calibrate Then
              Exit
            Else
            Begin
              CheckPlayers;
              Exit;
            End;
          End Else
          Begin
            Write('Hopping worlds.', 'MESSAGE');
            Me := GetMe;
            While Me.InFight Do
            Begin
              Wait(10);
              Me := GetMe;
            End;
            _Hop(False);
            Inc(Players[CurrentPlayer].Integers[6]);
            LoginPlayer;
            SetRun(True);
            SetAngle(True);
            MakeCompass('N');
            DoSpecialSpot;
          End;
        End;
  End;
End;

Procedure _Sleep;
Var
  Time : Integer;
Begin
  If Not Sleeper Then
    Exit;
  If TimeFromMark(Running) >= SkipTime Then
  Begin
    MarkTime(Running);
    If Not WalkToTileEx(BackupSpot) Then
      Write('Walking to Backup spot failed.', 'ERROR')
    Else
    Begin
      Write('At Backup spot.', 'MESSAGE');
      Me := GetMe;
      While Me.InFight Do
      Begin
        Wait(10);
        Me := GetMe;
      End;
      Logout;
      If SleepFor = 0 Then
        Time := Random(10000)
      Else
        Time := _SleepFor + Random(20000);
      Inc(Players[CurrentPlayer].Integers[8]);
      IncEx(Players[CurrentPlayer].Integers[9], Time);
      Wait(Time);
      LoginPlayer;
      SetRun(True);
      SetAngle(True);
      MakeCompass('N');
      DoSpecialSpot;
    End;
  End;
End;

Procedure GetStats;
Begin
  //Setup training:
  If Not IsAutoRetaliate Then
    Retaliate(True);
  Combat := GetMe.Combat;
  HPLvl := GetHP(False);
  If Players[CurrentPlayer].Strings[0] = 'melee' Then
  Begin
    Stats[0] := GetMySkill(0, True);
    Stats[1] := GetMySkill(2, True);
    ToLvls[0] := R_XpTillNextLevelEx(0);
    ToLvls[1] := R_XpTillNextLevelEx(2);
  End Else
  Begin
    Stats[1] := GetMySkill(4, True);
    ToLvls[1] := R_XpTillNextLevelEx(4);
  End;
  Stats[2] := GetMySkill(1, True);
  Stats[3] := GetMySkill(3, True);
  ToLvls[2] := R_XpTillNextLevelEx(1);
  ToLvls[3] := R_XpTillNextLevelEx(3);
End;

Procedure OnKill;
Begin
  If Not LoggedIn Then
    Exit;
  _Status('OnKill');
  Write('Killed a crab.', 'SUCCESS');
  Inc(Players[CurrentPlayer].Integers[3]);
  DoRandoms;
  FindSeaweed;
  Eat;
  GetStats;
  Progress;
  CheckPlayers;
  ToMain;
  _Sleep;
End;

Procedure CheckPanic;
Begin
  If Not LoggedIn Then
    Exit;
  If Not UsePanic Then
    Exit;
  _Status('CheckPanic');
  HP := GetHP(True);
  DoRandoms;
  If HP > MinHP Then
    Exit;
  If Eat Then
    Exit;
  If Not MinRegen Then
  Begin
    If HP <= MinHP Then
    Begin
      Write('HP is critical, running away and logging out.', 'CRITICAL');
      If Not WalkToTileEx(DeAgressiveWalk[0]) Then
        Write('DeAgressiveWalk[0] (CheckPanic) failed.', 'ERROR')
      Else
        Write('DeAgressiveWalk[0] (CheckPanic) succeeded.', 'SUCCESS');
      If Not WalkToTileEx(DeAgressiveWalk[1]) Then
        Write('DeAgressiveWalk[1] (CheckPanic) failed.', 'ERROR')
      Else
        Write('DeAgressiveWalk[1] (CheckPanic) succeeded.', 'SUCCESS');
      Me := GetMe;
      While Me.InFight Do
      Begin
        Wait(10);
        Me := GetMe;
      End;
      Wait(4000 + Random(2500));
      DoNP := True;
      Exit;
    End;
  End Else
  Begin
    Write('Going to regenerate HP.', 'MESSAGE');
    If Not WalkToTileEx(DeAgressiveWalk[0]) Then
      Write('DeAgressiveWalk[0] (CheckPanic) failed.', 'ERROR')
    Else
      Write('DeAgressiveWalk[0] (CheckPanic) succeeded.', 'SUCCESS');
    If Not WalkToTileEx(DeAgressiveWalk[1]) Then
      Write('DeAgressiveWalk[1] (CheckPanic) failed.', 'ERROR')
    Else
      Write('DeAgressiveWalk[1] (CheckPanic) succeeded.', 'SUCCESS');
    Me := GetMe;
    While Me.InFight Do
    Begin
      Wait(10);
      Me := GetMe;
    End;
    Wait(4000 + Random(2500));
    While HP < HPLvl Do
    Begin
      Wait(100 + Random(500));
      HP := GetHP(True);
      If Random(50) = 3 Then
        AntiBan;
      R_FindRandoms;
      FindNormalRandoms;
      If Not LoggedIn Then
      Begin
        LoginPlayer;
        SetRun(True);
        SetAngle(True);
        MakeCompass('N');
      End;
    End;
    Inc(Players[CurrentPlayer].Integers[7]);
    MarkTime(Running);
    DoSpecialSpot;
  End;
End;

Function CatchALooseOne: Boolean;
Var
  N : TNPC;
  t : TPoint;
  i : Integer;
Begin
  If Not LoggedIn Then
    Exit;
  _Status('CatchALooseOne');
  DoRandoms;
  Me := GetMe;
  If Me.InFight Then
    Exit;
  If FindNPC('Rock Crab', N) Then
  Begin
    If Not TileOnMS(N.Tile, 0) Then
      Exit;
    If N.InFight Then
      Exit;
    For i := 0 To High(CrabSpot) Do
    Begin
      If (N.Tile.x = CrabSpot[i].x) And (N.Tile.y = CrabSpot[i].y) Then
        Exit;
    End;
    Me := GetMe;
    If Me.InFight Then
      Exit;
    Write('Found a loose crab.', 'SUCCESS');
    DoRandoms;
    t := TileToMS(N.Tile, 0);
    Mouse(t.x, t.y, 3, 3, False);
    Wait(100 + Random(50));
    If Not ChooseOption('ttack') Then
      Exit;
    Me := GetMe;
    While Not Me.InFight Do
    Begin
      Wait(10);
      Me := GetMe;
      DoRandoms;
      CheckPanic;
    End;
    Write('Attacked a crab.', 'SUCCESS');
  End;
  AreWeInteracting(_NPCWeAreFighting);
  While Me.InFight Do
  Begin
    Wait(10);
    DoRandoms;
    CheckPanic;
    Me := GetMe;
    If (Not Me.InFight) Or NPCWeAreFighting Then
    Begin
      Result := True;
      OnKill;
      Exit;
    End;
  End;
End;

Procedure NotAgressive;
Begin
  If Not LoggedIn Then
    Exit;
  _Status('NotAgressive');
  DoRandoms;
  Write('Getting the crabs to attack.', 'MESSAGE');
  If Not WalkToTileEx(DeAgressiveWalk[0]) Then
  Begin
    Write('DeAgressiveWalk[0] failed.', 'ERROR');
    If Not Calibrate Then
      Exit
    Else
    Begin
      NotAgressive;
      Exit;
    End;
  End Else
    Write('DeAgressiveWalk[0] succeeded.', 'SUCCESS');
  If Not WalkToTileEx(DeAgressiveWalk[1]) Then
  Begin
    Write('DeAgressiveWalk[1] failed.', 'ERROR');
    If Not Calibrate Then
      Exit
    Else
    Begin
      NotAgressive;
      Exit;
    End;
  End Else
    Write('DeAgressiveWalk[1] succeeded.', 'SUCCESS');
  If Not WalkToTileEx(DeAgressiveWalk[2]) Then
  Begin
    Write('DeAgressiveWalk[2] failed.', 'ERROR');
    If Not Calibrate Then
      Exit
    Else
    Begin
      NotAgressive;
      Exit;
    End;
  End Else
    Write('Finished walking to the end, now walking back.', 'SUCCESS');

  If Not WalkToTileEx(DeAgressiveWalk[1]) Then
  Begin
    Write('DeAgressiveWalk[1] (Back) failed.', 'ERROR');
    If Not Calibrate Then
      Exit
    Else
    Begin
      NotAgressive;
      Exit;
    End;
  End Else
    Write('DeAgressiveWalk[1] (Back) succeeded.', 'SUCCESS');
  If Not WalkToTileEx(DeAgressiveWalk[0]) Then
  Begin
    Write('DeAgressiveWalk[0] (Back) failed.', 'ERROR');
    If Not Calibrate Then
      Exit
    Else
    Begin
      NotAgressive;
      Exit;
    End;
  End Else
    Write('DeAgressiveWalk[0] (Back) succeeded.', 'SUCCESS');

  If Not WalkToTileEx(BackupSpot) Then
  Begin
    Write('Walking to Backup spot failed.', 'ERROR');
    If Not Calibrate Then
      Exit
    Else
    Begin
      NotAgressive;
      Exit;
    End;
  End Else
  Begin
    Write('Walking to the Special spot to prevent too many crabs from popping.', 'SUCCESS');
    Inc(Players[CurrentPlayer].Integers[4]);
    DoSpecialSpot;
  End;
End;

Procedure CrabLoop;
Begin
  If Not LoggedIn Then
    Exit;
  _Status('CrabLoop');
  Me := GetMe;
  ToMain;
  CheckPlayers;
  While CrabsRocked = 0 Do
  Begin
    Wait(250 + Random(250));
    Me := GetMe;
    If Me.InFight Then
      Break;
    CatchALooseOne;
    CheckPlayers;
  End;
  Me := GetMe;
  If Not Me.InFight Then
    Write('Not in a fight.', 'MESSAGE');
  MarkTime(NoFight);
  While Not Me.InFight Do
  Begin
    Wait(100 + Random(50));
    Me := GetMe;
    If (Me.Tile.X <> MainSpot.x) And (Me.Tile.y <> MainSpot.y) Then
    Begin
      ToMain;
      Exit;
    End;
    If TimeFromMark(NoFight) >= (3 * 1000) Then
    Begin
      Write('Maybe crabs are un agressive.', 'MESSAGE');
      If Not CatchALooseOne Then
      Begin
        NotAgressive;
        Exit;
      End;
    End;
  End;
  DoRandoms;
  Write('Got attacked by a crab.', 'SUCCESS');
  Write('In a fight.', 'MESSAGE');
  AreWeInteracting(_NPCWeAreFighting);
  If NPCWeAreFighting Then
  Begin
    OnKill;
    Exit;
  End;
  Me := GetMe;
  While Me.InFight Do
  Begin
    Wait(10);
    DoRandoms;
    CheckPanic;
    Me := GetMe;
    If (Not Me.InFight) Or NPCWeAreFighting Then
    Begin
      OnKill;
      Exit;
    End;
    AntiBan;
    If Not LoggedIn Then
      LoginPlayer;
  End;
End;

Procedure SetMode;
Begin
  {Attack}
  If Players[CurrentPlayer].Integers[0] <> 0 Then
  Begin
    If Players[CurrentPlayer].Integers[0] > Stats[0] Then
    Begin
      CurrTraining := 0;
      SetFightMode(1);
      Write('Training attack.', 'PLAYER');
      Exit;
    End;
  End;
  {Strength/Ranging}
  If Players[CurrentPlayer].Integers[1] <> 0 Then
  Begin
    If Players[CurrentPlayer].Integers[1] > Stats[1] Then
    Begin
      CurrTraining := 1;
      SetFightMode(2);
      Case Players[CurrentPlayer].Strings[0] Of
        'melee': Write('Training strength.', 'PLAYER');
        'ranging': Write('Training ranged.', 'PLAYER');
      End;
      Exit;
    End;
  End;
  {Defence}
  If Players[CurrentPlayer].Integers[2] <> 0 Then
  Begin
    If Players[CurrentPlayer].Integers[2] > Stats[2] Then
    Begin
      CurrTraining := 2;
      If Not R_SetFightMode(4) Then
        R_SetFightMode(3);
      Case Players[CurrentPlayer].Strings[0] Of
        'melee': Write('Training defence.', 'PLAYER');
        'ranging': Write('Training ranged/defence.', 'PLAYER');
      End;
      Exit;
    End;
  End;
End;

Procedure SetCoords;
Begin
  If Not LoggedIn Then
    Exit;
  _Status('SetCoords');
  Write('Setting up all coords/vars.', 'MESSAGE');
  //Setup Crab spots:
  SetLength(CrabSpot, 3);
  CrabSpot[0] := Point(2512, 3766);
  CrabSpot[1] := Point(2513, 3765);
  CrabSpot[2] := Point(2514, 3766);
  //Setup DeAgressive walk:
  SetLength(DeAgressiveWalk, 3);
  DeAgressiveWalk[0] := Point(2529, 3767);
  DeAgressiveWalk[1] := Point(2543, 3759);
  DeAgressiveWalk[2] := Point(2553, 3747);
  //Setup Main spot:
  MainSpot := Point(2513, 3766);
  //Setup Special spot:
  SpecialSpot := Point(2515, 3766);
  //Setup Backup spot:
  BackupSpot := Point(2522, 3765);
  //Setup sleeper:
  MarkTime(Running);
  SkipTime := ((SleepTime * 60000) + Random(300000));
End;

Procedure SetupScript;
Begin
  DeclarePlayers;
  ReportLength := 46;
  _SleepFor := (SleepFor * (60 * 1000));
  SmartSetupEx(SMARTWorld, True, SMARTSigned, False);
  SetTargetDC(SmartGetDC);
  While Not RSReady Do
    Wait(100 + Random(50));
  SetupReflection;
  ChangeReportWidth(425);
  SmartSetDebug(True);
  If (SMARTSigned = True) And (Not LoggedIn) And (HopStart = True) Then
    _Hop(True);
End;

Procedure SetupPlayer;
Begin
  If DoNP Then
    DoNP := False;
  If Not LoggedIn Then
    LoginPlayer;
  ClearDebug;
  Write('Welcome to WaBiCrab by Floor66!', 'WELCOME');
  SetCoords;
  GetStats;
  SetMode;
  SetRun(True);
  SetAngle(True);
  MakeCompass('N');
  DoSpecialSpot;
  If (SMARTSigned = True) And LoggedIn And (Hop = True) Then
    CheckPlayers;
End;

Procedure ScriptTerminate;
Begin
  Progress;
End;

Begin
  SetupSRL;
  SetupScript;
  Repeat
    SetupPlayer;
    Repeat
      Repeat
        If Not LoggedIn Then
          LoginPlayer;
        DoRandoms;
        If DoNP Then
          Break;
        CrabLoop;
        Progress;
        CheckPanic;
        CheckPlayers;
        ToMain;
        _Sleep;
      Until((Stats[CurrTraining] >= Players[CurrentPlayer].Integers[CurrTraining]));
      If DoNP Or AllLeveled Then
      Begin
        NextPlayer2(False);
        Break;
      End;
      Players[CurrentPlayer].Integers[CurrTraining] := 0;
      GetStats;
      SetMode;
    Until(False);
  Until(AllPlayersInactive);
End.