Log in

View Full Version : Memory leak? Cannot figure it out



babablksheep
12-08-2012, 06:09 PM
So I've modified Nebbula's monkfisher to suit my needs, added a break system and real-time paint.
The problem I'm having is the memory leak, it increases in mem usage significantly and crashes by the 7th or 8th load. Disabling the paint seems to get rid of it and getting rid of counting items seems to reduce it.
So my question is, is it the counting of the items that is causing the leak? If so, is there a solution or am I stuck with disabling the paint entirely?

program NebulaMonkFisher;
{$DEFINE SMART}
{$i srl/srl.simba}
{$i sps/sps.simba}
{$I SRL/SRL/Misc/SmartGraphics.Simba}

///////////////////////////// Instructions: ////////////////////////////////////
///////////////////// Start in the Piscatoris Bank /////////////////////////////
////////////////// Have a small net in your Toolbelt ///////////////////////////
/////////// Enter how many Loads of monkfish you want to fish //////////////////
///////////////////Enter what world you want to fish in ////////////////////////
//////////////////// Enter your username + password ////////////////////////////
////////////////////////////////////////////////////////////////////////////////

Var
f, k, g, count:integer; // Failsafes
lpu, startbreaktime, breakwhen, ebreakwhen, endbreaktime, x, y, DiffInCount, Mffi, Mffb, XpGained, monkfish: integer; //other
MiddleWalk, spot1, spot2, spot3, EastWalk, WestWalk:TPointArray;
PBox: TBox;
Status, BStatus: String;
const
Loads = 999999; // Amount of loads to do
Procedure DeclarePlayers;
begin
HowManyPlayers := 1; // Don't touch this
NumberOfPlayers(HowManyPlayers);// Don't touch this
CurrentPlayer := 0; // Don't touch this
Players[0].Name := ''; // Username
Players[0].Pass := ''; // Password
Players[0].Active := True; // Don't touch this
Players[0].Pin := ' '; // Bank Pin, Leave blank if you don't have one
end;

{---------------------Don't touch anything past this line---------------------}
//Procedure Loadmonkfish;
//begin
// monkfish := DTMFromString('mggAAAHicY2NgYBBmZmCQB2JJIOYDYi4gVg ficEYGBj8gjgVifyCOguJsD2ugLiYMzM+AHTDiwBAAAFOTA7s= ');
//end;
//Procedure Freemonkfish;
//begin
// FreeDTM(monkfish);
//end;
Function CountMonks: integer;
var
Count: integer;
begin
if GetCurrentTab() <> 25 then
begin
Gametab(Tab_Inv);
end;
//Count := CountItems('dtm', monkfish, []);
Count := CountItems('color',4346998, []);
result := Count;
end;
Procedure PaintProggy(TP: TStringArray; Placement: TPoint; Colour: integer);
var
I, H: Integer;
begin
if TimeFromMark(lpu) >= 1000 then
begin
Smart_ClearCanvas;
For I := 0 To High(TP) Do
begin
LoadTextTPA(TP[I], UpChars, H);
Placement.Y := Placement.Y + (H);
Smart_DrawTextEx(False, Placement.X, Placement.Y, 'UpChars', TP[I], Colour);
MarkTime(lpu);
end;
end;
end;
Function CalculateNextBreakTime: string;
var
Clock, Clock2: TIntegerArray;
begin
Clock := [0,0,0];
Clock2 := [0,0,0];
ConvertTime(ebreakwhen,Clock[0],Clock[1],Clock[2]);
ConvertTime(breakwhen - (TimeFromMark(endbreaktime)),Clock2[0],Clock2[1],Clock2[2]);
result := 'Next break in ' + tostr(Clock2[0])+':'+tostr(Clock2[1])+':'+tostr(Clock2[2])+' for ' + tostr(Clock[0])+':'+tostr(Clock[1])+':'+tostr(Clock[2]);
end;
Function gSmartLines(onbreak: boolean): TStringArray;
Var
SmartLines: TStringArray;
Clock: TIntegerArray;
XPPH, FishPerHour : integer;
begin
if (not onbreak or not LoggedIn) then
begin
DiffInCount := CountMonks - Mffi;
if DiffInCount <> 0 then
begin
IncEx(XpGained, DiffInCount*120);
IncEx(Mffi, DiffInCount);
end;
end;
Clock := [0,0,0];
XPPH := Round((XpGained * 3600) / (GetTimeRunning / 1000));
FishPerHour := Round(((Mffi+Mffb) * 3600) / (GetTimeRunning / 1000));
ConvertTime(GetTimeRunning,Clock[0],Clock[1],Clock[2]);
SetArrayLength(SmartLines, 7);
SmartLines[0] := ('Time Ran:' + tostr(Clock[0])+':'+tostr(Clock[1])+':'+tostr(Clock[2]));
SmartLines[1] := ('Exp Gained:' + IntToStr(XpGained));
SmartLines[2] := ('Exp Per hour:' + IntToStr(XPPH));
SmartLines[3] := ('Monkfish Fished:' + IntToStr(Mffb + Mffi));
SmartLines[4] := ('Monkfish per hour:' + IntToStr(FishPerHour));
SmartLines[5] := ('Status: '+Status);
if not onbreak then
begin
BStatus := CalculateNextBreakTime;
end;
SmartLines[6] := (BStatus);
result := SmartLines;
end;
Procedure doChecks;
begin
if (ExitSquealOfFortune()) then
begin
writeln('Closing squeal of fortune pop-up');
end;
if (FindSpinTicket()) then
begin
writeln('Found spin ticket, claiming.');
end;
if (not LoggedIn()) then
begin
WriteLn('Error: Not Logged In! Fixing - Thanks API!');
LoginPlayer();
wait(3500);
end;
PaintProggy(gSmartLines(false),Point(10,30),clWhit e);
end;
Procedure CalculateNextBreak;
var
Clock2, Clock: TIntegerArray;
begin
MarkTime(endbreaktime);
breakwhen := randomrange(600000, 6000000)//Break every 10 to 100 minutes
ebreakwhen := randomrange(10000, 3000000)//Break for 10 seconds to 50 minutes
Clock := [0,0,0];
Clock2 := [0,0,0];
ConvertTime(ebreakwhen,Clock[0],Clock[1],Clock[2]);
ConvertTime(breakwhen,Clock2[0],Clock2[1],Clock2[2]);
writeln('*zzz*Next break in ' + tostr(Clock2[0])+':'+tostr(Clock2[1])+':'+tostr(Clock2[2])+' for ' + tostr(Clock[0])+':'+tostr(Clock[1])+':'+tostr(Clock[2]));
end;
Procedure CheckForEBreak;
var
bml: integer;
Clock: TIntegerArray;
begin
Status := 'On Break';
repeat
inc(bml);
Clock := [0,0,0];
ConvertTime((ebreakwhen - TimeFromMark(startbreaktime)),Clock[0],Clock[1],Clock[2]);
if(TimeFromMark(lpu) > 950) then
begin
MarkTime(lpu);
BStatus := 'Resuming in: ' + tostr(Clock[0])+':'+tostr(Clock[1])+':'+tostr(Clock[2]);
PaintProggy(gSmartLines(true),Point(10,30),clWhite );
end;
if (bml > 5000000) then
begin
bml := 0;
writeln('*zzz* Currently on a coffee break resuming in: ' + tostr(Clock[0])+':'+tostr(Clock[1])+':'+tostr(Clock[2]));
end;
until (TimeFromMark(startbreaktime) >= ebreakwhen);
begin
//onbreak := 0;
writeln('*zzz* Resuming Fishing now.');
marktime(endbreaktime);
CalculateNextBreak;
end;
end;
Function CheckForBreak: Boolean;
var
Clock: TIntegerArray;
begin
if (TimeFromMark(endbreaktime) >= breakwhen) then
begin
Clock := [0,0,0];
marktime(startbreaktime);
ConvertTime(ebreakwhen,Clock[0],Clock[1],Clock[2]);
writeln('*zzz*Going on a coffee break resuming in:' + tostr(Clock[0])+':'+tostr(Clock[1])+':'+tostr(Clock[2]));
result := true;
if(ebreakwhen >= 300000) then//Check if break is greater than idle logout
begin
if(randomrange(1, 100) > 50) then//If so, have a chance of logging out manually (as if you knew you were going to be gone for a while)
begin
writeln('*zzz*Decided to logout, we know we''re going to be gone a while.')
Logout();
end;
end;
//onbreak := 1;
end else
begin
result := false;
end;
end;
Procedure Antiban;
var
randomanti: Integer;
begin
randomanti := random(375);
if randomanti < 23 then
begin
Wait(RandomRange(400,600));
end;
Case randomanti of
1: Mouse(531, 62, 11, 11, true);
2: begin
HoverSkill('Fishing', false);
Wait(RandomRange(2000, 3000));
Gametab(Tab_Inv);
end;
3: begin
Gametab(Tab_Stats);
Wait(randomrange(750, 2400));
Gametab(Tab_Inv);
end;
4: begin
Gametab(Tab_Friends);
Wait(randomrange(750, 2400));
Gametab(Tab_Inv);
end;
5: MakeCompass(RandomRange(0,20));
//6: MouseBox(0, 0, 753, 492, 0);
7: MakeCompass(RandomRange(340, 360));
8: SetAngle(RandomRange(0,30));
//10: MouseBox(5, 482, 454, 500, 1);
11: PickUpMouse;
12: PickUpMouse;
13: MouseBox(0, 0, 753, 492, 0);
14: MMouse(333, 225, 300, 215);
15: MMouse(333, 225, 300, 215);
16: MMouse(333, 225, 300, 215);
17: SetAngle(RandomRange(0,30));
18: MakeCompass(RandomRange(0,20));
19: MakeCompass(RandomRange(340, 360));
20: MakeCompass('N');
21: MakeCompass('N');
22: MouseSpeed := RandomRange(10,20);
23: MouseSpeed := RandomRange(10,20);
end;
end;

Procedure Beginning;
begin
// Loadmonkfish;
// Addonterminate('Freemonkfish');
MakeCompass('N');
SetAngle(0);
CalculateNextBreak;
// Writeln('done with beginning');
GameTab(Tab_Inv);
end;

Procedure WalkBankFromMiddle;
begin
MiddleWalk := [Point(1185, 1858), Point(1180, 1870), Point(1176, 1883), Point(1158, 1882)];
SPS_WalkPath(MiddleWalk);
end;

Procedure WalkFishingSpot1;
begin
spot1 := [Point(1180+randomrange(-2, 2), 1835+randomrange(-2, 2))];
SPS_WalkPath(spot1);
end;

Procedure WalkFishingSpot2;
begin
spot2 := [Point(1220+randomrange(-2, 2), 1838+randomrange(-2, 2))];
SPS_WalkPath(spot2);
end;

Procedure WalkFishingSpot3;
begin
spot3 := [Point(1145+randomrange(-2, 2), 1841+randomrange(-2, 2))];
SPS_WalkPath(spot3);
end;

Procedure WalkBankFromEast;
begin
EastWalk := [Point(1242, 1844), Point(1229, 1852), Point(1216, 1860), Point(1204, 1866), Point(1188, 1873), Point(1178, 1883), Point(1156, 1885)];
SPS_WalkPath(EastWalk);
end;

Procedure WalkBankFromWest;
begin
WestWalk := [Point(1096, 1842), Point(1110, 1846), Point(1125, 1849), Point(1142, 1851), Point(1158, 1853), Point(1174, 1857), Point(1176, 1885), Point(1158, 1883)];
SPS_WalkPath(WestWalk);
end;

Procedure PrintProggy();
Var
wc: integer;
SmartLines: TStringArray;
begin
SmartLines := gSmartLines(false);
repeat
writeln('***'+SmartLines[WC]);
inc(WC);
until (WC >= 4);
end;

Function StartFishing: Boolean;
begin
Status := 'Finding a fishing spot'
doChecks()
if not CheckForBreak then
begin
count := 1
f := 0
repeat
// MakeProggy(false);
inc(count);
x := MSCX;
y := MSCY;
// Writeln('Searching');
Wait(randomrange(300,700));
MouseSpeed := RandomRange(7,14);
If (FindObjTPA(x, y, 11379098, 10, 1, 20, 20, 2,['Harpoon'])) then
begin
// writeln('Found possible spot');
Mouse(x, y, 4, 4, False);
Wait(randomrange(300, 900));
If (WaitOption('Net F', 3000)) then
begin
if (randomrange(0, 25) < 10) then
begin
wait(randomrange(300, 900));
x := MSCX;
y := MSCY;
MMouse(randomrange(0, x), randomrange(0, y), 0, 0);
end;
//writeln('found spot');
result := true
Break;
end;
end;
until((count>4) or (true) or (not LoggedIn()));
If (count>4) then
begin
result := false
end;
end else
begin
CheckForEBreak;
end;
end;
Procedure WhileFishing;
begin
if not CheckForBreak then
begin
doChecks()
wait(randomrange(2000,2500));
repeat
PBox := IntToBox(245, 130, 285, 195);
repeat
Status := 'Fishing';
doChecks()
if CheckForBreak then
begin
CheckForEBreak;
end;
//MakeProggy(false);
if (AveragePixelShift(PBox, 50, 500)>=79) then
AntiBan;
until ((AveragePixelShift(PBox, 50, 500)<78) or (InvFull) or (not LoggedIn()));
// Writeln('pixelshift A done');
if (InvFull) then
begin
// writeln('Inv is full');
break;
end else
begin
if (AveragePixelShift(PBox, 250, 2500)<550) then
begin
// Writeln('PixelShift B done');
wait(randomrange(10,150));
if not startfishing then
break;
end;
end;
until((InvFull) or (not LoggedIn()));
end else
begin
CheckForEBreak;
end;
end;

Procedure WalkToBank;
var
P : TPoint;
Begin
SPS_GetMyPos;
Writeln(ToStr(SPS_GetMyPos));
P := SPS_GetMyPos;
if (P.x>1200) then
begin
writeln('Walking East Path');
WalkBankFromEast;
end else
if (P.x<1166) then
begin
writeln('Walking Wast Path');
WalkBankFromWest;
end else
begin
writeln('Walking Middle Path');
WalkBankFromMiddle;
end;
end;

Procedure Banking;
var
failattempts: integer;
begin
if not CheckForBreak then
begin
repeat
writeln('Detected as still walking, waiting to try for banker...');
until(AveragePixelShift(PBox, 1, 1800)<3)
MouseSpeed := RandomRange(100,110);
writeln('done walking to bank2;');
//PaintProggy(gSmartLines,Point(10,30),clWhite);
Writeln('Banking');
f := 0;
Wait(randomrange(400,800));
repeat
Wait(randomrange(250, 600));
//Inc(f); //gets rid of old failure check, it counts a fail even if it succeeds, which may not be a big deal, but let's just be smarter about it and keep it local.
x := MSCX;
y := MSCY;
if (FindObjTPA(x, y, 2846095, 15, 1, 4, 5, 4, ['rnold', 'Arnold'])) then
begin
Mouse(x, y, 0, 0, false);
if (WaitOption('Bank ', 800)) then
begin
g := 0
repeat
Inc(g);
Wait(RandomRange(45, 55))
until((BankScreen) or (g>60) or (PinScreen) or (not LoggedIn()));
If PinScreen then
InPin(Players[CurrentPlayer].Pin);
end;
end else
begin
inc(failattempts);
if(failattempts > 3) then
begin
SetAngle(0);
failattempts := 0;
MakeCompass(RandomRange(90,270));
end;
end;
until((BankScreen) or (not LoggedIn()));
if (not LoggedIn()) then
begin
writeln('Looking for the banker when we are not even logged in...');
end else
begin
IncEx(Mffb, Mffi);
Mffi := 0;
DepositAll;
Wait(randomRange(400, 800));
CloseBank;
end;
end else
begin
CheckForEBreak;
end;
end;

begin
MouseSpeed := RandomRange(10,20);
SRL_SixHourFix := True;
SMART_FixSpeed := True;
ClearDebug;
SetupSRL;
DeclarePlayers;
if (not LoggedIn()) then
begin
LoginPlayer();
wait(3500);
end;
Beginning;
writeln('Starting');
// MakeProggy;
SPS_Setup(RUNESCAPE_SURFACE,['2_4']);
repeat
// if onbreak = 1 then
// repeat
// until(onbreak = 0);
Status := 'Checking Position';
doChecks();
repeat
repeat
SPS_GetMyPos;
if (invfull) then
break
else
if not Startfishing then
begin
Status := 'Walking to fish spot'
PaintProggy(gSmartLines(false),Point(10,30),clWhit e);
MouseSpeed := RandomRange(10,20);
WalkFishingSpot1;
wait(RandomRange(600,1200));
if not Startfishing then
begin
MouseSpeed := RandomRange(10,20);
WalkFishingSpot2;
wait(RandomRange(600,1200));
if not Startfishing then
begin
MouseSpeed := RandomRange(10,20);
WalkFishingSpot1;
wait(RandomRange(600,1200));
if not Startfishing then
begin
MouseSpeed := RandomRange(10,20);
WalkFishingSpot3;
wait(RandomRange(600,1200));
if not Startfishing then
begin
end;
end;
end;
end;
end;
until((true) or (not LoggedIn()));
WhileFishing;
until((InvFull) or (not LoggedIn()));
if (InvFull) then
begin
Wait(Randomrange(1300,4000));
Status := 'Walking to bank'
PaintProggy(gSmartLines(false),Point(10,30),clWhit e);
WalkToBank;
// LoadDTMS;
Status := 'Banking'
PaintProggy(gSmartLines(false),Point(10,30),clWhit e);
Banking;
PrintProggy();
inc(k);
Writeln('###Finished with load #'+IntToStr(k));
// FreeDTMMs;
MouseSpeed := RandomRange(10,20);
end;
until(k=loads);
end.

superuser
12-08-2012, 07:17 PM
LoadTextTPA(TP[I], UpChars, H);
You create TPA which you don't put in variable, hence staying in memory since you are not releasing it. Also, each TXArray you don't set to 0, stays in memory. For example:


var
x: TStringArray;

...

x := FooBar(...)

// Now, if you don't do SetLength(x, 0), you create a leak..

babablksheep
12-08-2012, 08:02 PM
Awesome, thanks!

babablksheep
12-09-2012, 01:56 AM
Would I also have to release the memory reserved for single variables?

KingKong
12-09-2012, 02:10 AM
no, its only for arrays

Brandon
12-09-2012, 02:12 AM
Each TXArray you don't set to 0, stays in memory. For example:


var
x: TStringArray;

...

x := FooBar(...)

// Now, if you don't do SetLength(x, 0), you create a leak..



no, its only for arrays


Both of these are entirely untrue. The memory is free'd when the variable goes out of scope or when the script ends. The only time something leaks is when you use non-scope defined variables such as assigning an object directly to Result.

Ex: CombineTPA vs CombineTPAWrap. The Wrapper functions don't leak but the non-wrapper ones do.


Yo can try it by constantly creating new arrays in loops and it will not leak.

babablksheep
12-09-2012, 04:41 AM
I'm still having problems isolating the individual leaks. I've made sure every result is a local variable in the function so it will go out of scope. Also, I've made sure to set each length to 0 at the end of each method. It seems to have helped, but has not gotten rid of the insane memory usage after a prolonged period.

NKN
12-09-2012, 06:41 AM
I'm still having problems isolating the individual leaks. I've made sure every result is a local variable in the function so it will go out of scope. Also, I've made sure to set each length to 0 at the end of each method. It seems to have helped, but has not gotten rid of the insane memory usage after a prolonged period.
Did you use the wrappers of every function?

superuser
12-09-2012, 09:19 AM
Both of these are entirely untrue. The memory is free'd when the variable goes out of scope or when the script ends. The only time something leaks is when you use non-scope defined variables such as assigning an object directly to Result.

Ex: CombineTPA vs CombineTPAWrap. The Wrapper functions don't leak but the non-wrapper ones do.


Yo can try it by constantly creating new arrays in loops and it will not leak.

Right on the spot here!

babablksheep
12-09-2012, 09:41 AM
I do not use any low level tpa functions, which are the ones that have wrapped variations.
I have added this, found it some old archive. It overrides the TPA functions with their wrapped equivalent. It does not help.

{$IFDEF RAYMONDPOWNS} {DONT TOUCH THIS LINE, IT FIXES CODE 8. The define is an undocumented define for Pascalscript as there is no documented one.} function SplitTPA(arr : TPointArray; dist : Integer) : T2DPointArray; begin SplitTPAWrap(arr, dist, result); end; function SplitTPAEx(arr : TPointArray; w, h : integer) : T2DPointArray; begin SplitTPAExWrap(Arr, w, h, result); end; function ClearTPAFromTPA(arP, ClearPoints : TPointArray) : TPointArray; begin ClearTPAFromTPAWrap(arP, ClearPoints, result); end; function TPAToATPAEx(arP : TPointArray; w, h : integer) : T2DPointArray; begin TPAtoATPAExWrap(arP, w, h, result); end; function TPAToATPA(arP : TPointArray; dist : Integer) : T2DPointArray; begin TPAtoATPAWrap(arP, dist, result); end; function FindGapsTPA(TPA : TPointArray; MinPixels : integer) : T2DPointArray; begin FindGapsTPAWrap(tpa, MinPixels, result); end; {$ENDIF}

It seems the leak is caused by this code in particular, but I've tried everything to no avail.


Procedure PaintProggy(Placement: TPoint; Colour: integer);
var
TPA1: TPointArray;
TP: TStringArray;
I, H: Integer;
begin
if(UsePaint) then
begin
if TimeFromMark(lpu) >= 1000 then
begin

Smart_ClearCanvas;
TP := gSmartLines();
For I := 0 To High(TP) Do
begin
TPA1 := LoadTextTPA(TP[I], UpChars, H);
Placement.Y := Placement.Y + (H);
Smart_DrawTextEx(False, Placement.X, Placement.Y, 'UpChars', TP[I], Colour);
MarkTime(lpu);
end;
SMART_FreeDebug();
end;
setLength(TP, 0);
setLength(TPA1, 0);
end;
end;

Is there something I'm missing? Is the fact that it is called so often why the leak is so blatant and previously unnoticed?

superuser
12-09-2012, 09:54 AM
I do not use any low level tpa functions, which are the ones that have wrapped variations.
I have added this, found it some old archive. It overrides the TPA functions with their wrapped equivalent. It does not help.

{$IFDEF RAYMONDPOWNS} {DONT TOUCH THIS LINE, IT FIXES CODE 8. The define is an undocumented define for Pascalscript as there is no documented one.} function SplitTPA(arr : TPointArray; dist : Integer) : T2DPointArray; begin SplitTPAWrap(arr, dist, result); end; function SplitTPAEx(arr : TPointArray; w, h : integer) : T2DPointArray; begin SplitTPAExWrap(Arr, w, h, result); end; function ClearTPAFromTPA(arP, ClearPoints : TPointArray) : TPointArray; begin ClearTPAFromTPAWrap(arP, ClearPoints, result); end; function TPAToATPAEx(arP : TPointArray; w, h : integer) : T2DPointArray; begin TPAtoATPAExWrap(arP, w, h, result); end; function TPAToATPA(arP : TPointArray; dist : Integer) : T2DPointArray; begin TPAtoATPAWrap(arP, dist, result); end; function FindGapsTPA(TPA : TPointArray; MinPixels : integer) : T2DPointArray; begin FindGapsTPAWrap(tpa, MinPixels, result); end; {$ENDIF}

It seems the leak is caused by this code in particular, but I've tried everything to no avail.


Procedure PaintProggy(Placement: TPoint; Colour: integer);
var
TPA1: TPointArray;
TP: TStringArray;
I, H: Integer;
begin
if(UsePaint) then
begin
if TimeFromMark(lpu) >= 1000 then
begin

Smart_ClearCanvas;
TP := gSmartLines();
For I := 0 To High(TP) Do
begin
TPA1 := LoadTextTPA(TP[I], UpChars, H);
Placement.Y := Placement.Y + (H);
Smart_DrawTextEx(False, Placement.X, Placement.Y, 'UpChars', TP[I], Colour);
MarkTime(lpu);
end;
SMART_FreeDebug();
end;
setLength(TP, 0);
setLength(TPA1, 0);
end;
end;

Is there something I'm missing? Is the fact that it is called so often why the leak is so blatant and previously unnoticed?

SMART_DrawTextEx is leaking, or actually SMART_DrawTextMulti is. I had to create my own text-drawing function:


procedure TextOut(b, x, y: integer; const t: string; c: integer);
var
pa: TPointArray;
h, i: integer;
begin
if b > 0 then begin
pa := LoadTextTPA(t, SmallChars, h);

for i := 0 to High(pa) do begin
FastSetPixel(b, x + 1 + pa[i].x, y + 1 + pa[i].y, 1317920); // Shadow
FastSetPixel(b, x + pa[i].x, y + pa[i].y, c);
end;

SetLength(pa, 0);
end;
end;


You can use it like this:


TextOut(SMART_Canvas.Index, x, y + SRL_NAVBAR_INGAME_Y, 'Text to draw', clYellow);

Brandon
12-09-2012, 02:26 PM
Replace your SmartGraphics with this.. I removed the CombineTPA's and FindTPAEdges non-wrappers and replaced them with the wrapper variants. I think I got them all :l

Diffchecker: http://diffchecker.com/K1H3S09o

Code:


{$DEFINE SMART_GRAPHICS}
{*
Paint Smart
===========

The Paint Smart include contains functions that will paint graphics on to the
SMART screen. Used to make scripts look nicer and sometimes to display
progress reports. Also used as a useful debugging tool.

*}

var
SMART_Canvas: TMufasaBitmap;
SMART_DebugSetup, SMART_Reset: Boolean;

{*
Authors: Coh3n, Brandon.

Declares everything needed for setting up SmartDebug.
There is no need to call this in scripts.
*}
procedure SMART_SetupDebug;
begin
SmartSetDebug(True);
SMART_Canvas := TMufasaBitmap.Create;
SMART_Canvas.SetPersistentMemory(SmartDebugArray, 765, 553);
SMART_DebugSetup := true;
if not SMART_Reset then
AddOnTerminate('SMART_FreeDebug');
end;

{*
Author: Brandon.

Creates an array of specific colours for use with FastSetPixels.
*}
Function ColorsFromTPA(TPA: TPointArray; Color: Integer): TIntegerArray;
var
I, L: Integer;
begin
SetLength(Result, Length(TPA));
L:= High(TPA);
For I:= 0 To L Do
Result[I]:= Color;
end;

{*
Authors: Coh3n, Brandon.

Clears an Area of the canvas Specified by the box.
*}
procedure SMART_ClearCanvasArea(Area: TBox);
{$IFDEF SMART}
begin
if (not SMART_DebugSetup) then
SMART_SetupDebug;

SMART_Canvas.Rectangle(Area, 0);

{$ELSE}
begin
{$ENDIF}
end;

{*
Author: Coh3n, Brandon.

Clears the entire Smart Canvas.
*}
procedure SMART_ClearCanvas;
begin
if (not SMART_DebugSetup) then
SMART_SetupDebug;

If (SMART_CANVAS.TransparentColorSet) then
SMART_CANVAS.FastDrawClear(SMART_CANVAS.GetTranspa rentColor)
else
SMART_CANVAS.FastDrawClear(0);
end;

{*
Author: Mormanman.
Clears the MainScreen of Smart.
*}
procedure SMART_ClearMS;
begin
SMART_ClearCanvasArea(IntToBox(MSBox.X1 + SRL_NAVBAR_INGAME_X,
MSBox.Y1 + SRL_NAVBAR_INGAME_Y, MSBox.X2, MSBox.Y2 + SRL_NAVBAR_INGAME_Y));
end;

{*
Authors: Sir R. Magician, Brandon.

Draws a TPA with a specified Colour onto Smart's Canvas.
Clears the Canvas first if Clear is set to true.
*}
procedure SMART_DrawDotsEx(Clear: boolean; Pixels: TPointArray; Color: TColor);
{$IFDEF SMART}
var
P: TPointArray;
begin
if (not SMART_DebugSetup) then
SMART_SetupDebug;

if Clear then SMART_ClearCanvas;
P := CopyTPA(Pixels);
OffsetTPA(P, Point(SRL_NAVBAR_INGAME_X, SRL_NAVBAR_INGAME_Y));
SMART_Canvas.DrawTPA(P, Color);
{$ELSE}
begin
{$ENDIF}
end;

{*
Authors: Sir R. Magician, mormanman, Brandon.

Draws a 2-Dimensional Array of Pixels on Smart.
Clears the Canvas first if Set to True.
*}
procedure SMART_DrawDotsMulti(Clear: boolean; pixels : T2DPointArray);
{$IFDEF SMART}
var
h, color : integer;
begin
if (not SMART_DebugSetup) then
SMART_SetupDebug;

if Clear then SMART_ClearCanvas;

for h := 0 to High(pixels) do
begin

color := h div 10 + h mod 10;
case color of
0 : color := clWhite;
1 : color := clYellow;
2 : color := clBlue;
3 : color := clLime;
4 : color := 26367;//orange
5 : color := clPurple;
6 : color := clAqua;
7 : color := clFuchsia;
8 : color := clGreen;
9 : color := clRed;
end;

SMART_DrawDotsEx(False, pixels[h], color);
end;
{$ELSE}
begin
{$ENDIF}
end;

{*
Author: mormonman.

Draws the box of each TPA in the ATPA and write the index number in the top
left corner and a cross at the point found by MiddleTPA.
*}
procedure SMART_DebugATPA(Clear: Boolean; ATPA: T2DPointArray);
{$IFDEF SMART}
var
i, h, len: Integer;
B: TBox;
MP: TPoint;
TPA: TPointArray;
Points: T2DPointArray;
begin
len := Length(ATPA);
if (len < 1) then
Exit;
SetLength(Points, len);

for i := 0 to High(ATPA) do
begin
B := GetTPABounds(ATPA[i]);
len := Length(ATPA[i]);
if (len > 0) then
begin
TPA := LoadTextTPA(ToStr(i), SmallChars, h);
OffsetTPA(TPA, Point(B.X1+1, B.Y1+1));
end;
CombineTPAWrap(FindTPAEdges(TPAFromBox(B)), TPA, Points[i]);
MP := MiddleTPA(ATPA[i]);
TPA := [Point(MP.x-1, MP.y), Point(MP.x+1, MP.y), Point(MP.x, MP.y-1),
Point(MP.x, MP.y+1), Point(MP.x-2, MP.y), Point(MP.x, MP.y),
Point(MP.x+2, MP.y), Point(MP.x, MP.y-2), Point(MP.x, MP.y+2)];
CombineTPAWrap(Points[i], TPA, Points[i]);
end;

SMART_DrawDotsMulti(Clear, Points);
{$ELSE}
begin
{$ENDIF}
end;

{*
Author: mormonman

Draws the TPA bounds and puts a cross at the point created by MiddleTPA.
*}
procedure SMART_DebugTPA(Clear: Boolean; TPA: TPointArray);
begin
SMART_DebugATPA(Clear, [TPA]);
end;

{*
Author: Sir R. Magician

Clears the SMART canvas, then draws a red TPA (Dots).
*}
procedure SMART_DrawDots(Dots: TPointArray);
begin
SMART_DrawDotsEx(True, Dots, clRed);
end;

{*
Author: Coh3n

Draws a single colored dot (Color) at the set point (Point) on the SMART canvas.
Will clear the SMART canvas if set to do so (Clear).
*}
procedure SMART_DrawDot(Clear: Boolean; Point: TPoint; Color: TColor);
begin
SMART_DrawDotsEx(Clear, [Point], Color);
end;

{*
Authors: mormonman, Brandon.

Draws an array of boxes onto the SMART canvas. Set Color to -1 for it to use
different colors (like in SMART_DrawDotsMulti).
Fill will fill each box with a color.
*}
procedure SMART_DrawBoxes(Clear, Fill: Boolean; TBA: TBoxArray; Color: Integer);
{$IFDEF SMART}
var
i, colour, temp: Integer;
Box: TBox;
TPAEdges: TPointArray;
begin
if (not SMART_DebugSetup) then
SMART_SetupDebug;

if Clear then SMART_ClearCanvas;

if (Length(TBA) < 1) then Exit;
for i := 0 to High(TBA) do
begin
Box := TBA[i];
if (Color > 0) then
begin
Temp := color;
end else
begin
colour := i div 5 + i mod 5;
case colour of
0 : Temp := clWhite;
1 : Temp := clYellow;
2 : Temp := clBlue;
3 : Temp := clLime;
4 : Temp := clGreen;
end;
end;

if Fill then
begin
Box := IntToBox(Min(TBA[i].X1, TBA[i].X2), Min(TBA[i].Y1, TBA[i].Y2) + SRL_NAVBAR_INGAME_Y,
Max(TBA[i].X1, TBA[i].X2), Max(TBA[i].Y1, TBA[i].Y2) + SRL_NAVBAR_INGAME_Y);
if (Box.X1 < 0) then Box.X1 := 0;
if (Box.X2 < 0) then Box.X2 := 0;
if (Box.Y1 < 0) then Box.Y1 := 0;
if (Box.Y2 < 0) then Box.Y2 := 0;
SMART_Canvas.Rectangle(Box, Temp)
end else
begin
FindTPAEdgesWrap(TPAFromBox(Box), TPAEdges);
SMART_DrawDotsEx(False, TPAEdges, Temp);
end;

end;

{$ELSE}
begin
{$ENDIF}
end;

{*
Author: mormonman, Brandon.

Draws a single colored (color) box (Box) on the SMART canvas. Will clear the
canvas if set to do so (Clear).
Fill will fill in the box with the specified Color.
*}
procedure SMART_DrawBoxEx(Clear, Fill: boolean; Box: TBox; color: TColor);
begin
SMART_DrawBoxes(Clear, Fill, [Box], color);
end;

{*
Author: mormonman

Clears the SMART canvas, then draws a single red box, specified by 'Box'.
*}
procedure SMART_DrawBox(Box: TBox);
begin
SMART_DrawBoxEx(True, False, Box, clRed);
end;

{*
Author: Coh3n

Draws a box on the RS mainscreen, even if the coordinates are outside client
boundaries.
Fill will Fill in the box with the specified Color.
*}
procedure SMART_DrawBoxMS(Clear, Fill: Boolean; Box: TBox; Color: TColor);
begin
if (Box.X1 < MSX1) then Box.X1 := MSX1;
if (Box.Y1 < MSY1) then Box.Y1 := MSY1;
if (Box.X2 > MSX2) then Box.X2 := MSX2;
if (Box.Y2 > MSY2) then Box.Y2 := MSY2;
SMART_DrawBoxEx(Clear, Fill, Box, Color);
end;

{*
Author: mormonman

Draws a line a set color (Color) from point 1 (TP1) to point 2 (TP2). Will
clear the SMART canvas if set to do so (Clear).
*}
procedure SMART_DrawLine(Clear: Boolean; TP1, TP2: TPoint; Color: TColor);
var
TempMufasa: TMufasaBitmap;
TempTBitmap: TBitmap;
begin
{$IFDEF SMART}
if (not SMART_DebugSetup) then
SMART_SetupDebug;

if (Clear) then
SMART_ClearCanvas;

TempTBitmap := TBitmap.Create;
TempTBitmap.Width := Max(1, iAbs(TP2.X - TP1.X));
TempTBitmap.Height := Max(1, iAbs(TP2.Y - TP1.Y));
TempTBitmap.Canvas.Pen.COLOR := Color;

TempTBitmap.Canvas.moveto(0, 0);
TempTBitmap.Canvas.LineTo(iAbs(TP2.X - TP1.X), iAbs(TP2.Y - TP1.Y));

TempMufasa := TMufasaBitmap.Create;
TempMufasa.LoadFromTBitmap(TempTBitmap);
if (SMART_Canvas.TransparentColorSet) then
TempMufasa.SetTransparentColor(SMART_Canvas.GetTra nsparentColor);

FastDrawTransparent(Min(TP1.X, TP2.X), Min(TP1.Y, TP2.Y) + SRL_NAVBAR_INGAME_Y, TempMufasa.Index, SMART_Canvas.Index);

TempMufasa.Free;
TempTBitmap.Free;
{$ENDIF}
end;

{*
Author: mormonman

Draws an ellipse on the SMART canvas defined by 'Center', 'XRadius', and
'YRadius'. If 'Fill' is true it will fill the ellipse, otherwise it draws just
the border. Will clear the SMART canvas if set to do so (Clear).
*}
procedure SMART_DrawEllipse(Clear: Boolean; Center: TPoint; XRadius, YRadius: Integer; Fill: Boolean; Color: TColor);
{$IFDEF SMART}
var
TPA: TPointArray;
TempMufasa: TMufasaBitmap;
TempTBitmap: TBitmap;
begin
if Fill then
begin
if (not SMART_DebugSetup) then
SMART_SetupDebug;

if Clear then
SMART_ClearCanvas;

TempTBitmap := TBitmap.Create;
TempTBitmap.Canvas.Brush.COLOR := Color;

TempTBitmap.Width := (XRadius * 2);
TempTBitmap.Height := (YRadius * 2);

TempTBitmap.Canvas.Ellipse(Center.X - XRadius, Center.Y - YRadius, Center.X + XRadius, Center.Y + YRadius);

TempMufasa := TMufasaBitmap.Create;
TempMufasa.LoadFromTBitmap(TempTBitmap);
if (SMART_Canvas.TransparentColorSet) then
TempMufasa.SetTransparentColor(SMART_Canvas.GetTra nsparentColor);

FastDrawTransparent(0, SRL_NAVBAR_INGAME_Y, TempMufasa.Index, SMART_Canvas.Index);
TempMufasa.Free;
TempTBitmap.Free;
end else
begin
TPA := TPAFromEllipse(Center.X, Center.Y, XRadius, YRadius);

if (Length(TPA) >= 1) then
SMART_DrawDotsEx(Clear, TPA, Color);
end;
{$ELSE}
begin
{$ENDIF}
end;

{*
Author: mormonman

Draws a circle on the SMART canvas defined by 'Center' and 'Radius'. If 'Fill'
is true it will fill the circle, otherwise it draws just the border. Will
clear the SMART canvas if set to do so (Clear).
*}
procedure SMART_DrawCircle(Clear: Boolean; Center: TPoint; Radius: Integer; Fill: Boolean; Color: TColor);
begin
SMART_DrawEllipse(Clear, Center, Radius, Radius, Fill, Color);
end;

{*
Author: mormonman

Draws an array of polygons on the SMART canvas in the set color. Will clear the
SMART canvas if set to do so (Clear).
*}
procedure SMART_DrawPolygons(Clear: Boolean; Polygons: T2DPointArray; color: TColor);
{$IFDEF SMART}
var
i, h, Hi: Integer;
begin
if (Clear) then
SMART_ClearCanvas;

if (Length(Polygons) < 1) then
Exit;

for h := 0 to High(Polygons) do
begin
Hi := High(Polygons[h]);
if (Hi < 2) then Exit;

for i := 0 to Hi - 1 do
SMART_DrawLine(False, Polygons[h][i], Polygons[h][i+1], color);

SMART_DrawLine(False, Polygons[h][Hi], Polygons[h][0], color);
end;
{$ELSE}
begin
{$ENDIF}
end;

{*
Authors: Flight & Coh3n

Draws text on the SMART canvas. Used mainly for progress reports. Parameters
are as follows:
* Clear: Clear the SMART canvas before drawing
* Shadow: if set to true, will add a shadow to the text
* TSA: the string array of what to be printed; each element is a different line
* Placement: the point to start the text drawing
* Font: the font to use (see Simba/Fonts/)
* Colour: the color of the font
*}
procedure SMART_DrawTextMulti(Clear, Shadow: Boolean; TSA: TStringArray; Placement: TPoint; Font: string; Colour: TColor);
var
i, h, TPH: Integer;
TTP, SArr: TPointArray;
begin
if (not SMART_DebugSetup) then
SMART_SetupDebug;

if (Clear) then
SMART_ClearCanvas;

TPH := High(TSA);

for i := 0 to TPH do
begin
TTP := LoadTextTPA(TSA[i], Font, h);
OffsetTPA(TTP, Point(Placement.x, Placement.y+(i*h)));
SMART_DrawDotsEx(False, TTP, Colour);
if Shadow then
begin
SArr := CopyTPA(TTP);
OffsetTPA(SArr, Point(1, 1));
ClearTPAFromTPAWrap(SArr, TTP, SArr);
SMART_DrawDotsEx(False, SArr, 65536);
end;
end;
end;

{*
Author: Coh3n

Draws shadowed line of text on the SMART canvas. Parameters are as follows:
* Clear: Clear the SMART canvas before drawing
* x, y: the coords of where to place the text
* font: the font to use (see Simba/Fonts/)
* Text: the text to draw to the SMART canvas
* Colour: the color of the font
*}
procedure SMART_DrawTextEx(Clear: Boolean; x, y: Integer; font, Text: string; Color: TColor);
begin
SMART_DrawTextMulti(Clear, true, [Text], Point(x, y), font, Color);
end;

{*
Author: Coh3n

Same as SMART_DrawTextEx, except clears the canvas before drawing.
*}
procedure SMART_DrawText(x, y: Integer; font, Text: string; Color: TColor);
begin
SMART_DrawTextEx(False, x, y, font, Text, Color);
end;

{*
Author: Coh3n

Draws a bitmap (Bitmap) on the SMART canvas at given coordinates (Placement).
Will clear the canvas beforehand if specified to do so (Clear).
*}
procedure SMART_DrawBitmap(Clear: Boolean; Bitmap: Integer; Placement: TPoint);
begin
if (not SMART_DebugSetup) then
SMART_SetupDebug;

if (Clear) then
SMART_ClearCanvas;

FastDrawTransparent(Placement.X, Placement.Y + SRL_NAVBAR_INGAME_Y, Bitmap, SMART_Canvas.Index);
end;

{*
Authors: Coh3n, Brandon.

Frees the SMART_Canvas bitmap.
*}
procedure SMART_FreeDebug;
begin
try
if (SMART_DebugSetup) then
begin
SMART_Canvas.ResetPersistentMemory;
SMART_Canvas.Free;
SMART_DebugSetup := False;
SMART_Reset := True;
end;
except
Writeln('Failed to free SMART_Canvas bitmap: '+ExceptionToString(ExceptionType, ExceptionParam));
end;
end;

Olly
12-09-2012, 03:41 PM
Replace your SmartGraphics with this.. I removed the CombineTPA's and FindTPAEdges non-wrappers and replaced them with the wrapper variants. I think I got them all :l

Diffchecker: http://diffchecker.com/K1H3S09o




Commit that? :p

Brandon
12-09-2012, 04:41 PM
Commit that? :p

Can't do that atm.. I have to wait until my new Laptop Arrives at my doorstep. Till then, everything I post is from an iPhone or from my mom's laptop.

Meh.. I'll try and commit it today if I can. I guess.

EDIT: Done.

babablksheep
12-09-2012, 07:08 PM
Thanks a bunch guys!