SRL Archive - RS3 Help

[OGL] Access Violation


Clutch

2015-05-19 23:30:54

So, I am trying to use @Obscurity;'s Walk procedure, after adding it to the code though it will run through once and then error out under Method Include as seen here;
[ATTACH=CONFIG]25972[/ATTACH]

I am not sure if it's the way I have my script written with two different - "mainLoops" as within my other script the walk procedure works perfectly fine. Although this question is probably more geared towards @Obscurity; or @Clarity; anyone else with some ideas, would be appreciated!

program ClutchCrafting;
{$include_once ogLib/lib/core/core.simba}
{See Thread for Instructions}
{ https://villavu.com/forum/showthread.php?t=113141&p=1343183#post1343183}
const
ItemSlot = 2; {first slot begins at 0}
PresetOption = 2; {Bank Preset 1 or 2}
Item = 45135; {See Thread for Instructions}
Banker = 3377138974;
Loop = '';

var
Banker1, funcModelArray: glModelArray;
clientCenter: TPoint;
SClay: glTextureArray;
position:array[0..2] of int32;
canPosition, canWalk, canBank, canRotateCamera: countDown = [0];

procedure Check;
begin end;

procedure pWalk;
var
funcDirection:ansiString;
funcIndex:uInt32=0;
funcMapX,
funcMapY:array[0..3] of single;
funcPlayer:tPoint;
funcTextureArray:glTextureArray;
begin
writeLN('[procedure] pWalk');
funcPlayer:=minimap.getLocalPosition();
if funcPlayer.y<position[1]-3 then
funcDirection:='south'
else if funcPlayer.y>position[1]+2 then
funcDirection:='north';
if funcPlayer.x<position[0]-3 then
funcDirection:=funcDirection+'east'
else if funcPlayer.x>position[0]+3 then
funcDirection:=funcDirection+'west';
if funcDirection then
minimap.clickDirection(funcDirection);
canWalk.setTime(random(1500,2500));
end;

procedure pPosition;
begin
writeLN('[procedure] pPosition');
position:=[71, 84, 270];
canPosition.setTime(random(9000));
end;

procedure CTool;
begin
production.SetTool(0)
end;

procedure CItem;
begin
inventory.clickItem(Item);
wait(RandomRange(600,1200));
end;

procedure Craft;
begin
if production.getProduct()=(ItemSlot) then
begin
production.clickMake;
wait(RandomRange(600,1500));
while production.HasProgress() do
wait(RandomRange(600,1200));
end
else
begin
production.setProduct(ItemSlot);
end;
canBank.SetTime(600);
end;

procedure OBank;
begin
Banker1 := ogl.getModels(Banker);
mouse.click(Banker1[0].toPoint().randomizePointEllipse(5), 1);
wait(RandomRange(1200,2000));
canBank.setTime(15000);
end;

procedure Withdraw;
begin
bank.clickpreset(PresetOption);
wait(RandomRange(600,1000));
end;
procedure RotateCamera;
begin
writeLn('Rotating Camera');
mainScreen.setDegrees(normalRandom(0,360),normalRandom(0,50));
canRotateCamera.setTime(random(120000));
WriteLn('Done Rotating Camera');
end;

Procedure mainLoop;
var
Reaction : Procedure() =@Check;
begin
if production.hasChooseATool() then
Reaction:=@CTool
else if production.hasProduction then
Reaction:=@Craft
else if inventory.isFull() and (not canBank.isFinished()) then
Reaction:=@CItem
else if bank.HasBank() then
Reaction:=@Withdraw
else if ogl.getModels(Banker).isEmpty or canRotateCamera.isFinished() then
Reaction:=@RotateCamera
else if (Length (ogl.getModels(Banker))) or (canBank.isFinished()) then
Reaction:=@OBank;
Reaction();
end;

Procedure mainLoop2;
var
Reaction : Procedure() =@Check;
begin
SClay:= ogl.getTextures(93840);

if canPosition.isFinished() then
Reaction:=@pPosition
else if (not SClay.isEmpty()) and canWalk.isFinished() then
Reaction:=@pWalk
else if canRotateCamera.isFinished() then
Reaction:=@RotateCamera
else if bank.HasBank() then
Reaction:=@Withdraw
else if (Length (ogl.getModels(Banker))) or (canBank.isFinished()) then
Reaction:=@OBank;

Reaction();
end;

begin
ogl.setup();
ogl.setDebugMode('textures');
if Loop = '1' then
repeat
mainLoop;
until False
else
repeat
writeLn(minimap.getLocalPosition());
mainLoop2;
until False;
end.

I continued to write the script despite that I couldn't get it to walk… anyways now it's throwing up errors about unknown declaration 'models' OR 'textures' whichever I try to set the debug too AND even when its commented out…? I didn't even think that was possible.

program ClutchCrafting;
{$include_once ogLib/lib/core/core.simba}
{See Thread for Instructions}
{ https://villavu.com/forum/showthread.php?t=113141&p=1343183#post1343183}
const
ItemSlot = 2; {first slot begins at 0}
PresetOption = 2; {Bank Preset 1 or 2}
Item = 45135; {See Thread for Instructions}
Banker = 3377138974;
Loop = '';

var
Banker1, funcModelArray: glModelArray;
clientCenter: TPoint;
SClay: glTextureArray;
Door, PWheel: glModelArray;
position:array[0..2] of int32;
canMould, canPW, canOpen, canPosition, canWalk, canBank, canRotateCamera: countDown = [0];

procedure Check;
begin end;

procedure pWalk;
var
funcDirection:ansiString;
funcIndex:uInt32=0;
funcMapX,
funcMapY:array[0..3] of single;
funcPlayer:tPoint;
funcTextureArray:glTextureArray;
begin
writeLN('[procedure] pWalk');
funcPlayer:=minimap.getLocalPosition();
if funcPlayer.y<position[1]-3 then
funcDirection:='south'
else if funcPlayer.y>position[1]+2 then
funcDirection:='north';
if funcPlayer.x<position[0]-3 then
funcDirection:=funcDirection+'east'
else if funcPlayer.x>position[0]+3 then
funcDirection:=funcDirection+'west';
if funcDirection then
minimap.clickDirection(funcDirection);
canWalk.setTime(random(1500,2500));
canPW.setTime(Random(1000,2000));
end;

procedure pPosition;
begin
writeLN('[procedure] pPosition');
position:=[71, 84, 270];
canPosition.setTime(random(9000));
end;

procedure PWCheck;
begin
PWheel := ogl.getModels(2328382469);
mouse.click(PWheel[0].toPoint().randomizePointEllipse(5), 1);
wait(RandomRange(3000,5000));

if production.hasProduction then
begin
canMould.setTime(600);
exit;
end else
canOpen.setTime(1000);
end;

procedure Open;
begin
Door:= ogl.getModels(2524031219);
mouse.click(Door[0].toPoint().randomizePointEllipse(5), 1);
wait(RandomRange(3000,5000));
end;

procedure Mould;
begin
if production.getProduct()=(ItemSlot) then
begin
production.clickMake;
wait(RandomRange(600,1500));
while production.HasProgress() do
wait(RandomRange(600,1200));
end
else
begin
production.setProduct(ItemSlot);
end;
end;

procedure CTool;
begin
production.SetTool(0)
end;

procedure CItem;
begin
inventory.clickItem(Item);
wait(RandomRange(600,1200));
end;

procedure Craft;
begin
if production.getProduct()=(ItemSlot) then
begin
production.clickMake;
wait(RandomRange(600,1500));
while production.HasProgress() do
wait(RandomRange(600,1200));
end
else
begin
production.setProduct(ItemSlot);
end;
canBank.SetTime(600);
end;

procedure OBank;
begin
Banker1 := ogl.getModels(Banker);
mouse.click(Banker1[0].toPoint().randomizePointEllipse(5), 1);
wait(RandomRange(1200,2000));
canBank.setTime(15000);
end;

procedure Withdraw;
begin
bank.clickpreset(PresetOption);
wait(RandomRange(600,1000));
end;
procedure RotateCamera;
begin
writeLn('Rotating Camera');
mainScreen.setDegrees(normalRandom(0,360),normalRandom(0,50));
canRotateCamera.setTime(random(120000));
WriteLn('Done Rotating Camera');
end;

Procedure mainLoop;
var
Reaction : Procedure() =@Check;
begin
if production.hasChooseATool() then
Reaction:=@CTool
else if production.hasProduction then
Reaction:=@Craft
else if inventory.isFull() and (not canBank.isFinished()) then
Reaction:=@CItem
else if bank.HasBank() then
Reaction:=@Withdraw
else if ogl.getModels(Banker).isEmpty or canRotateCamera.isFinished() then
Reaction:=@RotateCamera
else if (Length (ogl.getModels(Banker))) or (canBank.isFinished()) then
Reaction:=@OBank;
Reaction();
end;

Procedure mainLoop2;
var
Reaction : Procedure() =@Check;
begin
SClay:= ogl.getTextures(93840);

if canPosition.isFinished() then
Reaction:=@pPosition
else if (not SClay.isEmpty()) and canWalk.isFinished() then
Reaction:=@pWalk
else if (ogl.getModels(PWheel)) and (canPW.isFinished()) then
Reaction:=@PWCheck
else if canOpen.isFinished() then
Reaction:=@Open
else if (canMould.isFinished()) then
Reaction:=@Mould
else if canRotateCamera.isFinished() then
Reaction:=@RotateCamera
else if bank.HasBank() then
Reaction:=@Withdraw
else if (Length (ogl.getModels(Banker))) or (canBank.isFinished()) then
Reaction:=@OBank;

Reaction();
end;

begin
ogl.setup();
{ogl.setDebugMode('models');}
if Loop = '1' then
repeat
mainLoop;
until False
else
repeat
writeLn(minimap.getLocalPosition());
mainLoop2;
until False;
end.

Brandon

2015-05-20 00:14:31

From: Clutch
..


Banker[0] or PWheel[0] is nil or empty. Accessing the index will not access violate but accessing any of its properties will.

They are both arrays. You need to make sure they aren't nil and aren't empty.

Clutch

2015-05-20 00:17:33

From: Brandon
Banker[0] or PWheel[0] is nil or empty. Accessing the index will not access violate but accessing any of its properties will.

They are both arrays. You need to make sure they aren't nil and aren't empty.


I'll try and alter those tomorrow thanks for the information! Any ideas about the second part? I literally just edit it after you responded, or is that response for the second portion of my question?

Edit: @Brandon;
From: Brandon
Banker[0] or PWheel[0] is nil or empty. Accessing the index will not access violate but accessing any of its properties will.

They are both arrays. You need to make sure they aren't nil and aren't empty.

Could you by chance further explain. I understand what I have written does, but I do not understand the inner workings of it. Such as the [0]. I haven't the slightest idea as to what purpose that servers. I haven't gotten around to messing with it yet but I'm guessing I can try something along the lines of
mouse.click(ogl.getModels(12345).randomizePointelipse(20))

or I may just have to try altering my other code from my other scripts with the right-click option and change that to a left-click and not require a choose option.

Found this after digging through the includes. Believe it may be what I am looking for.
function glModel.closest(funcPointArray:tPointArray):tPointArray;
begin result:=funcPointArray.closestTo(self);end;

Brandon

2015-05-21 06:22:50

The digging around snippet above will work.

Your know how arrays work. Now think about what happens if you access and empty or nil array.

Banker is an array of glModel:


Var
Arr: glModelArray;
Pt: TPoint;
Begin
Arr := nil;

Pt := Arr[0].Point();

Click(pt);
End;

In the above arr[0] won't crash because lape does not do bounds checking.
It is undefined behaviour however.

The crash comes when you try to access and instance member on a nil object.

Nil.Point(); is where it crashes. That function probably does similar to:


Function GlModel.Point(): TPoint;
Begin
Result := point(self.X, self.Y);
End;

If arr[0] is nil, you're now doing "nil.X, nil.Y".

However the real problem lies in the array being empty. If the array is empty you are accessing the first index which is a random memory address (you're lucky if it's nil) and casting that to glModel. Finally, you're calling .point on this random address and voila.. Crash that you cannot catch or find.

You should be checking:

If (Length(Arr) > 0) then
Click(arr.closestPoint());

Or w/e.. But the length check matters.

Clutch

2015-05-21 21:53:02

From: Brandon
The digging around snippet above will work.

Your know how arrays work. Now think about what happens if you access and empty or nil array.

Banker is an array of glModel:


Var
Arr: glModelArray;
Pt: TPoint;
Begin
Arr := nil;

Pt := Arr[0].Point();

Click(pt);
End;

In the above arr[0] won't crash because lape does not do bounds checking.
It is undefined behaviour however.

The crash comes when you try to access and instance member on a nil object.

Nil.Point(); is where it crashes. That function probably does similar to:


Function GlModel.Point(): TPoint;
Begin
Result := point(self.X, self.Y);
End;

If arr[0] is nil, you're now doing "nil.X, nil.Y".

However the real problem lies in the array being empty. If the array is empty you are accessing the first index which is a random memory address (you're lucky if it's nil) and casting that to glModel. Finally, you're calling .point on this random address and voila.. Crash that you cannot catch or find.

You should be checking:

If (Length(Arr) > 0) then
Click(arr.closestPoint());

Or w/e.. But the length check matters.


Not following to the length that I would like, but did catch on to the important parts. Thanks for the information!

Brandon

2015-05-21 21:57:46

From: Clutch
Not following to the length that I would like


Too long of a post?

Clutch

2015-05-21 22:04:36

From: Brandon
Too long of a post?

Never, I just don't understand why "[0]" has to be there. If that's what's making it nil why not just remove it? Ignoring the fact that I assume it most likely will break it. I guess what I'm getting at, why the hell am I making it nil in the first place?

Brandon

2015-05-21 22:25:18

From: Clutch
Never, I just don't understand why "[0]" has to be there. If that's what's making it nil why not just remove it? Ignoring the fact that I assume it most likely will break it. I guess what I'm getting at, why the hell am I making it nil in the first place?



You aren't making it nil in the first place.

It works like this:


ModelID = 1024;


Let's say there's 10 of those on the screen at once, when you call "glGetModels(1024)", it will give you an array containing 10 of them. [0] will be the first one to render on screen. [1] the second, [2] the third.. and so on and so forth.. If none of them are on screen, it will give you an array of 0 elements or "nil". If you try to access something that isn't there (because the array is empty), it will crash and rightfully so. It's better that it crashes or access-violates than silently fails and you have no idea why.

That's the only reason you need to check the length or your return value.

Similarly, in reflection, if you wanted an array of TNPC, you'd have to check if SMART returned you anything at all before clicking.

If you don't check the length, how will you know which banker to click? How will you know how many bankers are on screen? How will you filter them out so you can grab the closest one to your char? Are you always going to click Banker[0] aka the first banker rendered?


So again, it is not your fault at all. It's by design. You just have to be careful. Not just for OpenGL, but ANY array. Whether it be an array of text, chars, colours, etc..

Clutch

2015-05-22 00:35:38

From: Brandon
You aren't making it nil in the first place.

It works like this:


ModelID = 1024;


Let's say there's 10 of those on the screen at once, when you call "glGetModels(1024)", it will give you an array containing 10 of them. [0] will be the first one to render on screen. [1] the second, [2] the third.. and so on and so forth.. If none of them are on screen, it will give you an array of 0 elements or "nil". If you try to access something that isn't there (because the array is empty), it will crash and rightfully so. It's better that it crashes or access-violates than silently fails and you have no idea why.

That's the only reason you need to check the length or your return value.

Similarly, in reflection, if you wanted an array of TNPC, you'd have to check if SMART returned you anything at all before clicking.

If you don't check the length, how will you know which banker to click? How will you know how many bankers are on screen? How will you filter them out so you can grab the closest one to your char? Are you always going to click Banker[0] aka the first banker rendered?


So again, it is not your fault at all. It's by design. You just have to be careful. Not just for OpenGL, but ANY array. Whether it be an array of text, chars, colours, etc..


Lol, that makes perfect sense now yet I feel stupid at the same time! Thanks again for the clarification!

Thomas

2015-05-22 02:15:53

Quick addition, instead off writing length(array) > 0, one could just write 'if length(array) then'