Wizzup?
03-10-2008, 03:39 PM
Well, this is a cool thing you can do in SCAR, I don't know how usefull it is, but it is still pretty cool. :p
Say, you got this program:
program New;
procedure writemessage(s: String);
begin
writeln(s);
end;
begin
writemessage('hello');
end.
This will write hello in your debug.
You can make 'shortcuts', as I like to call them, to this procedure.
A shortcut can be made by adding an @+ProcedureName.
Write:=@WriteMessage;
You might know this way of adressing functions, I was first introduced to them when I worked with forms and TTimers.
Timer.OnTimer := @SomeProcedure;
// Or
Button.OnClick := @SomeProcedure;
program New;
procedure writemessage(s: String);
begin
writeln(s);
end;
Var
Write: Procedure (avar: string);
begin
Write := @WriteMessage;
Write('hello');
end.
Please not that the shortcut's procedure input and output (only for functions) has to be the same.
A simple example with a function:
program New;
procedure writemessage(s: String);
begin
writeln(s);
end;
function returnnumber:integer;
begin
result := 5;
end;
Var
Write: Procedure (avar: string);
Number: Function: Integer;
begin
Write := @WriteMessage;
Number := @ReturnNumber;
Write(IntToStr(Number()));
end.
Please note the Number(), if you don't add this SCAR will interpret it as a type mismatch.
You can also remove the link from the shortcut by simply setting it to nil.
Write := nil;
You can make it more complicated.
I wrote this when I was experimenting on using multiple locations (Lumbridge, Varrock) in one script, without using cases in walking (Like VYC does).
First, I made a record of a Location.
Type
TLocation = Record
Name: String;
ToMine, ToBank, BankItems, Start, Stop: Procedure;
MyMine: Function: Boolean;
End;
TLocationArray = Array Of TLocation;
Var
Locations: TLocationArray;
CurrentLocation: TLocation;
Load the Locations array like this:
Procedure LoadLocations;
Begin
SetLength(Locations, 1);
Locations[0].Name := 'VEM';
Locations[0].ToMine := @VEM_ToMine;
Locations[0].ToBank := @VEM_ToBank;
Locations[0].BankItems := @VEM_BankStuff;
Locations[0].MyMine := @VEM_MyMine;
End;
This way your mainloop could look like this:
Repeat
ResetLocation(CurrentLocation);
CurrentLocation := Fetch_Location(Players[CurrentPlayer].Strings[3]);
{This string (Strings[3]) holds the location name.
Fetch_Location returns a TLocation. }
CurrentLocation.Start();
If Players[CurrentPlayer].Loc = 'Bank' Then
Begin
CurrentLocation.ToMine();
End;
If Players[CurrentPlayer].Loc = 'Mine' Then
Begin
Repeat
Wait(100);
If Not CurrentLocation.MyMine() Then
Wait(50);
If FlagPresent Then
Wait(2000 + Random(500));
FindNormalRandoms;
If Not LoggedIn Then Break;
If Not FindPick then Break;
Until (InvFull Or ((GetSystemTime - MyTimer) > 60000 * MinutesPerLoad));
CurrentLocation.ToBank();
CurrentLocation.BankItems();
End;
ProgressReport;
CurrentLocation.Stop();
//Something with player logging in and out.
Until False;
Fetch_Location could look like this:
Function Fetch_Location(Name: string): TLocation;
Var
I: Integer;
Begin
Name := LowerCase(Name);
For I := Low(Locations) To High(Locations) Do
If Name = LowerCase(Locations[I].Name) Then
Begin
Result := Locations[I];
Exit;
End;
End;
You can also make Array of Function/Procedure.
program New;
type TFuncArray = Array Of Function: Integer;
Var
a: TFuncArray;
Function Return1: Integer;
Begin
result := 8;
End;
Function Return2: Integer;
Begin
result := 4;
End;
var
count: integer;
begin
setlength(a, 2);
a[0] := @return1;
a[1] := @return2;
for count := 0 to 1 do
writeln(inttostr(a[count]()));
end.
I hope this helped.
Raymond, SKy, nielsie and everyone else:
Please correct me on name-mistakes, general mistakes, extra features, or anything else that you think I should change or add to this tutorial.
~Wizzup?
Say, you got this program:
program New;
procedure writemessage(s: String);
begin
writeln(s);
end;
begin
writemessage('hello');
end.
This will write hello in your debug.
You can make 'shortcuts', as I like to call them, to this procedure.
A shortcut can be made by adding an @+ProcedureName.
Write:=@WriteMessage;
You might know this way of adressing functions, I was first introduced to them when I worked with forms and TTimers.
Timer.OnTimer := @SomeProcedure;
// Or
Button.OnClick := @SomeProcedure;
program New;
procedure writemessage(s: String);
begin
writeln(s);
end;
Var
Write: Procedure (avar: string);
begin
Write := @WriteMessage;
Write('hello');
end.
Please not that the shortcut's procedure input and output (only for functions) has to be the same.
A simple example with a function:
program New;
procedure writemessage(s: String);
begin
writeln(s);
end;
function returnnumber:integer;
begin
result := 5;
end;
Var
Write: Procedure (avar: string);
Number: Function: Integer;
begin
Write := @WriteMessage;
Number := @ReturnNumber;
Write(IntToStr(Number()));
end.
Please note the Number(), if you don't add this SCAR will interpret it as a type mismatch.
You can also remove the link from the shortcut by simply setting it to nil.
Write := nil;
You can make it more complicated.
I wrote this when I was experimenting on using multiple locations (Lumbridge, Varrock) in one script, without using cases in walking (Like VYC does).
First, I made a record of a Location.
Type
TLocation = Record
Name: String;
ToMine, ToBank, BankItems, Start, Stop: Procedure;
MyMine: Function: Boolean;
End;
TLocationArray = Array Of TLocation;
Var
Locations: TLocationArray;
CurrentLocation: TLocation;
Load the Locations array like this:
Procedure LoadLocations;
Begin
SetLength(Locations, 1);
Locations[0].Name := 'VEM';
Locations[0].ToMine := @VEM_ToMine;
Locations[0].ToBank := @VEM_ToBank;
Locations[0].BankItems := @VEM_BankStuff;
Locations[0].MyMine := @VEM_MyMine;
End;
This way your mainloop could look like this:
Repeat
ResetLocation(CurrentLocation);
CurrentLocation := Fetch_Location(Players[CurrentPlayer].Strings[3]);
{This string (Strings[3]) holds the location name.
Fetch_Location returns a TLocation. }
CurrentLocation.Start();
If Players[CurrentPlayer].Loc = 'Bank' Then
Begin
CurrentLocation.ToMine();
End;
If Players[CurrentPlayer].Loc = 'Mine' Then
Begin
Repeat
Wait(100);
If Not CurrentLocation.MyMine() Then
Wait(50);
If FlagPresent Then
Wait(2000 + Random(500));
FindNormalRandoms;
If Not LoggedIn Then Break;
If Not FindPick then Break;
Until (InvFull Or ((GetSystemTime - MyTimer) > 60000 * MinutesPerLoad));
CurrentLocation.ToBank();
CurrentLocation.BankItems();
End;
ProgressReport;
CurrentLocation.Stop();
//Something with player logging in and out.
Until False;
Fetch_Location could look like this:
Function Fetch_Location(Name: string): TLocation;
Var
I: Integer;
Begin
Name := LowerCase(Name);
For I := Low(Locations) To High(Locations) Do
If Name = LowerCase(Locations[I].Name) Then
Begin
Result := Locations[I];
Exit;
End;
End;
You can also make Array of Function/Procedure.
program New;
type TFuncArray = Array Of Function: Integer;
Var
a: TFuncArray;
Function Return1: Integer;
Begin
result := 8;
End;
Function Return2: Integer;
Begin
result := 4;
End;
var
count: integer;
begin
setlength(a, 2);
a[0] := @return1;
a[1] := @return2;
for count := 0 to 1 do
writeln(inttostr(a[count]()));
end.
I hope this helped.
Raymond, SKy, nielsie and everyone else:
Please correct me on name-mistakes, general mistakes, extra features, or anything else that you think I should change or add to this tutorial.
~Wizzup?