SRL Archive - Archive

sc6 entry #6


Markus

2011-10-26 16:45:52

This is BadBoyJH from villavu forums submitting my (hopefully) on time script for the competition.
If it is slightly late, I appologise, I have been at university for the past 12 hours.
I know you may not want to open the zip file, if you don't, Hopefully we can sort out another method of getting the files to you, but my mail client hates sending more than 1 file.

Thanks for hosting this comp, and for all the hard work you do around villavu. If there are any issues, send me an email, or preferably, PM me.

zip file had 4 files. File #3 and #4:
r_worldwalker.simba

{
This is CStrikes world walker
Edits include:
- function "WorldWalkTo" which was originally called "WalkTo",
- unused variables have been removed
}

const
// Axis offsets
X_OFFSET = 0;
Y_OFFSET = 0;
// Node points
VARROCKWESTBANK_X = 3186 + X_OFFSET;
VARROCKWESTBANK_Y = 3439 + Y_OFFSET;
FALADOREASTBANK_X = 3013 + X_OFFSET;
FALADOREASTBANK_Y = 3356 + Y_OFFSET;
LUMBRIDGENE_X = 3217 + X_OFFSET;
LUMBRIDGENE_Y = 3251 + Y_OFFSET;
DRAYNORBANK_X = 3094 + X_OFFSET;
DRAYNORBANK_Y = 3242 + Y_OFFSET;
BARBVILLAGEC_X = 3081 + X_OFFSET;
BARBVILLAGEC_Y = 3416 + Y_OFFSET;

var NodeArray : TTileArray;
currentTile : TTile; // This is the tile we're on
VWB_LNE, VWB_BBC, // Highway variables
BBC_VWB, BBC_FEB,
DRB_LNE, DRB_FEB,
LNE_DRB, LNE_VWB,
FEB_DRB, FEB_BBC : TPointArray;
Highway, SubStreet : T2DPointArray; // ATPA's

{******************************************************************************}
{ procedure SetupNodesAndPaths; }
{ By: Cstrike }
{ Description: Sets up node points and all arrays for program to function. }
{******************************************************************************}
procedure SetupNodesAndPaths;
begin
NodeArray := [Tile (VARROCKWESTBANK_X, VARROCKWESTBANK_Y), // 0 Varrock west bank
Tile (FALADOREASTBANK_X, FALADOREASTBANK_Y), // 1 Fally east bank
Tile (LUMBRIDGENE_X, LUMBRIDGENE_Y), // 2 Lumby NE
Tile (DRAYNORBANK_X, DRAYNORBANK_Y), // 3 Draynor bank
Tile (BARBVILLAGEC_X, BARBVILLAGEC_Y)]; // 4 Barb village center (S of dungeon)
// Node highway travel only
VWB_LNE := [Point(3186, 3439),
Point(3194, 3429), Point(3207, 3428), Point(3211, 3415),
Point(3211, 3400), Point(3211, 3386), Point(3213, 3372),
Point(3218, 3359), Point(3226, 3347), Point(3228, 3337),
Point(3240, 3336), Point(3240, 3326), Point(3240, 3312),
Point(3239, 3302), Point(3239, 3294), Point(3239, 3282),
Point(3241, 3275), Point(3241, 3264), Point(3227, 3261),
Point(3217, 3257), Point(3219, 3247),
Point(LUMBRIDGENE_X, LUMBRIDGENE_Y)];
VWB_BBC := [Point(3180, 3429),
Point(3169, 3428), Point(3163, 3421), Point(3151, 3417),
Point(3140, 3417), Point(3129, 3416), Point(3120, 3418),
Point(3111, 3420), Point(3099, 3420), Point(3089, 3419),
Point(BARBVILLAGEC_X, BARBVILLAGEC_Y)];
BBC_VWB := [Point (3089,3419),
Point (3099,3420), Point (3111,3420), Point (3120,3418),
Point (3129,3416), Point (3140,3417), Point (3151,3417),
Point (3163,3421), Point (3169,3428), Point (3180,3429),
Point(VARROCKWESTBANK_X, VARROCKWESTBANK_Y)];
BBC_FEB := [Point (3075,3419),
Point (3064,3417), Point (3054,3415), Point (3044,3419),
Point (3032,3426), Point (3020,3428), Point (3010,3431),
Point (3002,3431), Point (2989,3429), Point (2986,3419),
Point (2978,3412), Point (2971,3402), Point (2965,3389),
Point (2969,3379), Point (2983,3376), Point (2993,3368),
Point (3004,3363), Point (FALADOREASTBANK_X, FALADOREASTBANK_Y)];
DRB_LNE := [Point (3098,3235),
Point (3100,3230), Point (3110,3229), Point (3119,3228),
Point (3125,3225), Point (3133,3227), Point (3141,3229),
Point (3147,3235), Point (3157,3235), Point (3165,3238),
Point (3171,3239), Point (3176,3245), Point (3180,3247),
Point (3185,3245), Point (3193,3246), Point (3200,3247),
Point (3208,3246), Point (3212,3246),
Point(LUMBRIDGENE_X, LUMBRIDGENE_Y)];
DRB_FEB := [Point(3086, 3249),
Point(3080, 3256), Point(3073, 3266), Point(3072, 3276),
Point(3064, 3277), Point(3050, 3275), Point(3039, 3276),
Point(3031, 3278), Point(3021, 3276), Point(3010, 3278),
Point(3005, 3287), Point(3006, 3298), Point(3006, 3311),
Point(3006, 3320), Point(3007, 3331), Point(3008, 3345),
Point(3006, 3356), Point (FALADOREASTBANK_X, FALADOREASTBANK_Y)];
LNE_DRB := [Point(3214, 3246),
Point(3208, 3246), Point(3200, 3247), Point(3193, 3246),
Point(3185, 3245), Point(3180, 3247), Point(3176, 3245),
Point(3171, 3239), Point(3165, 3238), Point(3157, 3235),
Point(3147, 3235), Point(3141, 3229), Point(3133, 3227),
Point(3125, 3225), Point(3119, 3228), Point(3110, 3229),
Point(3100, 3230), Point(3098, 3235),
Point(DRAYNORBANK_X, DRAYNORBANK_Y)];
LNE_VWB := [Point (3223,3237),
Point (3219,3247), Point (3217,3257), Point (3227,3261),
Point (3241,3264), Point (3241,3275), Point (3239,3282),
Point (3239,3294), Point (3239,3302), Point (3240,3312),
Point (3240,3326), Point (3240,3336), Point (3228,3337),
Point (3226,3347), Point (3218,3359), Point (3213,3372),
Point (3211,3386), Point (3211,3400), Point (3211,3415),
Point (3207,3428), Point (3194,3429), Point (3186,3439),
Point (VARROCKWESTBANK_X, VARROCKWESTBANK_Y)];
FEB_DRB := [Point (3006,3356),
Point (3008,3345), Point (3007,3331), Point (3006,3320),
Point (3006,3311), Point (3006,3298), Point (3005,3287),
Point (3010,3278), Point (3021,3276), Point (3031,3278),
Point (3039,3276), Point (3050,3275), Point (3064,3277),
Point (3072,3276), Point (3073,3266), Point (3080,3256),
Point (3086,3249), Point (DRAYNORBANK_X, DRAYNORBANK_Y)];
FEB_BBC := [Point(3004, 3363),
Point(2993, 3368), Point(2983, 3376), Point(2969, 3379),
Point(2965, 3389), Point(2971, 3402), Point(2978, 3412),
Point(2986, 3419), Point(2989, 3429), Point(3002, 3431),
Point(3010, 3431), Point(3020, 3428), Point(3032, 3426),
Point(3044, 3419), Point(3054, 3415), Point(3064, 3417),
Point(3075, 3419), Point(BARBVILLAGEC_X, BARBVILLAGEC_Y)];
// Highway
SetArrayLength (Highway, 5); //Priority: FEB = VWB > DRB > LMB > BBC
Highway[0] :=[Point(BARBVILLAGEC_X, BARBVILLAGEC_Y), Point (3089,3419), // Barb vil to varrock west bank
Point (3099,3420), Point (3111,3420), Point (3120,3418),
Point (3129,3416), Point (3140,3417), Point (3151,3417),
Point (3163,3421), Point (3169,3428), Point (3180,3429),
Point(VARROCKWESTBANK_X, VARROCKWESTBANK_Y)];
Highway[1] :=[Point(LUMBRIDGENE_X, LUMBRIDGENE_Y), // Lumby northeast to varrock west bank (tiles[1..2] (note, not tiles[0]) were fucked up, check them)
Point (3217,3257), Point (3227,3261),
Point (3241,3264), Point (3241,3275), Point (3239,3282),
Point (3239,3294), Point (3239,3302), Point (3240,3312),
Point (3240,3326), Point (3240,3336), Point (3228,3337),
Point (3226,3347), Point (3218,3359), Point (3213,3372),
Point (3211,3386), Point (3211,3400), Point (3211,3415),
Point (3207,3428), Point (3194,3429),
Point (VARROCKWESTBANK_X, VARROCKWESTBANK_Y)];
Highway[2] :=[Point(BARBVILLAGEC_X, BARBVILLAGEC_Y), Point (3075,3419), // barb vil to fally east bank
Point (3064,3417), Point (3054,3415), Point (3044,3419),
Point (3032,3426), Point (3020,3428), Point (3010,3431),
Point (3002,3431), Point (2989,3429), Point (2986,3419),
Point (2978,3412), Point (2971,3402), Point (2965,3389),
Point (2969,3379), Point (2983,3376), Point (2993,3368),
Point (3004,3363), Point (FALADOREASTBANK_X, FALADOREASTBANK_Y)];
Highway[3] :=[Point (DRAYNORBANK_X, DRAYNORBANK_Y), Point(3086, 3249), // draynor bank to fally east bank
Point(3080, 3256), Point(3073, 3266), Point(3072, 3276),
Point(3064, 3277), Point(3050, 3275), Point(3039, 3276),
Point(3031, 3278), Point(3021, 3276), Point(3010, 3278),
Point(3005, 3287), Point(3006, 3298), Point(3006, 3311),
Point(3006, 3320), Point(3007, 3331), Point(3008, 3345),
Point(3006, 3356), Point (FALADOREASTBANK_X, FALADOREASTBANK_Y)];
Highway[4] :=[Point(LUMBRIDGENE_X, LUMBRIDGENE_Y), Point(3214, 3246), // lumby to draynor bank
Point(3208, 3246), Point(3200, 3247), Point(3193, 3246),
Point(3185, 3245), Point(3180, 3247), Point(3176, 3245),
Point(3171, 3239), Point(3165, 3238), Point(3157, 3235),
Point(3147, 3235), Point(3141, 3229), Point(3133, 3227),
Point(3125, 3225), Point(3119, 3228), Point(3110, 3229),
Point(3100, 3230), Point(3098, 3235), Point(DRAYNORBANK_X, DRAYNORBANK_Y)];
//Streets
SetArrayLength (SubStreet, 27);
// These paths are between the >60 west of draynor guarded gate, and lumbyNE node
SubStreet[0] := [Point(3094, 3242), Point(3100, 3244), Point(3105, 3247), // √ Inside draynor village to draynor bank
Point(3104, 3257), Point(3102, 3262), Point(3092, 3259)];
SubStreet[1] := [Point(3110, 3229), Point(3114, 3220), Point(3117, 3212), // √ Wiz tower from below draynor bank path
Point(3114, 3205), Point(3113, 3196), Point(3113, 3187),
Point(3113, 3181), Point(3113, 3171), Point(3110, 3167),
Point(3102, 3165), Point(3101, 3155), Point(3105, 3150)];
SubStreet[2] := [Point(3133, 3227), Point(3136, 3218), Point(3138, 3208), // √ Follows western sea that arcs around the two lumby mines, and ends at the lumby mine with addy/mith at the SE corner [south of lumby]
Point(3141, 3203), Point(3141, 3193), Point(3144, 3184),
Point(3143, 3177), Point(3146, 3167), Point(3148, 3158),
Point(3151, 3149), Point(3159, 3147), Point(3168, 3150),
Point(3177, 3150), Point(3186, 3148), Point(3196, 3148),
Point(3202, 3152), Point(3212, 3151), Point(3222, 3150),
Point(3234, 3150)];
SubStreet[3] := [Point(3133, 3227), Point(3137, 3218), Point(3143, 3213), // √ Goes from south of jail, to hook around the north of the swamp below lumbridge
Point(3148, 3206), Point(3154, 3202), Point(3161, 3197),
Point(3174, 3197), Point(3185, 3195), Point(3197, 3190),
Point(3202, 3185), Point(3212, 3184), Point(3219, 3176)];
SubStreet[4] := [Point(3098, 3235), Point(3092, 3228), Point(3091, 3217), // South of draynor bank
Point(3101, 3211)];
SubStreet[5] := [Point(3072, 3276), Point(3074, 3287), Point(3072, 3297), // √ Hooks north of the draynor market, and goes up to the west of draynor manor (without passing over the walls, and then hooks southeast slightly into the forest
Point(3072, 3307), Point(3076, 3314), Point(3078, 3323),
Point(3088, 3322), Point(3092, 3312)];
SubStreet[6] := [Point(3072, 3276), Point(3077, 3281), Point(3086, 3289), // √ Goes east of the draynor/south fally gate >60 total guys, follows the path to the 4 way cross, goes up to draynor manor and hooks around the right side, ending on the bottom left of the draynor manor near some grey patch
Point(3094, 3291), Point(3102, 3294), Point(3109, 3297),
Point(3113, 3303), Point(3113, 3310), Point(3111, 3318),
Point(3111, 3327), Point(3110, 3339), Point(3109, 3346),
Point(3115, 3351), Point(3123, 3351), Point(3128, 3356),
Point(3128, 3364), Point(3125, 3373), Point(3116, 3376),
Point(3109, 3376), Point(3096, 3376), Point(3091, 3374),
Point(3087, 3365), Point(3087, 3357), Point(3086, 3348),
Point(3090, 3338)];
SubStreet[7] := [Point(3157, 3235), Point(3157, 3227), Point(3160, 3221), // South of ham in lumby-west, between two trees, really close to the water symbol
Point(3167, 3212), Point(3175, 3210)];
SubStreet[8] := [Point(3157, 3235), Point(3152, 3243), Point(3143, 3253), // Runs east of the jail up by the grains and continues up to the right of draynor mansion, stopping before this hole in the white wall east of the manor
Point(3135, 3262), Point(3134, 3275), Point(3134, 3288),
Point(3134, 3300), Point(3136, 3311), Point(3141, 3320),
Point(3145, 3329), Point(3147, 3333)];
SubStreet[9] := [Point(3176, 3245), Point(3172, 3252), Point(3164, 3257), //East around ham building, north in front of windmill/grain thing, and then a tile west of that as the last additional added tile
Point(3163, 3263), Point(3161, 3271), Point(3162, 3278),
Point(3163, 3287), Point(3166, 3293), Point(3167, 3301),
Point(3159, 3310)];
SubStreet[10] :=[Point(3176, 3245), Point(3180, 3232), Point(3182, 3226), // south past the right set of rare trees (west of farming patch) so the southwest side of the lumby castle (outside the walls), does not go under the castle
Point(3185, 3218), Point(3186, 3210), Point(3194, 3204),
Point(3198, 3200)];
SubStreet[11] :=[Point(3176, 3245), Point(3179, 3251), Point(3180, 3258), // east of HAM to the west side of the sheep shearer's farm place
Point(3181, 3267)];
SubStreet[12] :=[Point(3133, 3227), Point(3130, 3235), Point(3132, 3242), // runs up through the bottom of the jail and hooks around the north from the east, to the west
Point(3130, 3248), Point(3119, 3251)];
SubStreet[13] :=[Point(3133, 3227), Point(3139, 3223), Point(3143, 3217), // Walks south of that irritating wall that seperates lumby forest from lumby swamps, remember... walks south of the wall and retrieves to the brown path
Point(3146, 3211), Point(3153, 3209), Point(3160, 3203),
Point(3172, 3203), Point(3184, 3202), Point(3191, 3197),
Point(3199, 3194), Point(3208, 3194)];
SubStreet[14] :=[Point(3217, 3251), Point(3222, 3242), Point(3225, 3235), // Walk from lumbyNE node down the path through graveyard to just east of the mining spot with addy
Point(3231, 3230), Point(3236, 3225), Point(3237, 3216),
Point(3237, 3202), Point(3243, 3199), Point(3245, 3190),
Point(3243, 3180), Point(3239, 3169), Point(3241, 3159),
Point(3237, 3147)];
SubStreet[15] :=[Point(3217, 3251), Point(3221, 3243), Point(3224, 3235), // Goes from LNE node into lumby castle, and inside right to outside the cooks door/near south spiral ladder
Point(3232, 3227), Point(3234, 3218), Point(3225, 3216),
Point(3215, 3217), Point(3214, 3209), Point(3207, 3208)];
SubStreet[16] :=[Point(3217, 3257), Point(3217, 3265), Point(3215, 3274), // takes the first tile in the path that goes from LNE->VWB
Point(3210, 3278), Point(3197, 3278), Point(3190, 3285),
Point(3189, 3294), Point(3188, 3302), Point(3185, 3308),
Point(3177, 3313)];
// These paths are between 'east of lumby bridge(s) and varrock west bank
SubStreet[17] :=[Point(3207, 3428), Point(3216, 3426), Point(3223, 3430),
Point(3232, 3431), Point(3241, 3429), Point(3254, 3429),
Point(3254, 3420)]; // Varrock east bank
SubStreet[18] :=[Point(3207, 3428), Point(3216, 3425), Point(3223, 3429),
Point(3237, 3430), Point(3249, 3430), Point(3262, 3429),
Point(3271, 3429), Point(3279, 3430), Point(3287, 3424),
Point(3288, 3414), Point(3291, 3409), Point(3292, 3401),
Point(3293, 3393), Point(3294, 3385), Point(3293, 3377),
Point(3288, 3373), Point(3286, 3367)]; // Varrock southEast mines
SubStreet[24] := [Point(3207, 3428), Point(3208, 3434), Point(3213, 3438),
Point(3213, 3446), Point(3206, 3452), Point(3200, 3458),
Point(3197, 3466), Point(3197, 3476), Point(3196, 3484),
Point(3197, 3493), Point(3196, 3499), Point(3201, 3504),
Point(3211, 3502), Point(3219, 3502), Point(3228, 3500),
Point(3231, 3488), Point(3230, 3480)]; // Goes near varrock fountain, then up and around the castle, hooking around the west side, past the yews in the north, and then into the queens garden on the east side
// These paths are between BBC and varrock west bank
SubStreet[19] :=[Point(3169, 3428), Point(3171, 3421), Point(3171, 3412),
Point(3171, 3403), Point(3171, 3395), Point(3174, 3389),
Point(3177, 3384), Point(3175, 3377), Point(3170, 3369),
Point(3173, 3363), Point(3181, 3367)]; // Varrock southWest mine near champion guild
SubStreet[20] :=[Point(3186, 3439), Point(3186, 3445), Point(3184, 3451),
Point(3175, 3452), Point(3170, 3456), Point(3164, 3465),
Point(3164, 3473), Point(3164, 3479), Point(3165, 3487)]; // Grand exchange
SubStreet[21] :=[Point(3089, 3419), Point(3086, 3426), Point(3089, 3435),
Point(3087, 3444), Point(3087, 3450), Point(3090, 3457),
Point(3088, 3460), Point(3087, 3466), Point(3082, 3467),
Point(3080, 3477), Point(3080, 3485), Point(3086, 3490),
Point(3093, 3493)]; // Edgeville
// These paths are between falador east bank and BBC

// These paths are between fally and draynor >60 level guards
SubStreet[22] :=[Point(3010, 3278), Point(3008, 3272), Point(2998, 3270),
Point(2990, 3270), Point(2983, 3265), Point(2978, 3262),
Point(2977, 3253), Point(2977, 3241)]; // Fally south (corner of farm) going to rimmington mining field
SubStreet[23] :=[Point(3039, 3276), Point(3039, 3268), Point(3038, 3261),
Point(3040, 3255), Point(3041, 3247), Point(3042, 3235),
Point(3048, 3235)]; // Slightly SE of the opening to the farm, heads almost straight down to the port and then over to the port sarim dropoff box approximately
SubStreet[25] :=[Point(3064, 3277), Point(3062, 3271), Point(3059, 3266),
Point(3059, 3260), Point(3060, 3253)]; // West of lvl 60 gate, immediately goes south and over farming patch to the trees near the sea
SubStreet[26] :=[Point(3010, 3278), Point(3002, 3277), Point(2997, 3278),
Point(2990, 3278), Point(2985, 3276), Point(2980, 3273),
Point(2978, 3268), Point(2974, 3262), Point(2968, 3257),
Point(2964, 3253), Point(2957, 3244), Point(2953, 3241),
Point(2946, 3239), Point(2943, 3231), Point(2939, 3227),
Point(2934, 3220), Point(2932, 3215), Point(2924, 3215),
Point(2922, 3207), Point(2927, 3202), Point(2934, 3199)]; // Fally crossroads SW of farm, follows path all the way down to the chemist/distiller, then goes west and hooks around to the south
end;

// Output's the TPA for debug purposes
procedure DebugTheTPA (TPA : TPointArray);
var i : Integer;
begin
writeln ('TPA debug:');
for i:=0 to high(TPA) do
begin
writeln ('['+inttostr(i)+']: Point ('+inttostr(TPA[i].x)+','+inttostr(TPA[i].y)+')');
end;
end;

// Output's the TTA for debug purposes
procedure DebugTheTTA (TTA : TTileArray);
var i : Integer;
begin
writeln ('TTA debug:');
for i:=0 to high(TTA) do
begin
writeln ('['+inttostr(i)+']: Tile ('+inttostr(TTA[i].x)+','+inttostr(TTA[i].y)+')');
end;
end;

//Easy code for a current position output
procedure DebugCurrentPos;
begin
currentTile := GetMyPos;
writeln ('DEBUG_CURRENT_TILE: Current tile = ('+inttostr(currentTile.x)+','+inttostr(currentTile.y)+')');
end;

{******************************************************************************}
{ procedure AddTPAToTTA (TPA : TPointArray; var T_TileArray : TTileArray); }
{ By: Cstrike }
{ Description: Create TTileArray from TPA }
{******************************************************************************}
procedure AddTPAToTTA (TPA : TPointArray; var T_TileArray : TTileArray);
var i, j, originalHighTTA : Integer;
begin
j:=0;
originalHighTTA := high(T_TileArray)
SetArrayLength (T_TileArray, (high(TPA)+high(T_TileArray)+2));
for i:=originalHighTTA+1 to (originalHighTTA+high(TPA))+1 do
begin
T_TileArray[i] := Tile(TPA[j].x,TPA[j].y);
Inc(j);
end;
end;

{******************************************************************************}
{ procedure AddTPAFromDownToTTA (ATPA : T2DPointArray; ATPAPos, TPAPos : Integer; var TPA : TPointArray); }
{ By: Cstrike }
{ Description: A shofrter version of CreateTPADownFromFragment (below), may }
{ screw up occasionally, don't know why. Must debug this. }
{******************************************************************************}
procedure AddTPAFromDownToTTA (ATPA : T2DPointArray; ATPAPos, TPAPos : Integer; var TPA : TPointArray);
var i : Integer;
begin
SetArrayLength (TPA, TPAPos+1);
for i:=TPAPos downto 0 do
begin
TPA[i] := ATPA[ATPAPos][i];
end;
InvertTPA (TPA);
end;

{******************************************************************************}
{ procedure CreateTPAUpFromFragment (ATPA : T2DPointArray; ATPAPos, TPAPos : Integer; var TPA : TPointArray); }
{ By: Cstrike }
{ Description: Stores a TPA from an ATPA's TPA position up until high(TPA) }
{ Ex: If you have a TPA in an ATPA from 0 to 20, and want to create TPA#2 from }
{ TPA position 16 to 20, you would enter TPAPos as 16. ATPAPos is just the }
{ index of what TPA in the ATPA you're looking for (aka, ATPA[ATPAPos]) }
{******************************************************************************}
procedure CreateTPAUpFromFragment (ATPA : T2DPointArray; ATPAPos, TPAPos : Integer; var TPA : TPointArray);
var initial, i, highATPA, TPADifference : Integer;
begin
initial := 0; // This is so the new TPA we create starts from zero, because every time I try using 'i', it ends up being something thats not zero, screwing it all up. So I just made my own variable for starting at zero
highATPA := High(ATPA[ATPAPos]);
TPADifference := (highATPA-TPAPos);
SetArrayLength (TPA, TPADifference+1);
for i:=TPAPos to highATPA do
begin
TPA[initial] := ATPA[ATPAPos][i];
Inc(initial); // Now that we've set TPA, lets increase it for next time... if it exceeds it... no big deal because it will end the loop before creating a new TPA point
end;
end;

{******************************************************************************}
{ procedure CreateTPAUpFromFragmentInvert (ATPA : T2DPointArray; ATPAPos, TPAPos : Integer; var TPA : TPointArray); }
{ By: Cstrike }
{ Description: Stores a TPA from an ATPA's TPA position up until high(TPA) }
{ Ex: If you have a TPA in an ATPA from 0 to 20, and want to create TPA#2 from }
{ TPA position 16 to 20, you would enter TPAPos as 16. ATPAPos is just the }
{ index of what TPA in the ATPA you're looking for (aka, ATPA[ATPAPos]) }
{ It is considered "Invert" because at the end it inverts the TPA fragment }
{ which is useful for when you are using WalkTo. When you are retrieving }
{ to a bank, you don't need to invert because it will always have the end }
{ tile as being the bank node, but if you try and use this while walking }
{ to a branch point (to branch off on a subpath to get near your TPoint), }
{ the other function will make it so that it will always make you return }
{ to a node point. Thus, invert makes you walk in the opposite direction }
{ from a node point to your branch-off-from-the-highway-point }
{******************************************************************************}
procedure CreateTPAUpFromFragmentInvert (ATPA : T2DPointArray; ATPAPos, TPAPos : Integer; var TPA : TPointArray);
var initial, i, highATPA, TPADifference : Integer;
begin
initial := 0; // This is so the new TPA we create starts from zero, because every time I try using 'i', it ends up being something thats not zero, screwing it all up. So I just made my own variable for starting at zero
highATPA := High(ATPA[ATPAPos]);
TPADifference := (highATPA-TPAPos);
SetArrayLength (TPA, TPADifference+1);
for i:=TPAPos to highATPA do
begin
TPA[initial] := ATPA[ATPAPos][i];
Inc(initial); // Now that we've set TPA, lets increase it for next time... if it exceeds it... no big deal because it will end the loop before creating a new TPA point
end;
InvertTPA (TPA);
end;

{******************************************************************************}
{ procedure CreateTPADownFromFragment (ATPA : T2DPointArray; ATPAPos, TPAPos : Integer; var TPA : TPointArray); }
{ By: Cstrike }
{ Description: Stores a TPA from an ATPA's TPA position down until TPA[0] }
{ Ex: If you have a TPA in an ATPA from 0 to 20, and want to create TPA#2 from }
{ TPA position 7 to 0 (NOT from 0 to 7!), you would enter TPAPos as 7. }
{ ATPAPos is just the index of what TPA in the ATPA you're looking for }
{ (aka, ATPA[ATPAPos]) }
{******************************************************************************}
procedure CreateTPADownFromFragment (ATPA : T2DPointArray; ATPAPos, TPAPos : Integer; var TPA : TPointArray);
var initial, i, highATPA, TPADifference : Integer;
begin
initial := 0; // This is so the new TPA we create starts from zero, because every time I try using 'i', it ends up being something thats not zero, screwing it all up. So I just made my own variable for starting at zero
highATPA := High(ATPA[ATPAPos]);
TPADifference := (highATPA-TPAPos);
SetArrayLength (TPA, TPAPos+1);
writeln ('TPADif = ' +inttostr(TPADifference));
for i:=TPAPos downto 0 do // Start from our TPA position (lets say were 7 of 20, start at position 7), and then go down to position zero
begin
TPA[initial] := ATPA[ATPAPos][i];
Inc(initial); // Now that we've set TPA, lets increase it for next time... if it exceeds it... no big deal because it will end the loop before creating a new TPA point
end;
end;

{******************************************************************************}
{ procedure CreateTPADownFromFragmentInvert (ATPA : T2DPointArray; ATPAPos, TPAPos : Integer; var TPA : TPointArray); }
{ By: Cstrike }
{ Description: Stores a TPA from an ATPA's TPA position down until TPA[0] }
{ Ex: If you have a TPA in an ATPA from 0 to 20, and want to create TPA#2 from }
{ TPA position 7 to 0 (NOT from 0 to 7!), you would enter TPAPos as 7. }
{ ATPAPos is just the index of what TPA in the ATPA you're looking for }
{ (aka, ATPA[ATPAPos]). Inverts at the end (see CTPAUFFInvert for details) }
{ (aka, does from 0 to 7 ;) ...) }
{******************************************************************************}
procedure CreateTPADownFromFragmentInvert (ATPA : T2DPointArray; ATPAPos, TPAPos : Integer; var TPA : TPointArray);
var initial, i, highATPA, TPADifference : Integer;
begin
initial := 0; // This is so the new TPA we create starts from zero, because every time I try using 'i', it ends up being something thats not zero, screwing it all up. So I just made my own variable for starting at zero
highATPA := High(ATPA[ATPAPos]);
TPADifference := (highATPA-TPAPos);
SetArrayLength (TPA, TPAPos+1);
writeln ('TPADif = ' +inttostr(TPADifference));
for i:=TPAPos downto 0 do // Start from our TPA position (lets say were 7 of 20, start at position 7), and then go down to position zero
begin
TPA[initial] := ATPA[ATPAPos][i];
Inc(initial); // Now that we've set TPA, lets increase it for next time... if it exceeds it... no big deal because it will end the loop before creating a new TPA point
end;
InvertTPA (TPA);
end;

{******************************************************************************}
{ procedure RemoveTPFromTPA (TPA : TPointArray; Index : Integer); }
{ By: Cstrike }
{ Description: Removes TPA[Index] and truncates TPA that you input }
{******************************************************************************}
procedure RemoveTPFromTPA (TPAToRemoveFrom, ModifiedTPA : TPointArray; Index : Integer);
var i, j : Integer;
begin
j := 0;
if Index > High(TPAToRemoveFrom) then
begin
writeln ('Warning, index greater than what TPA has, setting new TPA to old TPA');
ModifiedTPA := TPAToRemoveFrom;
Exit;
end;
for i:=0 to high(TPAToRemoveFrom) do
begin
SetArrayLength (ModifiedTPA,high(TPAToRemoveFrom));
if i <> index then
begin
ModifiedTPA[j] := TPAToRemoveFrom[i];
writeln ('J = '+inttostr(j));
//DebugTheTPA (ModifiedTPA);
Inc(j);
end;
end;
writeln ('RemoveTPFromTPA result:');
DebugTheTPA (ModifiedTPA);
end;

{******************************************************************************}
{ function TMin (TIA : TIntegerArray) : Integer; }
{ By: Cstrike }
{ Description: Sets TIA[0] as the lowest number }
{******************************************************************************}
function TMin (TIA : TIntegerArray) : Integer;
begin
QuickSort (TIA);
if high(TIA) > 0 then result := TIA[0] else result := 0;
end;

{******************************************************************************}
{ procedure FindTPInATPA (TP : TPoint; ATPA : T2DPointArray; var ATPAPos, TPAPos : Integer); }
{ By: Cstrike }
{ Description: Searches an ATPA for a TPoint. Returns the ATPA index and the }
{ TPA index of where the TPoint is located. Only returns one position, which }
{ is the last one it will find }
{******************************************************************************}
procedure FindTPInATPA (TP : TPoint; ATPA : T2DPointArray; var ATPAPos, TPAPos : Integer);
var i, j : integer;
begin
if not LoggedIn then exit;
writeln ('Debugging: Requested to find Point('+inttostr(TP.x)+','+inttostr(TP.y)+') in an ATPA');
ATPAPos := 0;
TPAPos := 0;
for i:=0 to high(ATPA) do
begin
for j:=0 to high(ATPA[i]) do
begin
if ATPA[i][j] = TP then
begin
ATPAPos := i;
writeln ('ATPApos = '+inttostr(i));
TPAPos := j;
writeln ('TPApos = '+inttostr(j));
end;
end;
end;
end;

{******************************************************************************}
{ function FindPathToTile (TP : TPoint; walkRadius : Integer) : Boolean; }
{ By: Cstrike }
{ Description: Attemps to walk (blindly) towards the TPoint (or TTile, since }
{ the TPoint is converted). X increases as you go east, Y as you go north. }
{ Needs serious code fixing, but it works. WalkRadius is how many tiles it }
{ will walk in each increment. Shouldn't use a radius that is larger than }
{ the minimap. Should not use zero, try and keep it between 2 and 12. }
{******************************************************************************}
function FindPathToTile (TP : TPoint; walkRadius : Integer) : Boolean;
var currentTile, walkTile, desiredTile : TTile;
i, hyp, increments, cx, cy, xincI, yincI : Integer;
xinc, yinc : Extended;
begin
if not LoggedIn then exit;
if walkRadius < 1 then // If human is stupid then
begin
writeln ('Warning, walkRadius < 1, exiting...');
result := false;
exit;
end;
currentTile := GetMyPos;
writeln ('current tile ('+inttostr(currentTile.x)+','+inttostr(currentTile.y)+')');
desiredTile := PointToTile (TP);
writeln ('desired point ('+inttostr(TP.x)+','+inttostr(TP.y)+')');
hyp := Distance (currentTile.x, currentTile.y, TP.x, TP.y);
writeln ('hypotenuse = ' + inttostr(hyp));
increments := round(hyp/walkRadius);
writeln ('increments = '+inttostr(increments));
if increments > 0 then
begin
xinc := ((currentTile.x - TP.x)/increments);
yinc := ((currentTile.y - TP.y)/increments);
xinc := abs (xinc);
yinc := abs (yinc);
xincI := round (xinc);
yincI := round (yinc);
writeln ('x incs = '+floattostr(xinc));
writeln ('y incs = '+floattostr(yinc));
cx := currentTile.x;
cy := currentTile.y;
if (currentTile.x <= TP.x) and (currentTile.y <= TP.y) then
begin
writeln ('current tile x < TP.x, currentTile.y < TP.y');
for i:=0 to increments-1 do
begin
cx := cx + xincI;
cy := cy + yincI;
walkTile := Tile (cx, cy);
WalkToTile (walkTile, 0, 1); // BOOLEAN FALSE
end;
end else
if (currentTile.x >= TP.x) and (currentTile.y <= TP.y) then
begin
writeln ('current tile x > TP.x, currentTile.y < TP.y');
for i:=0 to increments-1 do
begin
cx := cx - xincI;
cy := cy + yincI;
walkTile := Tile (cx, cy);
WalkToTile (walkTile, 0, 1); // BOOLEAN FALSE
end;
end else
if (currentTile.x <= TP.x) and (currentTile.y >= TP.y) then
begin
writeln ('current tile x < TP.x, currentTile.y > TP.y');
for i:=0 to increments-1 do
begin
cx := cx + xincI;
cy := cy - yincI;
walkTile := Tile (cx, cy);
WalkToTile (walkTile, 0, 1); // BOOLEAN FALSE
end;
end else
if (currentTile.x >= TP.x) and (currentTile.y >= TP.y) then
begin
writeln ('current tile x > TP.x, currentTile.y > TP.y');
for i:=0 to increments-1 do
begin
cx := cx - xincI;
cy := cy - yincI;
walkTile := Tile (cx, cy);
WalkToTile (walkTile, 0, 1); // BOOLEAN FALSE
end;
end;
end else // If increments = 0
begin
result := true;
writeln ('No need to use PathFinder, were in TPA range');
end;
if TileOnMM (desiredTile) then
begin
writeln ('Good news, tile is on minimap!');
result := true;
end else
if not TileOnMM (desiredTile) then
begin
writeln ('Tile is NOT on the minimap');
result := false;
end;
end;

{******************************************************************************}
{ function SubPointDistances (ATPA : T2DPointArray) : TPoint; }
{ By: Cstrike }
{ Description: Returns TPoint from ATPA which is closest to current position }
{******************************************************************************}
function SubPointDistances (ATPA : T2DPointArray) : TPoint;
var distArrLowest, tempdistArrLowest, distTPAInt, tempdistTPATInt : TIntegerArray;
distArrLowestTP : TPointArray;
currentTile : TTile;
i, j, k, z : Integer;
begin
if not LoggedIn then exit;
currentTile := GetMyPos; // Don't remove this, it's needed
writeln ('SubPointDist: Current tile = ('+inttostr(currentTile.x)+','+inttostr(currentTile.y)+')');
writeln ('high(ATPA) = ' + inttostr(high(ATPA)));
SetArrayLength (distArrLowest, high(ATPA)+1); // The array that holds all the *smallest* distances from each TPA
SetArrayLength (tempdistArrLowest, high(ATPA)+1);
SetArrayLength (distArrLowestTP, high(ATPA)+1);
for i:=0 to high(ATPA) do // For the entire ATPA do...
begin
//writeln ('high(ATPA)[i] = ' + inttostr(high(ATPA[i])));
SetArrayLength (distTPAInt, high(ATPA[i])+1);
SetArrayLength (tempdistTPATInt, high(ATPA[i])+1);
for j:=0 to high(ATPA[i]) do // For each TPA in ATPA do...
begin
distTPAInt[j] := Distance (currentTile.x, currentTile.y, ATPA[i][j].x, ATPA[i][j].y);
tempdistTPATInt[j] := Distance (currentTile.x, currentTile.y, ATPA[i][j].x, ATPA[i][j].y);
//DEBUGDEBUGwriteln ('ATPA['+inttostr(i)+']['+inttostr(j)+'] distance = '+inttostr(distTPAInt[j])+' ('+inttostr(ATPA[i][j].x)+','+inttostr(ATPA[i][j].y)+')'); // Debug
if j = high(ATPA[i]) then // When we reach the top of our TPA, do the following [only because I cant do this outside the for loop...]
begin
TMin (tempdistTPATInt); // Return the integer thats the SMALLEST distance from the TIntegerArray
writeln ('Minimum distance (tempdistTPAInt[0])= '+inttostr(tempdistTPATInt[0]));
distArrLowest[i] := tempdistTPATInt[0];
tempdistArrLowest[i] := tempdistTPATInt[0];
for k:=0 to high(ATPA[i]) do // This goes back and gives us the TPoint that matches up with the smallest distance, and stores it in an array for future decisions
begin
if distArrLowest[i] = distTPAInt[k] then
begin
distArrLowestTP[i] := ATPA[i][k];
//writeln ('distArrLowestTP['+inttostr(i)+'] = ('+inttostr(distArrLowestTP[i].x)+','+inttostr(distArrLowestTP[i].y)+')');
end;
end;
end;
end;
end;
for z:=0 to high(ATPA) do // Debug output to get a nice chart :)
begin
writeln ('distArrLowest['+inttostr(z)+'] = '+inttostr(distArrLowest[z])+' @ distArrLowestTP['+inttostr(z)+'] ('+inttostr(distArrLowestTP[z].x)+','+inttostr(distArrLowestTP[z].y)+')');
end;
TMin (tempdistArrLowest);
for z:=0 to high(ATPA) do
begin
if tempdistArrLowest[0] = distArrLowest[z] then
begin
writeln ('Smallest distance is ['+inttostr(z)+'] = '+inttostr(distArrLowest[z])+' @ distArrLowestTP['+inttostr(z)+'] ('+inttostr(distArrLowestTP[z].x)+','+inttostr(distArrLowestTP[z].y)+')');
result := distArrLowestTP[z];
end;
end;
end;

{******************************************************************************}
{ function SubPointDistancesTP (ATPA : T2DPointArray, TP : TPoint) : TPoint; }
{ By: Cstrike }
{ Description: Returns TPoint from ATPA which is closest to a TP you input }
{******************************************************************************}
function SubPointDistancesTP (ATPA : T2DPointArray; TP : TPoint) : TPoint;
var distArrLowest, tempdistArrLowest, distTPAInt, tempdistTPATInt : TIntegerArray;
distArrLowestTP : TPointArray;
currentTile : TTile;
i, j, k, z : Integer;
begin
if not LoggedIn then exit;
currentTile := PointToTile(TP); // Don't remove this, it's needed
writeln ('SubPointDist: Current tile = ('+inttostr(currentTile.x)+','+inttostr(currentTile.y)+')');
writeln ('high(ATPA) = ' + inttostr(high(ATPA)));
SetArrayLength (distArrLowest, high(ATPA)+1); // The array that holds all the *smallest* distances from each TPA
SetArrayLength (tempdistArrLowest, high(ATPA)+1);
SetArrayLength (distArrLowestTP, high(ATPA)+1);
for i:=0 to high(ATPA) do // For the entire ATPA do...
begin
writeln ('Debugging: high(ATPA)[i] = ' + inttostr(high(ATPA[i])));
SetArrayLength (distTPAInt, high(ATPA[i])+1);
SetArrayLength (tempdistTPATInt, high(ATPA[i])+1);
for j:=0 to high(ATPA[i]) do // For each TPA in ATPA do...
begin
distTPAInt[j] := Distance (currentTile.x, currentTile.y, ATPA[i][j].x, ATPA[i][j].y);
tempdistTPATInt[j] := Distance (currentTile.x, currentTile.y, ATPA[i][j].x, ATPA[i][j].y);
writeln ('Debugging: ATPA['+inttostr(i)+']['+inttostr(j)+'] distance = '+inttostr(distTPAInt[j])+' ('+inttostr(ATPA[i][j].x)+','+inttostr(ATPA[i][j].y)+')'); // Debug
if j = high(ATPA[i]) then // When we reach the top of our TPA, do the following [only because I cant do this outside the for loop...]
begin
TMin (tempdistTPATInt); // Return the integer thats the SMALLEST distance from the TIntegerArray
writeln ('Debugging: Minimum distance (tempdistTPAInt[0])= '+inttostr(tempdistTPATInt[0]));
distArrLowest[i] := tempdistTPATInt[0];
tempdistArrLowest[i] := tempdistTPATInt[0];
for k:=0 to high(ATPA[i]) do // This goes back and gives us the TPoint that matches up with the smallest distance, and stores it in an array for future decisions
begin
if distArrLowest[i] = distTPAInt[k] then
begin
distArrLowestTP[i] := ATPA[i][k];
//writeln ('distArrLowestTP['+inttostr(i)+'] = ('+inttostr(distArrLowestTP[i].x)+','+inttostr(distArrLowestTP[i].y)+')');
end;
end;
end;
end;
end;
for z:=0 to high(ATPA) do // Debug output to get a nice chart :)
begin
writeln ('distArrLowest['+inttostr(z)+'] = '+inttostr(distArrLowest[z])+' @ distArrLowestTP['+inttostr(z)+'] ('+inttostr(distArrLowestTP[z].x)+','+inttostr(distArrLowestTP[z].y)+')');
end;
TMin (tempdistArrLowest);
for z:=0 to high(ATPA) do
begin
if tempdistArrLowest[0] = distArrLowest[z] then
begin
writeln ('Smallest distance is ['+inttostr(z)+'] = '+inttostr(distArrLowest[z])+' @ distArrLowestTP['+inttostr(z)+'] ('+inttostr(distArrLowestTP[z].x)+','+inttostr(distArrLowestTP[z].y)+')');
result := distArrLowestTP[z];
end;
end;
end;

{******************************************************************************}
{ function AssignNodeLocation (maxTileRadius : integer) : String; }
{ By: Cstrike }
{ Description: Using reflection tiles, it will assess your current position }
{ and based on how large of a tile radius you input, it will return the three }
{ letter node you are at. If it doesn't work, it returns as an empty string }
{******************************************************************************}
function AssignNodeLocation (maxTileRadius : integer) : String;
var i : Integer;
currentTile : TTile;
location : String;
begin
if not LoggedIn then exit;
currentTile := GetMyPos;
location := ''; // This is for failsafes
for i:=0 to high(NodeArray) do
begin
if (currentTile.x < (NodeArray[i].x+maxTileRadius)) and (currentTile.x > (NodeArray[i].x-maxTileRadius)) and (currentTile.y < (NodeArray[i].y+maxTileRadius)) and (currentTile.y > (NodeArray[i].y-maxTileRadius)) then // If were in a box defined by the given radius then...
begin
case i of
0: location := 'VWB';
1: location := 'FEB';
2: location := 'LNE';
3: location := 'DRB';
4: location := 'BBC';
end;
end;
end;
if location = '' then // If we can't change the variable to any text then...
begin
location := 'none';
end;
writeln ('In node range = ('+location+')');
result := location;
end;

{******************************************************************************}
{ procedure procedure TravelToNode (startNode, endNode : string); }
{ By: Cstrike }
{ Description: Travels between nodes. Must use node names. Current names are: }
{ VWB = varrock west bank FEB = falador east bank BBC = barb village center }
{ (south of dungeon entrance) DRB = draynor bank LNE = Lumbridge, northeast of }
{ the lumby castle. Use upper case for now }
{******************************************************************************}
procedure TravelToNode (startNode, endNode : string);
var pathToWalk : TPointArray;
pathToWalkTTA : TTileArray;
begin
if not LoggedIn then exit;
writeln ('Path requested ["'+startNode+ '" to "'+endNode+'"]');
case startNode of
// Varrock west bank
'VWB':
begin
case endNode of
'FEB': pathToWalk := CombineTPA(VWB_BBC, BBC_FEB);
'LNE': pathToWalk := VWB_LNE;
'DRB': pathToWalk := CombineTPA(VWB_LNE, LNE_DRB);
'BBC': pathToWalk := VWB_BBC;
end;
end;
// Falador East bank
'FEB':
begin
case endNode of
'VWB': pathToWalk := CombineTPA(FEB_BBC, BBC_VWB);
'LNE': pathToWalk := CombineTPA(FEB_DRB, DRB_LNE);
'DRB': pathToWalk := FEB_DRB;
'BBC': pathToWalk := FEB_BBC;
end;
end;
// Lumbridge north east
'LNE':
begin
case endNode of
'VWB': pathToWalk := LNE_VWB;
'FEB': pathToWalk := CombineTPA(LNE_DRB, DRB_FEB);
'DRB': pathToWalk := LNE_DRB;
'BBC': pathToWalk := CombineTPA(LNE_VWB, VWB_BBC);
end;
end;
// Draynor bank
'DRB':
begin
case endNode of
'VWB': pathToWalk := CombineTPA(DRB_LNE, LNE_VWB);
'FEB': pathToWalk := DRB_FEB;
'LNE': pathToWalk := DRB_LNE;
'BBC': pathToWalk := CombineTPA(DRB_FEB, FEB_BBC);
end;
end;
// Barbarian village center
'BBC':
begin
case endNode of
'VWB': pathToWalk := BBC_VWB;
'FEB': pathToWalk := BBC_FEB;
'LNE': pathToWalk := CombineTPA(BBC_VWB, VWB_LNE);
'DRB': pathToWalk := CombineTPA(BBC_FEB, FEB_DRB);
end;
end;
end; // End of all cases
AddTPAToTTA (pathToWalk, pathToWalkTTA);
if WalkPath (pathToWalkTTA) then
begin
writeln ('Successfully walked');
end else
begin
writeln ('Failure in walking');//["'+startNode+ '" to "'+endNode+'"]');
end;
end;

{******************************************************************************}
{ function RetrieveToClosestHighwayPoint : TPoint; }
{ By: Cstrike }
{ Description: Using the SubStreet ATPA, it will search for the closest TPoint }
{ and then it will walk that path until the last TPoint in the path. Returns }
{ the last TPoint in the path. This SHOULD be a TPoint on a highway or later }
{ parts of the script probably wont work unless you re-code it }
{ Ex: Takes you from your location through a substreet to SubStreet[i][0], }
{ which is a highway point (or should be). The A next to TPAPosA/ATPAPosA }
{ has no actual meaning, just a placeholder to be 'different'. Sorry. }
{******************************************************************************}
// THIS IS THE MESSED UP PROCEDURE
// Should return us to the closest highway point.
function RetrieveToClosestHighwayPoint : TPoint;
var TPSubstreetClosest, TPHighwayClosest, currentPosTP : TPoint;
TPA : TPointArray;
ATPAposA, TPAPosA, highTPA : Integer;
TTA, singleTTA : TTileArray;
myCurrentPos, HighwayClosestTile : TTile;
begin
if not LoggedIn then exit;
TPHighwayClosest := SubPointDistances (Highway); // Search all highways and return closest highway point
TPSubstreetClosest := SubPointDistances (SubStreet); // Searches ALL the substreets, and returns TP as the closest point
myCurrentPos := GetMyPos;
currentPosTP := TileToPoint (myCurrentPos);

// If were closer to a highway than a path...
if Distance (TPHighwayClosest.x, TPHighwayClosest.y, currentPosTP.x, currentPosTP.y) < Distance (TPSubstreetClosest.x, TPSubstreetClosest.y, currentPosTP.x, currentPosTP.y) then
begin
writeln ('Debugging: RetrieveToClosestHighwayPoint says were closer to highway than a substreet');
DebugCurrentPos; // Debug
HighwayClosestTile := PointToTile (TPHighwayClosest);
if TileOnMM (HighwayClosestTile) then
begin
singleTTA := [HighwayClosestTile];
if WalkPath (singleTTA) then writeln ('Debugging: Walked successfully to closest highway tile') else writeln ('WARNING: Could not walk to closest highway tile. Function soon to implode');
end else
begin
FindPathToTile (HighwayClosestTile, 7); // Change this if it sucks
end;
result := TPHighwayClosest; // Needs more failsafes
end else // Else if were closer to a substreet path than the highway...
begin
writeln ('Debugging: RetrieveToClosestHighwayPoint says were closer to a substreet rather than a highway');
//WARNING: Added TPSubstreetClosest to the next procedure, haven't tested it
FindTPInATPA (TPSubstreetClosest, SubStreet, ATPAposA, TPAPosA); // Searches all the substreets to find which TPA in the ATPA contains our point [aka: finds a TPoint in an ATPA], if multiple return for whatever reason, it will take the last one it finds I guess. Note, the last two variables are position remembering (aka: remembers the slot in the ATPA and TPA)
AddTPAFromDownToTTA (SubStreet, ATPAPosA, TPAPosA, TPA); // Now that it knows the ATPA/TPA/TP, it will take the TPoint it found, using its location and go along the TPA backwards from TPA[i] to TPA[0], which is technically our retrieved path. Remember, all our paths were designed from the highway and branch out, so it makes sense to find our spot and work backwards to a highway
AddTPAToTTA (TPA, TTA); // With this TPA we made above, convert it to a TTileArray for reflection
WalkPath (TTA); // Walk us to the point in the Highway[?]
DebugCurrentPos; // Debug
FFlag(0);
writeln ('Now trying to get to nearest node'); wait (3000); // Debug
highTPA := high(TPA);
writeln ('TPA[0] = ('+inttostr(TPA[highTPA].x)+','+inttostr(TPA[highTPA].y)+')'); // Debug
result := SubStreet[ATPAPosA][0]; // Returns the TPoint that
end;
end;

{******************************************************************************}
{ function RetrieveToClosestNode : String; }
{ By: Cstrike }
{ Description: Returns a string of the node you went to. It will return three }
{ lettered node in capitals. }
{ Ex: This procedure walks the closest street to a highway, then walks the }
{ highway to a node, then returns the node name for use in other functions }
{******************************************************************************}
function RetrieveToClosestNode : String;
var TP : TPoint;
TPA : TPointArray;
ATPAPosH, TPAPosH, highTPA : Integer;
TTA : TTileArray;
begin
if not LoggedIn then exit;
// DEBUG OCT 10th 2010, This is where it's messing up... below:
TP := RetrieveToClosestHighwayPoint; // This will first walk us on a street towards a highwaypoint, and then return the highway point that it reached
writeln ('Debugging: RetrieveToClosestHighwayPoint, says this: Point('+inttostr(TP.x)+','+inttostr(TP.y)+') in an ATPA');
FindTPInATPA (TP, Highway, ATPAPosH, TPAPosH); // Find our location in terms of ATPA[ATPAPosH][TPAPosH]
highTPA := high(Highway[ATPAPosH]); // This gives us how big our array is, so we can later determine which node we are closer to (since it has to decide between which 2 to walk to... and the closer looks less obvious right? Imagine being next to draynor and walking all the way to lumby)
writeln ('highTPA = '+inttostr(highTPA)); // Debug
if TPAPosH >= (highTPA/2) then // If we are in the upper half of the TPA [or middle] then
begin
writeln ('Greater than half, do the UpFragment');
CreateTPAUpFromFragment (Highway, ATPAPosH, TPAPosH, TPA);
end else // Else if we are in the lower half of the TPA then
begin
writeln ('Less than half, do the DownFragment');
CreateTPADownFromFragment (Highway, ATPAPosH, TPAPosH, TPA);
end;
DebugTheTPA (TPA);
AddTPAToTTA (TPA, TTA);
WalkPath (TTA);
result := AssignNodeLocation (8);
writeln ('Result: '+result);
end;

{******************************************************************************}
{ function DetermineNodeName (TP : TPoint) : String }
{ By: Cstrike }
{ Description: Checks node TP's with inputted TP and returns node name. If no }
{ node is found, returns ''. }
{******************************************************************************}
function DetermineNodeName (TP : TPoint) : String;
begin
if not LoggedIn then exit;
writeln ('DetermineNodeNameFunction: Point("'+inttostr(TP.x)+ '" to "'+inttostr(TP.y)+'")');
result := '';
case TP of
Point((VARROCKWESTBANK_X + X_OFFSET),(VARROCKWESTBANK_Y + Y_OFFSET)):
begin
result := 'VWB';
writeln ('Debugging: Node name determined = '+result);
end;
Point((FALADOREASTBANK_X + X_OFFSET),(FALADOREASTBANK_Y + Y_OFFSET)):
begin
result := 'FEB';
writeln ('Debugging: Node name determined = '+result);
end;
Point((LUMBRIDGENE_X + X_OFFSET),(LUMBRIDGENE_Y + Y_OFFSET)):
begin
result := 'LNE';
writeln ('Debugging: Node name determined = '+result);
end;
Point((DRAYNORBANK_X + X_OFFSET),(DRAYNORBANK_Y + Y_OFFSET)):
begin
result := 'DRB';
writeln ('Debugging: Node name determined = '+result);
end;
Point((BARBVILLAGEC_X + X_OFFSET),(BARBVILLAGEC_Y + Y_OFFSET)):
begin
result := 'BBC';
writeln ('Debugging: Node name determined = '+result);
end;
end;
end;

{******************************************************************************}
{ procedure GoToNodeFromAnywhere (Location : string); }
{ By: Cstrike }
{ Description: Takes you from anywhere, to the location you want. Location you }
{ input should be 3 capital letters like VWB. Should only use defined nodes, }
{ don't try entering something like VEB unless in the future it is defined as }
{ a node to actually go to. Use FEB/VWB/BBC/LNE/DRB for now }
{******************************************************************************}
procedure GoToNodeFromAnywhere (Location : string);
var startNode : String;
begin
if not LoggedIn then exit;
startNode := RetrieveToClosestNode;
if (startNode = Location) then writeln ('Already at '+Location) // This prevents TravelToNode from attempting to walk with 0 TTiles (which crashes the script)
else TravelToNode (startNode, Location);
end;

// If distance < 10 in WalkTo from highway or it's closest to a highway...
// TP is the point you overall want to end up at, at the end of this entire script
// ClosestHighwayTP is the TPoint on the highway that is where you're going to stop, and then start [blindwalking if need be] towards your point
procedure RetrieveWalkCloseToHighway (TP, ClosestHighwayTP : TPoint);
var
ATPAPos, TPAPos, highTPA : Integer;
TPA : TPointArray;
TTA : TTileArray;
TileToWalkTo : TTile;
nodeName : String;
begin
writeln ('Debugging: RetreiveWalkCloseToHighway');
writeln ('Debugging: TP = Point('+inttostr(TP.x)+','+inttostr(TP.y)+') in an ATPA');
writeln ('Debugging: ClosestHighwayTP = Point('+inttostr(ClosestHighwayTP.x)+','+inttostr(ClosestHighwayTP.y)+') in an ATPA');
FindTPInATPA (ClosestHighwayTP, Highway, ATPAPos, TPAPos); // Find where our closest highway TP (relative to our requested spot) is in the ATPA 'highway'
highTPA := high(Highway[ATPAPos]); // This gives us how big our array is, so we can later determine which node we are closer to (since it has to decide between which 2 to walk to... and the closer looks less obvious right? Imagine being next to draynor and walking all the way to lumby)
writeln ('highTPA = '+inttostr(highTPA)); // Debug
if TPAPos >= (highTPA/2) then // If we are in the upper half of the TPA [or middle] then
begin
writeln ('Greater than half, do the UpFragment and invert');
CreateTPAUpFromFragmentInvert (Highway, ATPAPos, TPAPos, TPA);
end else // Else if we are in the lower half of the TPA then
begin
writeln ('Less than half, do the DownFragment and invert');
CreateTPADownFromFragmentInvert (Highway, ATPAPos, TPAPos, TPA);
end;
DebugTheTPA (TPA); // Debug output
nodeName := DetermineNodeName (TPA[0]); // Our node SHOULD be at TPA[0], so find what node we should end up at
AddTPAToTTA (TPA, TTA);
DebugTheTTA (TTA); // Debug
// WALK TIME!! So far up to here is good debug
//DEBUG/////////////////////////////////////////
GoToNodeFromAnywhere (nodeName); // First, go to closest node
WalkPath (TTA); // Now that were at the node, walk the path
wait (random(500)); // Now wait for safe measure ;)
TileToWalkTo := PointToTile (TP); // WalkToTile (TP) here
if TileOnMM (TileToWalkTo) then
begin
writeln ('Desired tile on minimap, attempting to walk to it');
WalkToTile (TileToWalkTo, 1, 0);
end else
begin
writeln ('Desired tile NOT on minimap, attempting to blindwalk to it');
FindPathToTile (TP, 9); // Change walk radius of 9 if you think its too much
end;
{
CurrentTile := GetMyPos;
result := true;
if ((currentTile.x - TP.x) < 4) or ((currentTile.x - TP.x) > -4) or ((currentTile.y - TP.y) < 4) or ((currentTile.y - TP.y) > -4) then
begin
writeln ('We are greater than 4 tiles away from desired point('+inttostr(TP.x)+','+inttostr(TP.y)+')');
result := false;
end else writeln ('At tile!!');
}
end;


// If highway >= 10 away from WalkTo and Substreet is a shorter distance than Highway
procedure RetrieveWalkCloseToSubstreet (TP, ClosestHighwayTP : TPoint);
var
closestTP, rootSubstreetTP : TPoint;
ATPAPosS, TPAPosS, ATPAPosH, TPAPosH, highTPA, highTPAHighway : Integer;
FullWalkingPath, SubStreetDesiredPath : TPointArray;
TileToWalkTo : TTile;
startFromIndexZero : Boolean; // If this is true in the script, it will use substreets to get to required TP, false means it will use a highway and then attempt to walk to it
nodeName : String;
begin
if not LoggedIn then exit;
writeln ('**Beginning RetrieveWalkCloseToSubstreet');
closestTP := SubPointDistancesTP(SubStreet, TP); //Find closest point in ATPA.TPA
FindTPInATPA (closestTP, SubStreet, ATPAPosS, TPAPosS); //Determine what index it is, the S next to ATPAPos means 'S'ubstreet (since H is for 'H'ighway)
writeln ('WalkTo(Substreet) ATPAPos = '+inttostr(ATPAPosS)); writeln ('WalkTo(Substreet) TPAPos = '+inttostr(TPAPosS)); // DEBUG
rootSubstreetTP := SubStreet[ATPAPosS][0]; //Find what highway it connects to, since the SubStreet[ATPAPos][0] HAS to be a TPoint on the Highway ATPA
FindTPInATPA (rootSubstreetTP, Highway, ATPAPosH, TPAPosH); // Finds what highway index were looking for, and what point to walk from [The H next to ATPAPos/TPAPos is used for 'H'ighway, because ATPAPos is for the substreet)
highTPAHighway := high(Highway[ATPAPosH]); // This gives us how big our array is, so we can later determine which node we are closer to (since it has to decide between which 2 to walk to... and the closer looks less obvious right? Imagine being next to draynor and walking all the way to lumby)
writeln ('highTPASubstreet = '+inttostr(highTPA)); writeln ('highTPAHighway = '+inttostr(highTPAHighway)); // Debug
startFromIndexZero := false; // This is used when generating our big walk, whether to start from the top or bottom of the highway array, if true... starts from Highway[i][0]
writeln ('**Beginning HighwayNodeName determination');
if TPAPosH >= (highTPAHighway/2) then // Search if we branch off in the upper half of the highway, or the lower half of the highway
begin
writeln ('Greater than half, search highest TPA point for node');
writeln ('Using Highway['+inttostr(ATPAPosH)+']['+inttostr(highTPAHighway)+']');
nodeName := DetermineNodeName (Highway[ATPAPosH][highTPAHighway]); // Search the top of the Highway[Index] array, since the top of the array will be a node position, and we are in the upper half of the array lets just go to the closest one ;)
writeln ('Node name determined that is closest: '+nodeName);
end else // Else if we are in the lower half of the TPA then
begin
writeln ('Less than half, search TPA[0] for node');
writeln ('Using Highway['+inttostr(ATPAPosH)+'][0]');
nodeName := DetermineNodeName (Highway[ATPAPosH][0]);
writeln ('Node name determined that is closest: '+nodeName); // Same as the code slightly above ^^^ except were in lower half so check the bottom of the array
startFromIndexZero := true;
end;
writeln ('**Beginning FullWalkingPath creation: Create highway path');
if startFromIndexZero then // If we started getting the highway from Highway[ATPAPosH][0] then do this stuff
begin
writeln ('StartFromIndexZero = true');
CreateTPADownFromFragmentInvert (Highway, ATPAPosH, TPAPosH, FullWalkingPath); // Creates from position zero up to our desired HighwayPoint and stores it in FullWalkingPath
end else // Start from Highway[0][HighestIndex]
begin
writeln ('StartFromIndexZero = false');
CreateTPAUpFromFragmentInvert (Highway, ATPAPosH, TPAPosH, FullWalkingPath);
end; // We've done the highway, now below, create the subpath
writeln ('** Lets debug our FullWalkingPath TPA');
DebugTheTPA (FullWalkingPath);
//nodeName := DetermineNodeName (FullWalkingPath[0]); // Since our full walking path HAS to start at a node, logically if there were no errors... the very first point should be a node. This will tell us the node we have to be at! :)
writeln ('** Node name: '+nodeName+' -- determined from Point('+inttostr(FullWalkingPath[0].x)+','+inttostr(FullWalkingPath[0].y)+')');
writeln ('A_PosS = '+inttostr(ATPAPosS));
writeln ('T_PosS = '+inttostr(TPAPosS));
CreateTPADownFromFragmentInvert (SubStreet, ATPAPosS, TPAPosS, SubStreetDesiredPath); // Create a path from SubStreet[ATPAPos][0] [which we remove later since Highway[ATPAPosH][TPAPosH] = SubStreet[ATPAPos][0]
//RemoveTPFromTPA (SubStreetDesiredPathTemp, SubStreetDesiredPath, 0); // Remove position [0] since that is the root spot that connects to the highway. Since our highway code walks to the root point of the SubStreet, it would just click it twice, and we don't want that.
writeln ('** Debug substreetdesiredpath TPA');
DebugTheTPA (SubStreetDesiredPath);
FullWalkingPath := CombineTPA (FullWalkingPath, SubStreetDesiredPath);
writeln ('**TPAs combined, lets debug:');
DebugTheTPA (FullWalkingPath);
//Determine node we should be at before walking the above path
GoToNodeFromAnywhere (nodeName); // This is what it SHOULD do if there is no error. Will crash if string is '', must but FAIL-SAFE in here later FAILSAFE
writeln ('** GONE to starting node');
wait (random(500));
WalkPath (FullWalkingPath); //walk generated path
wait (random(500)); // Prevent random stupid errors I guess, maybe should use FFlag(0); or something
TileToWalkTo := PointToTile (TP); // Turn our point into a tile
if TileOnMM (TileToWalkTo) then WalkToTile (TileToWalkTo, 1, 0) // If tile's on the minimap, walk to it NEEDS FAILSAFE
else FindPathToTile (TP, 6); // Else, blindwalk because it's far
end;

{******************************************************************************}
{ procedure function WalkTo (TP : TPoint) : Boolean; }
{ By: Cstrike }
{ Description: Will take you from your location to Tile(TP.x,TP.y). Probably }
{ will not work if you're somewhere far away with no node path [ex: wildy]. }
{ Returns true if you reach TP. }
{******************************************************************************}
procedure WorldWalkTo(TP : TPoint); //Only change is here, function name changed from "WalkTo"
var
highwayTP, substreetTP: TPoint;
begin
if not LoggedIn then exit;
highwayTP := SubPointDistancesTP (Highway, TP); //Debug result: Works fine ;)
if Distance (TP.x, TP.y, highwayTP.x, highwayTP.y) < 10 then //Debug result: Works fine ;)
begin
writeln ('Debugging: Using RetrieveWalkCloseToHighway');
RetrieveWalkCloseToHighway (TP, highwayTP);
end else // Else if distance greater than 10
begin
substreetTP := SubPointDistancesTP (SubStreet, TP);
if Distance (TP.x, TP.y, highwayTP.x, highwayTP.y) < Distance (TP.x, TP.y, substreetTP.x, substreetTP.y) then
begin
writeln ('Highway >= 10, and highway closer');
RetrieveWalkCloseToHighway (TP, highwayTP);
end else
begin
writeln ('Highway >= 10, and substreet closer');
RetrieveWalkCloseToSubstreet (TP, substreetTP);
end;
end;
DebugCurrentPos;
end;

c_worldwalker.simba

function WW_IsMapUp : Boolean; //By mixster. Thanks mixster :)
var tmp : String;
begin
Result := GetMMLevels('hp', tmp) = -1;
end;

procedure WW_CloseMap;
var T : Integer;
begin
if not WW_IsMapUp then Exit;
Mouse(740, 10, 16, 16, True);
T := GetSystemTime + 15000;
while WW_IsMapUp and (GetSystemTime < T) do
Wait(500);
Wait(500);
end;

function WW_OpenWorldmap : Boolean;
var T : Integer;
begin
if WW_IsMapUp then
begin
Result := True;
Exit;
end;
MouseBox(527, 139, 559, 156, 1);
Wait(1500);
T := GetSystemTime + 15000;
while (GetColor(230, 196) = 1118604) and (GetSystemTime < T) do
Wait(200);
Result := GetSystemTime < T;
end;

function WW_GetPos(var X, Y : Integer) : Boolean;
begin
Result := False;
if WW_OpenWorldmap then
begin
if GetColor(712, 475) = 16777215 then
MouseBox(742, 464, 757, 479, 1);
if GetColor(606, 308) <> 5860213 then
MouseBox(666, 469, 698, 491, 1);
Result := FindColor(X, Y, 255, 609, 311, 757, 460);
if not Result then
WW_CloseMap;
end;
end;

//WW_Walk(Point(705, 373)); will walk to GE
function WW_Walk(Loc : TPoint) : Boolean;
var
MapDist, I, X, Y : Integer;
Angle, FAngle : Extended;
WalkPoint, Cur : TPoint;
begin
repeat
if WW_IsMapUp then
begin
if FindColor(X, Y, 9100798, 6, 6, 757, 460) then
begin
Mouse(X, Y, 90, 14, True);
Wait(1500);
end else
WW_CloseMap;
end;
WW_OpenWorldmap;
WW_GetPos(Cur.X, Cur.Y);
WW_CloseMap;

MapDist := Distance(Cur.X, Cur.Y, Loc.X, Loc.Y);
Angle := Degrees(ArcTan2(Cur.Y - Loc.Y, Cur.X - Loc.X));
Angle := Angle + 180;
if Angle > 360 then Angle := Angle - 360;

for I := 1 to MapDist do
begin
FAngle := Angle - rs_GetCompassAngleDegrees;
WalkPoint := RotatePoint(Point(MMCX + 60, MMCY), Radians(FAngle), MMCX, MMCY);
Mouse(WalkPoint.X-2, WalkPoint.Y-2, 4, 4, True);
RunEnergy(30);
while IsMoving do
if (FlagDistance < 20) and (FlagDistance > 0) then Break;
Wait(150);
end;
while IsMoving do
Wait(100);
until(MapDist < 1)
SetAngle(True);
Result := True;
end;

//WW_WalkToLocation('Varrock');
function WW_WalkToLocation(SearchString : String) : Boolean;
var
TargetPos : TPoint;
begin
Result := False;
if WW_OpenWorldmap then
begin
MouseBox(98, 472, 320, 487, 1);
TypeSend(SearchString);
Wait(1000+Random(500));
if not WW_GetPos(TargetPos.X, TargetPos.Y) then Exit;
Result := WW_Walk(TargetPos);
end;
end;

Markus

2011-10-26 16:46:47

Other 2 files:
bbjhfiremaker.ini

[MainStats]
NumberOfRecords=0
bbjhfiremaker.simba

{$Define UseReflection}
////////////////////////////////////////////////////////////////////////////////
//////// Welcome to BadBoy's Firemaker
//////// Setup
//////// 1. If you don't want to use reflection comment out line 1
//////// 2. Press the start button
//////// 3. Fill out the player form
////////
//////// Please Start in draynor
//////// If you don't the script will walk you to draynor
//////// Please Start with a tinderbox in your inventory
//////// if you don't the script will search your bank, and then
//////// attempt to walk to lumbridge to take the free one
//////// however it is buggy and won't always work, especially with colour
////////////////////////////////////////////////////////////////////////////////














{$DEFINE SMART}
{$i srl\srl.scar}
{$i srl\srl\misc\paintsmart.scar}
{$ifdef UseReflection}
{$i reflection\reflection.simba}
{$i R_WorldWalker.simba} //by CStrike
{$else}
{$i C_WorldWalker.simba} //By Xyt3x
{$endif}
{Developers Notes
Anything Marked R_ is a reflection function
Anything Marked C_ is a colour function
Anything Marked P_ is a progress report function
Anything Marked F_ is a form functions
Anything Unmarked is a core function that uses colour and reflection if included
}

type
C_Ident = record //Used to keep data for FindItem/WithdrawItem
Ident: Integer;
Name, IdentType: String;
Tol: TIntegerArray;
end;

type
F_SmartInformation = record
WorldText: TEdit;
MembersBool, SignedBool, DetailBool: TComboBox;
WorldLabel, MembersLabel, SignedLabel, DetailLabel: TLabel;
end;

F_Player = record
UsernameText, NickText, PasswordText, LogAmountText, PinText: TEdit;
LogType: TComboBox;
UsernameLabel, NickLabel, PasswordLabel, LogAmountLabel, LogTypeLabel, PinLabel: TLabel;
Members: TCheckbox;
LoadPlayerBtn, SavePlayerBtn, DeletePlayerBtn: TButton;
end;

F_BreakInformation = record
BreakForText, BreakAfterText: TEdit;
BreakForLabel, BreakAfterLabel: TLabel;
Break: TCheckBox;
end;

F_LoadPlayerForm = record
Form: TForm;
OKBtn: TButton;
PlayerList: TListBox;
WhichPlayer: Integer;
Created: Boolean;
end;

var
F_MainForm: TForm;
F_LoadPlayerForm: F_LoadPlayerForm;
F_Players: array of F_Player;
F_SmartInfo: F_SmartInformation;
F_FinishedBtn, F_AddPlayerBtn: TButton;
F_BreakInfo: F_BreakInformation;
BreakFor, TimeBetweenBreaks, LoginTime: Integer;
TakeBreaks: Boolean;

const
//Log Identifiers
NormalLog = 0;
OakLog = 1;
WillowLog = 2;
MapleLog = 3;
YewLog = 4;
AcheyLog = 5;
TeakLog = 6;
ArcticPineLog = 7;
MahoganyLog = 8;
EucalyptusLog = 9;
MagicLog = 10;
Tinderbox = 11; //Not a log, but is used in LoadIdent

//Player Integers Identifiers
WhichLog = 0;
LogTab = 1;
LogSlot = 2;
LogsBurnt = 3;
LevelsGained = 4;
BurnHowMany = 5;
LoadsDone = 6;
TinderboxFindingStatus = 7;

//Player Array Identifiers
AntibanArr = 0;

//Player Extendeds Identifiers
ExpGained = 0;

//Reflection IDs
TinderboxID = 590;
FireID = 2732;

//Tinderbox finding status Identifiers
Found = 0;
CheckBank = 1;

//Form constants
FormPSHeight = 140;
TabablePAmount = 10;
FormBaseHeight = 120;
FormWidth = 300;
PSDisplacement = -40;

{Setup Starts Here
If You do not want reflection, scroll up the top, and comment out that line}

procedure F_OnKeyPress(Sender: TObject; var Key: Char);
{F_OnKeyPress - Cancles any key that is pressed
Thanks to Coh3n for this, came from his Draynor Cutter
Banker Script and I wouldn't have thought of this}
begin
Key := Chr(VK_CANCEL);
end;

function F_LogStrToInt(LogStr: string): Integer;
{F_LogStrToInt - Changes the string from the form into the equivilant integer}
begin
case LogStr of
'Normal' : Result := NormalLog;
'Oak' : Result := OakLog;
'Willow' : Result := WillowLog;
'Maple' : Result := MapleLog;
'Yew' : Result := YewLog;
'Achey' : Result := AcheyLog;
'Teak' : Result := TeakLog;
'Actic pine' : Result := ArcticPineLog;
'Mahogany' : Result := MahoganyLog;
'Eucalyptus' : Result := EucalyptusLog;
'Magic' : Result := MagicLog;
end;
end;

procedure F_BreakingChanged(Sender: TObject);
begin
F_BreakInfo.BreakAfterText.Enabled := F_BreakInfo.Break.Checked;
F_BreakInfo.BreakForText.Enabled := F_BreakInfo.Break.Checked;
end;

procedure F_MembersChanged(Sender: TObject);
var
I, TheSender: Integer;
begin
for I := 0 to High(F_Players) do
if Sender = (F_Players[i].Members) then
begin
TheSender := I;
Break;
end;
if F_Players[i].Members.Checked then
begin
with F_Players[i].LogType.ITEMS do
begin
Add('Achey');
Add('Teak');
Add('Actic pine');
Add('Mahogany');
Add('Eucalyptus');
Add('Magic');
end;
end else begin
with F_Players[i].LogType.ITEMS do
begin
Clear;
Add('Normal');
Add('Oak');
Add('Willow');
Add('Maple');
Add('Yew');
end;
end;
end;

procedure F_LoadPlayerFromINI(WhichPlayer, WhichPlayerini: Integer);
begin
F_Players[WhichPlayer].UsernameText.Caption := ReadIni('name', IntToStr(WhichPlayerini), ScriptPath + 'BBJHFiremaker.ini');
F_Players[WhichPlayer].PasswordText.Caption := ReadIni('pass', IntToStr(WhichPlayerini), ScriptPath + 'BBJHFiremaker.ini');
F_Players[WhichPlayer].PinText.Caption := ReadIni('pin', IntToStr(WhichPlayerini), ScriptPath + 'BBJHFiremaker.ini');
F_Players[WhichPlayer].NickText.Caption := ReadIni('nick', IntToStr(WhichPlayerini), ScriptPath + 'BBJHFiremaker.ini');
F_Players[WhichPlayer].Members.Checked := StrToBool(ReadINI('members', IntToStr(WhichPlayerIni), ScriptPath + 'BBJHFiremaker.ini'));
F_Players[WhichPlayer].LogType.Caption := ReadIni('LogT', IntToStr(WhichPlayerini), ScriptPath + 'BBJHFiremaker.ini');
F_Players[WhichPlayer].LogAmountText.Caption := ReadIni('LogA', IntToStr(WhichPlayerini), ScriptPath + 'BBJHFiremaker.ini');
F_MembersChanged(F_Players[WhichPlayer].Members);
end;

procedure F_CloseLoadPlayerForm(Sender: TObject);
var
WhichPlayerini, WhichPlayerForm: Integer;
begin
WhichPlayerIni := F_LoadPlayerForm.PlayerList.ItemIndex;
WhichPlayerForm := F_LoadPlayerForm.WhichPlayer;
F_LoadPlayerFromINI(WhichPlayerForm, WhichPlayerini);
F_LoadPlayerForm.Form.Hide;
end;

procedure F_LoadThePlayerForm(Which: Integer);
var
I: Integer;
begin
with F_LoadPlayerForm do
begin
Form := TForm.Create(F_MainForm);
with Form do
begin
Parent := F_MainForm;
Height := 50;
Width := 150;
end;

PlayerList := TListBox.Create(F_LoadPlayerForm.Form);
with PlayerList do
begin
Parent := F_LoadPlayerForm.Form;
Top := 5;
Left := 5;
Width := 90;
Height := 40;
OnDblClick := @F_CloseLoadPlayerForm;
for I := 0 to -1 + Round(Pow(2, 31)) do
begin
if ReadIni('name', IntToStr(I), ScriptPath + 'BBJHFiremaker.ini') = '' then
Break;
Items.Add(ReadIni('name', IntToStr(I), ScriptPath + 'BBJHFiremaker.ini'));
end;
end;

OKBtn := TButton.Create(F_LoadPlayerForm.Form);
with OKBtn do
begin
Parent := F_LoadPlayerForm.Form;
Top := 15;
Left := 105;
Width := 40;
Height := 20;
Caption := 'OK';
OnClick := @F_CloseLoadPlayerForm;
end;

WhichPlayer := Which;
Created := True;
end;
F_LoadPlayerForm.Form.Show;
end;

procedure F_LoadPlayer(Sender: TObject);
var
IniAmount, I: Integer;
begin
for I := 0 to High(F_Players) do
if Sender = F_Players[i].LoadPlayerBtn then
Break;
IniAmount := StrToInt(ReadIni('MainStats', 'NumberOfRecords', ScriptPath + 'BBJHFiremaker.ini'));
if IniAmount = 1 then
F_LoadPlayerFromINI(I, 0) else
begin
if F_LoadPlayerForm.Created then
begin
F_LoadPlayerForm.Form.Show;
F_LoadPlayerForm.WhichPlayer := I;
end else
F_LoadThePlayerForm(I);
end;
end;

procedure F_SavePlayer(Sender: TObject);
var
IniAmount, I: Integer;
begin
for I := 0 to High(F_Players) do
if Sender = F_Players[i].SavePlayerBtn then
Break;
IniAmount := StrToInt(ReadIni('MainStats', 'NumberOfRecords', ScriptPath + 'BBJHFiremaker.ini'));
WriteINI('name', IntToStr(IniAmount), F_Players[i].UsernameText.Caption, ScriptPath + 'BBJHFiremaker.ini');
WriteINI('pass', IntToStr(IniAmount), F_Players[i].PasswordText.Caption, ScriptPath + 'BBJHFiremaker.ini');
WriteINI('pin', IntToStr(IniAmount), F_Players[i].PinText.Caption, ScriptPath + 'BBJHFiremaker.ini');
WriteINI('nick', IntToStr(IniAmount), F_Players[i].NickText.Caption, ScriptPath + 'BBJHFiremaker.ini');
WriteINI('members', IntToStr(IniAmount), BoolToStr(F_Players[i].Members.Checked), ScriptPath + 'BBJHFiremaker.ini')
WriteINI('LogT', IntToStr(IniAmount), F_Players[i].LogType.Caption, ScriptPath + 'BBJHFiremaker.ini');
WriteINI('LogA', IntToStr(IniAmount), F_Players[i].LogAmountText.Caption, ScriptPath + 'BBJHFiremaker.ini');
WriteINI('MainStats', 'NumberOfRecords', IntToStr(IniAmount + 1), ScriptPath + 'BBJHFiremaker.ini');
end;

procedure F_Finished(Sender: TObject);
{F_Finished - Takes data from the form, and puts it into Players variable}
var
I: Integer;
begin
for I := 0 to High(F_Players) do
if not F_Players[i].UsernameLabel.Visible then
Break;
NumberOfPlayers(I);
for I := 0 to High(Players) do
with Players[i] do
begin
Active := True;
Name := F_Players[i].UsernameText.Caption;
Pass := F_Players[i].PasswordText.Caption;
Nick := F_Players[i].NickText.Caption;
Pin := F_Players[i].PinText.Caption ;
{$ifdef Reflection}
Member := F_Players[i].Members.Checked;
{$endif}
Integers[WhichLog] := F_LogStrToInt(F_Players[i].LogType.Caption);
Integers[BurnHowMany] := StrToInt(F_Players[i].LogAmountText.Caption);
end;
TakeBreaks := F_BreakInfo.Break.Checked;
BreakFor := StrToInt(F_BreakInfo.BreakForText.Caption) * 60000;
TimeBetweenBreaks := StrToInt(F_BreakInfo.BreakAfterText.Caption) * 60000;
Smart_Server := StrToInt(F_SmartInfo.WorldText.Caption);
Smart_Members := F_SmartInfo.MembersBool.Caption = 'Yes';
Smart_Signed := F_SmartInfo.SignedBool.Caption = 'Yes';
Smart_SuperDetail := F_SmartInfo.DetailBool.Caption = 'Yes';
F_MainForm.ModalResult := 1;
end;

procedure F_RemoveNonNumbers(Sender: TObject; var Key: Char);
var
Where: Integer;
{F_RemoveNonNumbers - Any key except number keys, or backspace/delete keys}
begin
if not InIntArrayEx([VK_0, VK_1, VK_2, VK_3, VK_4, VK_5, VK_6, VK_7, VK_8, VK_9, VK_Delete, VK_Back], Where, GetKeyCode(Key)) then
Key := Chr(VK_Cancel);
if InRange(Where, 0, 9) and (Key = Chr(VK_Cancel)) then
if (StrToInt(F_SMartInfo.WorldText.Caption) * 10 + Where) > 172 then
begin
Key := Chr(VK_Cancel);
F_SMartInfo.WorldText.Caption := '172';
end;
end;

procedure F_DeletePlayer(Sender: TObject);
{F_DeletePlayer - Takes a player off the form}
var
LastShowing, WhichToDelete, I: Integer;
begin
for I := 0 to High(F_Players) do
if Sender = F_Players[i].DeletePlayerBtn then
Break;
WhichToDelete := I;
for I := 0 to High(F_Players) do
if not F_Players[I].DeletePlayerBtn.Showing then
Break;
LastShowing := I - 1;
for I := WhichToDelete to LastShowing - 1 do
begin
F_Players[I].LogAmountText.Caption := F_Players[I + 1].LogAmountText.Caption;
F_Players[I].LogType.Caption := F_Players[I + 1].LogType.Caption;
F_Players[I].NickText.Caption := F_Players[I + 1].NickText.Caption;
F_Players[I].PasswordText.Caption := F_Players[I + 1].PasswordText.Caption;
F_Players[I].UsernameText.Caption := F_Players[I + 1].UsernameText.Caption;
F_Players[I].PinText.Caption := F_Players[I + 1].PinText.Caption;
F_Players[I].Members.Checked := F_Players[I + 1].Members.Checked;
F_Players[I].LogType.Items := F_Players[I + 1].LogType.Items;
end;

F_Players[LastShowing].LogAmountText.Caption := '';
F_Players[LastShowing].LogType.Caption := '';
F_Players[LastShowing].NickText.Caption := '';
F_Players[LastShowing].PasswordText.Caption := '';
F_Players[LastShowing].UsernameText.Caption := '';
F_Players[LastShowing].PinText.Caption := '';
F_Players[LastShowing].Members.Checked := False;
F_Players[LastShowing].LogType.Items.Clear;

with F_Players[LastShowing] do
begin
DeletePlayerBtn.Hide;
LoadPlayerBtn.Hide;
LogAmountLabel.Hide;
LogAmountText.Hide;
LogType.Hide;
LogTypeLabel.Hide;
Members.Hide;
NickLabel.Hide;
NickText.Hide;
PasswordLabel.Hide;
PasswordText.Hide;
PinLabel.Hide;
PinText.Hide;
SavePlayerBtn.Hide;
UsernameLabel.Hide;
UsernameText.Hide;
end;
F_MainForm.Height := LastShowing * FormPSHeight + FormBaseHeight;
F_MainForm.Width := FormWidth;
F_FinishedBtn.Top := F_FinishedBtn.Top - FormPSHeight;
F_AddPlayerBtn.Top := F_AddPlayerBtn.Top - FormPSHeight;
F_AddPlayerBtn.TabOrder := 8 + LastShowing * TabablePAmount;
F_FinishedBtn.TabOrder := 9 + LastShowing * TabablePAmount;
end;

procedure F_AddPlayer(Sender: TObject);
{F_AddPlayer - Adds another Player into the form}
var
I: integer;
begin
for I := 0 to High(F_Players) do
if not F_Players[I].DeletePlayerBtn.Showing then
Break;
if I > High(F_Players) then
begin
SetLength(F_Players, Length(F_Players) + 1);
F_Players[High(F_Players)].UsernameLabel := TLabel.Create(F_MainForm);
with F_Players[High(F_Players)].UsernameLabel do
begin
Parent := F_MainForm;
Top := Length(F_Players) * FormPSHeight + PSDisplacement;
Left := 5;
Width := 60;
Height := 20;
Caption := 'Username';
Layout := tlCenter;
end;

F_Players[High(F_Players)].UsernameText := TEdit.Create(F_MainForm);
with F_Players[High(F_Players)].UsernameText do
begin
Parent := F_MainForm;
Top := Length(F_Players) * FormPSHeight + PSDisplacement;
Left := 65;
Width := 90;
Height := 20;
TabOrder := Length(F_Players) * TabablePAmount;
end;

F_Players[High(F_Players)].PasswordLabel := TLabel.Create(F_MainForm);
with F_Players[High(F_Players)].PasswordLabel do
begin
Parent := F_MainForm;
Top := Length(F_Players) * FormPSHeight + PSDisplacement + 25;
Left := 5;
Width := 60;
Height := 20;
Caption := 'Password';
Layout := tlCenter;
end;

F_Players[High(F_Players)].PasswordText := TEdit.Create(F_MainForm);
with F_Players[High(F_Players)].PasswordText do
begin
Parent := F_MainForm;
Top := Length(F_Players) * FormPSHeight + PSDisplacement + 25;
Left := 65;
Width := 90;
Height := 20;
TabOrder := Length(F_Players) * TabablePAmount + 1;
end;

F_Players[High(F_Players)].PinLabel := TLabel.Create(F_MainForm);
with F_Players[High(F_Players)].PinLabel do
begin
Parent := F_MainForm;
Top := Length(F_Players) * FormPSHeight + PSDisplacement + 50;
Left := 5;
Width := 60;
Height := 20;
Caption := 'PIN';
Layout := tlCenter;
end;

F_Players[High(F_Players)].PinText := TEdit.Create(F_MainForm);
with F_Players[High(F_Players)].PinText do
begin
Parent := F_MainForm;
Top := Length(F_Players) * FormPSHeight + PSDisplacement + 50;
Left := 65;
Width := 90;
Height := 20;
MaxLength := 4;
OnKeyPress := @F_RemoveNonNumbers;
TabOrder := Length(F_Players) * TabablePAmount + 2;
end;

F_Players[High(F_Players)].NickLabel := TLabel.Create(F_MainForm);
with F_Players[High(F_Players)].NickLabel do
begin
Parent := F_MainForm;
Top := Length(F_Players) * FormPSHeight + PSDisplacement + 75;
Left := 5;
Width := 60;
Height := 20;
Caption := 'Nickname';
Layout := tlCenter;
end;

F_Players[High(F_Players)].NickText := TEdit.Create(F_MainForm);
with F_Players[High(F_Players)].NickText do
begin
Parent := F_MainForm;
Top := Length(F_Players) * FormPSHeight + PSDisplacement + 75;
Left := 65;
Width := 90;
Height := 20;
MaxLength := 4;
TabOrder := Length(F_Players) * TabablePAmount + 3;
end;

F_players[High(F_Players)].LogTypeLabel := TLabel.Create(F_MainForm);
with F_Players[High(F_Players)].LogTypeLabel do
begin
Parent := F_MainForm;
Caption := 'Log Type';
Top := Length(F_Players) * FormPSHeight + PSDisplacement;
Left := 165;
Width := 60
Height := 20;
Layout := tlCenter;
end;

F_players[High(F_Players)].LogType := TComboBox.Create(F_MainForm);
with F_Players[High(F_Players)].LogType do
begin
Parent := F_MainForm;
Top := Length(F_Players) * FormPSHeight + PSDisplacement;
Left := 225;
Width := 70;
Height := 20;
OnKeyPress := @F_OnKeyPress;
Items.Add('Normal');
Items.Add('Oak');
Items.Add('Willow');
Items.Add('Maple');
Items.Add('Yew');
TabOrder := Length(F_Players) * TabablePAmount + 4;
end;

F_Players[High(F_Players)].LogAmountLabel := TLabel.Create(F_MainForm);
with F_Players[High(F_Players)].LogAmountLabel do
begin
Parent := F_MainForm;
Caption := 'Amount';
Top := Length(F_Players) * FormPSHeight + PSDisplacement + 25;
Left := 165;
Width := 60;
Height := 20;
Layout := tlCenter;
end;

F_Players[High(F_Players)].LogAmountText := TEdit.Create(F_MainForm);
with F_Players[High(F_Players)].LogAmountText do
begin
Parent := F_MainForm;
Top := Length(F_Players) * FormPSHeight + PSDisplacement + 25;
Left := 225;
Width := 70;
Height := 20;
OnKeyPress := @F_RemoveNonNumbers;
TabOrder := Length(F_Players) * TabablePAmount + 5;
end;

{$ifdef Reflection}
F_Players[High(F_Players)].Members := TCheckBox.Create(F_MainForm);
with F_Players[High(F_Players)].Members do
begin
Parent := F_MainForm;
Top := Length(F_Players) * FormPSHeight + PSDisplacement + 50;
Left := 165;
Width := 130;
Height := 20;
Caption := 'Members';
OnClick := @F_MembersChanged;
TabOrder := Length(F_Players) * TabablePAmount + 6;
end;
{$endif}

F_Players[High(F_Players)].DeletePlayerBtn := TButton.Create(F_MainForm);
with F_Players[High(F_Players)].DeletePlayerBtn do
begin
Parent := F_MainForm;
Top := Length(F_Players) * FormPSHeight + PSDisplacement + 75;
Left := 165;
Width := 130;
Height := 20;
OnClick := @F_DeletePlayer;
Caption := 'Delete Player';
TabOrder := Length(F_Players) * TabablePAmount + 7;
end;

F_Players[High(F_Players)].LoadPlayerBtn := TButton.Create(F_MainForm);
with F_Players[High(F_Players)].LoadPlayerBtn do
begin
Parent := F_MainForm;
Top := Length(F_Players) * FormPSHeight + PSDisplacement + 100;
Left := 15;
Width := 130;
Height := 20;
OnClick := @F_LoadPlayer;
Caption := 'Load Player';
TabOrder := Length(F_Players) * TabablePAmount + 8;
end;

F_Players[High(F_Players)].SavePlayerBtn := TButton.Create(F_MainForm);
with F_Players[High(F_Players)].SavePlayerBtn do
begin
Parent := F_MainForm;
Top := Length(F_Players) * FormPSHeight + PSDisplacement + 100;
Left := 165;
Width := 130;
Height := 20;
OnClick := @F_SavePlayer;
Caption := 'Save Player';
TabOrder := Length(F_Players) * TabablePAmount + 9;
end;
end else begin

with F_Players[I] do
begin
DeletePlayerBtn.Show;
LoadPlayerBtn.Show;
LogAmountLabel.Show;
LogAmountText.Show;
LogType.Show;
LogTypeLabel.Show;
Members.Show;
NickLabel.Show;
NickText.Show;
PasswordLabel.Show;
PasswordText.Show;
PinLabel.Show;
PinText.Show;
SavePlayerBtn.Show;
UsernameLabel.Show;
UsernameText.Show;
end;
end;

F_FinishedBtn.Top := F_FinishedBtn.Top + FormPSHeight;
F_AddPlayerBtn.Top := F_AddPlayerBtn.Top + FormPSHeight;
F_MainForm.Height := (I + 1) * FormPSHeight + FormBaseHeight;
F_MainForm.Width := FormWidth;
F_AddPlayerBtn.TabOrder := 8 + (I + 1) * TabablePAmount;
F_FinishedBtn.TabOrder := 9 + (I + 1) * TabablePAmount;
end;

procedure F_CreateForm;
{F_CreateForm - Creates the form Player form}
begin
F_MainForm := CreateForm;
with F_MainForm do
begin
Width := 300;
Height := 140;
end;
with F_SmartInfo do
begin
F_SmartInfo.WorldLabel := TLabel.Create(F_MainForm);
F_SmartInfo.WorldText := TEdit.Create(F_MainForm);
F_SmartInfo.DetailLabel := TLabel.Create(F_MainForm);
F_SmartInfo.DetailBool := TComboBox.Create(F_MainForm);
F_SmartInfo.MembersLabel := TLabel.Create(F_MainForm);
F_SmartInfo.MembersBool := TComboBox.Create(F_MainForm);
F_SmartInfo.SignedLabel := TLabel.Create(F_MainForm);
F_SmartInfo.SignedBool := TComboBox.Create(F_MainForm);

with F_SmartInfo.WorldLabel do
begin
Parent := F_MainForm;
Caption := 'Smart World:';
Top := 10;
Left := 10;
Width := 90;
Height := 25;
Layout := tlCenter;
end;

with F_SmartInfo.WorldText do
begin
Parent := F_MainForm;
Caption := '108';
Top := 10;
Left := 100;
Width := 40;
Height := 25;
MaxLength := 3;
OnKeyPress := @F_RemoveNonNumbers;
TabOrder := 1;
end;

with F_SmartInfo.DetailLabel do
begin
Parent := F_MainForm;
Caption := 'Use Super detail:';
Top := 10;
Left := 160;
Width := 90;
Height := 25;
Layout := tlCenter;
end;

with F_SmartInfo.DetailBool do
begin
Parent := F_MainForm;
Caption := 'No';
Top := 10;
Left := 250;
Width := 40;
Height := 25;
OnKeyPress := @F_OnKeyPress;
Items.Add('Yes');
Items.Add('No');
TabOrder := 3;
end;

with F_SmartInfo.MembersLabel do
begin
Parent := F_MainForm;
Caption := 'Members:';
Top := 35;
Left := 10;
Width := 90;
Height := 25;
Layout := tlCenter;
end;

with F_SmartInfo.MembersBool do
begin
Parent := F_MainForm;
Caption := 'No';
Top := 35;
Left := 100;
Width := 40;
Height := 25;
OnKeyPress := @F_OnKeyPress;
Items.Add('Yes');
Items.Add('No');
TabOrder := 2;
end;

with F_SmartInfo.SignedLabel do
begin
Parent := F_MainForm;
Caption := 'Signed Smart:';
Top := 35;
Left := 160;
Width := 90;
Height := 12;
Layout := tlCenter;
end;

with F_SmartInfo.SignedBool do
begin
Parent := F_MainForm;
Caption := 'Yes';
Top := 35;
Left := 250;
Width := 40;
Height := 25;
OnKeyPress := @F_OnKeyPress;
Items.Add('Yes');
Items.Add('No');
TabOrder := 4;
end;
end;

F_BreakInfo.Break := TCheckBox.Create(F_MainForm);
with F_BreakInfo.Break do
begin
Parent := F_MainForm;
Caption := 'Take Breaks';
Top := 60;
Left := 5;
Width := 90;
Height := 25;
TabOrder := 5;
Checked := True;
end;

F_BreakInfo.BreakAfterLabel := TLabel.Create(F_MainForm);
with F_BreakInfo.BreakAfterLabel do
begin
Parent := F_MainForm;
Caption := 'Break After';
Top := 60;
Left := 105;
Width := 60;
Height := 25;
Layout := tlCenter;
end;

F_BreakInfo.BreakAfterText := TEdit.Create(F_MainForm);
with F_BreakInfo.BreakAfterText do
begin
Parent := F_MainForm;
OnKeyPress := @F_RemoveNonNumbers;
Caption := '60';
Top := 60;
Left := 165;
Width := 30;
Height := 25;
TabOrder := 6;
end;

F_BreakInfo.BreakForLabel := TLabel.Create(F_MainForm);
with F_BreakInfo.BreakForLabel do
begin
Parent := F_MainForm;
Caption := 'Break For';
Top := 60;
Left := 205;
Width := 60;
Height := 25;
Layout := tlCenter;
end;

F_BreakInfo.BreakForText := TEdit.Create(F_MainForm);
with F_BreakInfo.BreakForText do
begin
Parent := F_MainForm;
OnKeyPress := @F_RemoveNonNumbers;
Caption := '15';
Top := 60;
Left := 265;
Width := 30;
Height := 25;
TabOrder := 7;
end;
F_BreakInfo.Break.OnClick := @F_BreakingChanged;

F_AddPlayerBtn := TButton.Create(F_MainForm);
with F_AddPlayerBtn do
begin
Parent := F_MainForm;
Caption := 'Add Another Player';
Top := FormBaseHeight - 25;
Left := 5;
Width := 140;
Height := 20;
OnClick := @F_AddPlayer;
TabOrder := 8;
end;

F_FinishedBtn := TButton.Create(F_MainForm);
with F_FinishedBtn do
begin
Parent := F_MainForm;
Caption := 'Finished!';
Top := FormBaseHeight - 25;
Left := 155;
Width := 140;
Height := 20;
OnClick := @F_Finished;
TabOrder := 9;
end;

F_AddPlayer(F_FinishedBtn);
end;

procedure F_CreateFormSafe;
var
varArr: TVariantArray;
begin
SetArrayLength(varArr, 0);
ThreadSafeCall('F_CreateForm', varArr);
end;

procedure F_ShowFormModal;
begin
F_MainForm.ShowModal;
end;

procedure F_ShowFormSafeModal;
var
varArr: TVariantArray;
begin
SetArrayLength(varArr, 0);
ThreadSafeCall('F_ShowFormModal', varArr);
end;

procedure F_CreatePlayerForm;
{F_CreatePlayerForm - Creates the Player form like it should}
begin
F_CreateFormSafe;
F_ShowFormSafeModal;
if F_MainForm.ModalResult = 2 then
begin
F_MainForm.Free;
TerminateScript;
end;
F_MainForm.Free;
end;

function LoadRandomPattern: TIntegerArray;
{LoadRandomPattern - Loads a random pattern to burn logs}
var
Rnd: Integer;
begin
Rnd := Random(7);
case Rnd of
0 : Result := [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28];
1 : Result := [1, 2, 3, 4, 8, 7, 6, 5, 9, 10, 11, 12, 16, 15, 14, 13, 17, 18, 19, 20, 24, 23, 22, 21, 25, 26, 27, 28];
2 : Result := [1, 5, 9, 13, 17, 21, 25, 2, 6, 10, 14, 18, 22, 26, 3, 7, 11, 15, 19, 23, 27, 4, 8, 12, 16, 20, 24, 28];
3 : Result := [1, 2, 5, 3, 6, 9, 4, 7, 10, 13, 8, 11, 14, 17, 12, 15, 18, 21, 16, 19, 22, 25, 20, 23, 26, 24, 27, 28];
4 : Result := [1, 5, 2, 9, 6, 3, 13, 10, 7, 4, 17, 14, 11, 8, 21, 18, 15, 12, 25, 22, 19, 16, 26, 23, 20, 27, 24, 28];
5 : Result := [1, 2, 5, 9, 6, 3, 4, 7, 10, 13, 17, 14, 11, 8, 12, 15, 18, 21, 25, 22, 19, 16, 20, 23, 26, 27, 24, 28];
6 : Result := [1, 5, 2, 3, 6, 9, 13, 10, 7, 4, 8, 11, 14, 17, 21, 18, 15, 12, 16, 19, 22, 25, 26, 23, 20, 24, 27, 28];
end;
if RBool then
InvertTIA(Result);
end;

function LoadEXPValue: Extended;
{LoadEXPValue - Returns the Experience gained for burning a perticular log}
begin
case Players[CurrentPlayer].Integers[WhichLog] of
NormalLog : Result := 40;
OakLog : Result := 60;
WillowLog : Result := 90;
MapleLog : Result := 135;
YewLog : Result := 202.5;
AcheyLog : Result := 40;
TeakLog : Result := 105;
ArcticPineLog : Result := 125;
MahoganyLog : Result := 157.5;
EucalyptusLog : Result := 193.5;
MagicLog : Result := 303.8;
end;
end;

function AMin(Ints: TIntegerArray): Integer;
var
I: Integer;
begin
case Length(Ints) of
0 : Result := 0;
1 : Result := Ints[0];
2 : Result := Min(Ints[0], Ints[1]);
else
begin
Result := Min(Ints[0], Ints[1]);
for I := 2 to High(Ints) do
Result := Min(Result, Ints[i]);
end;
end;
end;
{$ifdef Reflection}

function R_ReturnLogID(WhichLog: Integer): Integer;
{R_ReturnLogID - Simple, Returns the unique ID of the log types}
begin
case WhichLog of
NormalLog : Result := 1511;
OakLog : Result := 1521;
WillowLog : Result := 1519;
MapleLog : Result := 1517;
YewLog : Result := 1515;
AcheyLog : Result := 2862;
TeakLog : Result := 6333;
ArcticPineLog : Result := 10810;
MahoganyLog : Result := 6332;
EucalyptusLog : Result := 12581;
MagicLog : Result := 1513;
end;
end;

function R_GetTabStartYPoints: TIntegerArray;
{R_GetTablStartYPoints - Gets the Relative Points of the Text "Tab X"
in the bank screen, helps to determine which tab an item is on}
var
I: Integer;
begin
SetLength(Result, 8);
for I := 2 to 9 do
begin
if R_BankTabExists(I) then
Result[i-2] := GetInterfaceComponentRelativeY(Interface_Bank, I + 64) else
Break;
end;
SetLength(Result, I-3);
end;

function R_WhichTabIsItemOn(ItemID: Integer; SwitchToTab: Boolean): Integer;
{R_WhichTabIsItemOn - Returns the Tab that an the item with ID "ItemID" is on"}
var
I: Integer;
BankItem: TBankItem;
BankPoint: TPoint;
Ys: TIntegerArray;
begin
R_BankTab(1);
if not R_ItemExistsInBank(ItemID, BankItem) then
Exit;
BankPoint := R_GetBankItemRelPoint(BankItem.Slot);
Ys := R_GetTabStartYPoints;
for I := 0 to High(Ys) do
if Ys[I] > BankPoint.y + GetInterfaceComponentRelativeY(INTERFACE_BANK, INTERFACE_BANK_SLOTS) then
Break;
Result := I + 1;
if SwitchToTab then
R_BankTab(Result);
end;

function R_ItemOnCurrentTab(ID: Integer): Boolean;
{R_ItemOnCurrent Tab Returns True if the item with
the specified ID is on the current Tab}
var
BankItem: TBankItem;
begin
if not R_ItemExistsInBank(ID, BankItem) then
Exit;
if R_CurrentBankTab <> 1 then
Result := R_GetBankItemRelPoint(BankItem.Slot) <> Point(0, 0) else
Result := R_GetBankItemRelPoint(BankItem.Slot).y + GetInterfaceComponentRelativeY(INTERFACE_BANK, INTERFACE_BANK_SLOTS) < GetInterfaceComponentRelativeY(Interface_Bank, 68);
end;

function R_WithdrawItemID(ID: Integer; var Tab: Integer; Amount: Integer): Boolean;
{R_WithdrawItemID - Originally My work, but broke when the Free Trade and
Wilderness update occoured, has been fixed to use the above procedures}
var
ItemBox: TBox;
RelPoint: TPoint;
BankItem: TBankItem;
Mark, InvCou, CountTime: Integer;
begin
if not R_ItemExistsInBank(ID, BankItem) then
Exit;
if Tab = 0 then
begin
if R_ItemOnCurrentTab(ID) then
Tab := R_CurrentBankTab else
Tab := R_WhichTabIsItemOn(ID, True);
end else begin
R_BankTab(Tab);
if not R_ItemOnCurrentTab(ID) then
Tab := R_WhichTabIsItemOn(ID, True);
end;

{The rest of this function is from the reflection include, most of this function
was infact my work, but mormonman has fixed it up and made it easier to read}
//this then gets the box of the Item we want to withdraw.
RelPoint := R_GetBankItemRelPoint(BankItem.Slot);
ItemBox.x1 := RelPoint.x + GetInterfaceComponentRelativeX(INTERFACE_BANK, INTERFACE_BANK_SLOTS) + 4;
ItemBox.y1 := RelPoint.y + GetInterfaceComponentRelativeY(INTERFACE_BANK, INTERFACE_BANK_SLOTS) + 4;
ItemBox.x2 := ItemBox.x1 + GetChildComponentWidth(INTERFACE_BANK, INTERFACE_BANK_SLOTS, BankItem.Slot);
ItemBox.y2 := ItemBox.y1 + GetChildComponentHeight(INTERFACE_BANK, INTERFACE_BANK_SLOTS, BankItem.Slot);


if Amount = 1 then
begin
MouseBox(ItemBox.x1, ItemBox.y1, ItemBox.x2, ItemBox.y2, 1);
Result := True;
Exit;
end;
MouseBox(ItemBox.x1, ItemBox.y1, ItemBox.x2, ItemBox.y2, 2);
MarkTime(CountTime);
InvCou := R_CountItem(ID);
if Amount = 0 then
Result := R_ChooseOption('Withdraw-All ' + BankItem.Name) else
if Amount = -1 then
Result := R_ChooseOption('Withdraw-All but one ' + BankItem.Name) else
if OptionExists('Withdraw-' + IntToStr(Amount)) then
Result := R_ChooseOption('Withdraw-' + IntToStr(Amount) + ' ' + BankItem.Name)
else
begin
if R_ChooseOption('Withdraw-X ' + BankItem.Name) then
begin
MarkTime(Mark);
while not ReadyToTypeBank do
begin
Wait(RandomRange(100, 250));
if (TimeFromMark(Mark) > 10000) then
begin
Result := False;
Exit;
end;
end;
Wait(1000 + Random(1000));
TypeSend(IntToStr(Amount));
Result := True;
end;
end;

if not Result then
begin
Exit;
end;

//failsafe
while (R_CountItem(BankItem.ID) = InvCou) do
begin
if (TimeFromMark(CountTime) > 8000) then
begin
Result := False;
Exit;
end;
Wait(500);
end;
end;

function R_WithdrawLogs: Boolean;
{R_WithdrawLogs - Withdraws the logs using reflection}
begin
Result := R_WithdrawItemID(R_ReturnLogID(Players[CurrentPlayer].Integers[WhichLog]), Players[CurrentPlayer].Integers[LogTab], 0);
end;


function R_BestYCoordinate(MinY, MaxY: Integer): Integer;
{checks the coordinates between MinY and MaxY to
see which row has the least fires on them.}
var
I, Minimum: Integer;
FiresOnLine: TIntegerArray;
Lowest: TBooleanArray;
Fires: TRSObjectArray;
begin
Fires := GetObjectsByID(FireID, 0, 20);
SetLength(FiresOnLine, MaxY - MinY + 1);
SetLength(Lowest, MaxY - MinY + 1);
for I := 0 to High(Fires) do
if InRange(Fires[I].Tile.y, MinY, MaxY) then
Inc(FiresOnLine[Fires[i].Tile.y - MinY]);
Minimum := AMin(FiresOnLine);
for I := 0 to High(FiresOnLine) do
Lowest[i] := (FiresOnLine[i] = Minimum);
repeat
Result := MinY + Random(MaxY - MinY + 1)
until Lowest[Result - MinY];
end;

function R_CantLightFire: Boolean;
{R_CantLightFire - Returns true if the player is unable to light a fire at the current position}
begin
Result := (LastChatMessage(CHAT_TYPE_SYSTEM) = 'You can''t light a fire here.');
end;

procedure R_Deposit;
begin
R_DepositAllBut(TinderboxID);
end;

function R_OpenGeneralStore: Boolean;
var
NPCs: TNPCArray;
ScreenPos: TPoint;
begin
NPCs := GetNPCs('Shop');
ScreenPos := TileToMS(NPCs[0].Tile, Random(NPCs[0].Height));
MMouse(ScreenPos.x, ScreenPos.y, 3, 3);
ClickMouse2(False);
Result := R_ChooseOption('Trade');
end;
{$endif}

function C_GetMyPos: TPoint;
{By using the ladder in the old mans house on the minimap as a reference
point, I reverse engineered the TileToMM function to get this which
returns the tile the player is standing on. Occasionally out by 1 tile}
var
I: Integer;
Angle: Extended;
NLadderPoint, LadderPoint: TPoint;
LadderTPA, TPA: TPointArray;
ATPA: T2DPointArray;
LadderArea: TBox;
begin
if not FindColorsTolerance(TPA, Autocolor(srl_LadderColor), MMX1, MMY1, MMX2, MMY2, 20) then
begin
Result := Point(-1, -1);
Exit;
end;
TPA := RemoveDistTPointArray(MMCX, MMCY, 73, TPA, True);
ATPA := TPAToATPA(TPA, 8);
for I := 0 to High(ATPA) do
if Length(ATPA[i]) > 5 then
if FindColorTolerance(LadderPoint.x, LadderPoint.y, 987725, ATPA[i][0].x - 2, ATPA[i][0].y - 2, ATPA[i][0].x + 2, ATPA[i][0].y + 2, 20) then
begin
LadderTPA := ATPA[i];
Break;
end;
LadderArea := GetTPABounds(LadderTPA);
LadderPoint := Point(LadderArea.x1 + 6, LadderArea.y1 +4);
Angle := rs_GetCompassAngleRadians;
NLadderPoint := RotatePoint(LadderPoint, Angle, MMCX, MMCY);
Result.x := 3090 + Round((628 - NLadderPoint.x) / 4.0);
Result.y := 3253 + Round((NLadderPoint.y - 87) / 4.0);
end;

function C_LoadIdent(Which, WhichType: Integer): C_Ident;
{function LoadIdent - Loads a bitmap, DTM or colours,
and other necary information for the WithdrawItem procedure}
begin
if WhichType = 0 then
begin
Result.IdentType := 'bmp';
case Which of
NormalLog : Result.Ident := BitmapFromString(16, 10, 'meJx1kdsKglAQRf8iKul+v7yEhKGZSCWJCCEiREREj3' +
'1H/92igcNgCetBxzX7HGcsv1jEj/nprqFi4HV6vI7DYrjLepvEe72X' +
'yVMLhll0m+wvoyAfbM+YnXXUWoWWX4BpkXwT2HfTrhO37QNFGnluer' +
'nRCOQTOdQJRCYZaEQmgeOolxBNHKNxImlQs2Opa8TRGsgdGm5Wd1Lq' +
'GuNoU2A+UPqLv6YMpMqv2oj41ndrv4vTpsz8A3SHfNI=');
OakLog : Result.Ident := BitmapFromString(17, 11, 'meJx9kWFLwlAUhn9KDN0HSSs1Na2+DsRMS1EmiRuLFT' +
'JChogUbYiE9Cf8rT165iE1gpdx7znP+967c+1obUfr6+evmresuour' +
'0Wdl+CFiTQXRQsJQtLeWG39FZQM4sUpJBIBuX76JEkv6cUpFGJWSSa' +
'ATlwbzQi8UCyJBAQnUo0m+tGeF7uTs/vW07gpvdmZIseTXnLj89E7s' +
'xUOQa/oZa0gXr9mdIy4mmAyBLmnZhgd53h5j4Qi8xf6Uu+FKtSbUEe' +
'ciML5s8503IWEgkxk6MVujMT6xPBYiokQHpAwc0eJiqXZo3AW/J7yn' +
'HSw3x6JDk1Hrs/7J0/3PcgTLS/0AJ57MHA==');
WillowLog : Result.Ident := BitmapFromString(13, 14, 'meJx9kFEKwjAQRI9Qq00vIYilLWk0KEIo9aNIVQTvfx' +
'EHRpY1bYT3EXZewmaMD4W7gI09g3XrAc+cE+OD+TUXhfLUazNKhcP0' +
'EjMFbh0fb2ganX63rR1e44MLQu3yvV3tmmxbdbenTjEBiAAcABlwot' +
'Gp9FOFK8/cIUqlHDvem2GM2piXg58C2TDVXkqLqqOGTlLdsqs/mi78' +
'A+Bgaoc=');
MapleLog : Result.Ident := BitmapFromString(12, 13, 'meJzjtYrksQzjMQ9BIMswXqtIELKJhiIwF6QMjFBkbW' +
'OhCKYMi6xdPBDxOSRClcERkiyIAbTCPARhIEQKZjjIarMgbmNfLgNP' +
'hBYIAmvkNgngNvTm0nPj1HZEOMkmGsjl1HEBigM1AhUATQAhkwCgaU' +
'AREIJLQWTBUvBwALGB9gINByNkKYQ3kT2OhmCeVQkqQXgfmwKgLFQN' +
'sjKM4FINLoP6HVkKOSJsYwHkf2Dh');
YewLog : Result.Ident := BitmapFromString(12, 11, 'meJzjNvPmxoosfCGIy9QTzkZHZt5cxm6chi6cuvacKv' +
'ZwQQgCagTJ6jty6NhwaFmyq5nAxYEkkAtEHBrmQCkQ0rEBGaJrD+XC' +
'EVAvRErfEYQMXSBmYkFgKRAC2mvqyaFoCeXCEVgcjoBuMIouAjkb7l' +
'pUWQhCVgNXhhZWUDVIfscMSYQaTGUwQQCKxEWD');
Tinderbox : Result.Ident := BitmapFromString(12, 13, 'meJx10P0KgjAUBfD/8uNBIqgopJCUIUSUlmVjWCYyRE' +
'Si93+Ajt2YUwoOIvN3z5VxkSZccJEiIr3fsgeS5QWeODkn11N8oZO8' +
'kEghSwoBzAKEx1iWVVnVVd0geFENAFSyD6Pm+aJgHFUA2KgA1dK4Du' +
'g3rM3W9nd2ENEiAthCwHQ8xFqxL2MHMAXMpUugY24ACWDM1+1XPX0G' +
'oPJTghlTR2dD+WHGZNGyvhwUjsazjv2Rns+GTJO4MdzMG658bio=');
end;
Result.Tol := [20];
end;

if WhichType = 1 then
begin
Result.IdentType := 'dtm';
case Which of
NormalLog : Result.Ident := DTMFromString('mggAAAHicY2NgYHBkYmCwAGITIHYCY' +
'n8g9gHiJ0C5e0D8BojfQ+k7QBzvoQU' +
'kmTCwCAN2wIgDQwAA8QgH9w==');
OakLog : Result.Ident := DTMFromString('mbQAAAHicY2VgYMhhYmBIAuIEIK4G4' +
'lIgfgQUvwfE74D4GRDfBOLWFGsgyYS' +
'CRRgwASMWDAYAdtoH4A==');
WillowLog : Result.Ident := DTMFromString('mggAAAHicY2NgYJjOxMDQA8SdQDwbi' +
'JcC8VwgfgyUuwfEb4H4HRA/BeKbQOx' +
'iIwokmTCwCAN2wIgDQwAAwv0Jrw==');
MapleLog : Result.Ident := DTMFromString('mggAAAHicY2NgYDjAxMCwHYg3A/ERI' +
'D4PxCeB+BFQ7i4QvwXid0D8DIhvAnG' +
'sLS+QZMLAIgzYASMODAEAOrMKvQ==');
YewLog : Result.Ident := DTMFromString('mggAAAHicY2NgYHBhYmAwB2JLIPYBY' +
'l8g9gJiNkYGBmYgFgJiASBmB+K/QPW' +
'+FtxAkgkDizBgB4w4MAQAAFhEA5I=');
Tinderbox : Result.Ident := DTMFromString('mggAAAHicY2NgYHBhYmAwA2JrIPaBY' +
'kcgfg6UewrEH4D4LRA/BOKbQGxuwAE' +
'kmTCwCAN2wIgDQwAA1eAHlw==');
end;
end;

if WhichType = 2 then
begin
Result.IdentType := 'colour';
case Which of
NormalLog : Result.Ident := 2639195;
OakLog : Result.Ident := 3760255;
WillowLog : Result.Ident := 1126455;
MapleLog : Result.Ident := 867677;
YewLog : Result.Ident := 669001;
Tinderbox : Result.Ident := 5790300;
end;
if Which = Tinderbox then
Result.Tol := [20, 150] else
Result.Tol := [20, 250];
end;

case Which of
NormalLog : Result.Name := 'Log';
OakLog : Result.Name := 'Oak log';
WillowLog : Result.Name := 'Willow log';
MapleLog : Result.Name := 'Maple log';
YewLog : Result.Name := 'Yew log';
Tinderbox : Result.Name := 'Tinderbox';
end;
end;

function C_TileToMM(tile: TPoint): TPoint;
{C_TileToMM This is exactly the same as TileToMs except it uses my colour version of GetMyPos
Credit for this goes to Benland100
Occasionally out by a tile, due to innacuracies in C_GetMyPos, and getting the angle with colour}
var
temp: TPoint;
begin
temp := C_GetMyPos;

if (Temp = Point(-1, -1)) then
begin
Result := Point(-1, -1);
Exit;
end;
result.x:= (tile.x - temp.x) * 4 + 626;
result.y:= (temp.y - tile.y) * 4 + 85;
Result := RotatePoint(Result, -rs_GetCompassAngleRadians, MMCX, MMCY);
end;

function C_WalkToTile(TheTile: TPoint; FlagD: Integer): Boolean;
{C_WalkToTile - This is exactly the same as WalkToTile, except that it uses colour procedures
Credit for this goes to Wizzup, TheGuyWhoGotOn, and Drags111
It also doens't include randomness, which is added beforehand}
var
wTile: TPoint;
t: Integer;
begin
Result := False;
wTile := C_TileToMM(TheTile);
if not rs_OnMiniMap(wTile.X, wTile.Y) then
Exit;
Mouse(wTile.x, wTile.y, 1, 1, true);
Wait(RandomRange(80, 100));
t := getsystemtime;
if (FlagD = 0)then
begin
Flag;
end else
FFlag(FlagD);
Result := (GetSystemTime - t) < 60000;
end;

function C_WithdrawLogs: Boolean;
{C_WithdrawLogs - Withdraws the logs using colour}
var
I: Integer;
Idnt: C_Ident;
begin
for I := 0 to 2 do
begin
Idnt := C_LoadIdent(Players[CurrentPlayer].Integers[WhichLog], I);
Result := WithdrawItemEx(Idnt.Ident, Idnt.IdentType, Players[CurrentPlayer].Integers[LogSlot], 0, Idnt.Name, Idnt.Tol);
case I of
0 : FreeBitmap(Idnt.Ident);
1 : FreeDTM(Idnt.Ident);
end;
if Result then
Exit;
end;
end;

function C_WithdrawTinderbox: Boolean;
{C_WithdrawTinderbox - Withdraws the tinderbox using colour}
var
I: Integer;
Ident: C_Ident;
begin
for I := 0 to 2 do
begin
Ident := C_LoadIdent(Tinderbox, I);
Result := WithdrawItemEx(Ident.Ident, Ident.IdentType, Players[CurrentPlayer].Integers[LogSlot], 0, Ident.Name, Ident.Tol);
case I of
0 : FreeBitmap(Ident.Ident);
1 : FreeDTM(Ident.Ident);
end;
if Result then
Exit;
end;
end;

function C_CantLightFire: Boolean;
{C_CantLightFire - Returns True if the player is unable to light a fire}
begin
if ArrInStr(['You can', 't lig', 're her', 'can''t li'], GetBlackChatMessage) then
Result := True else
Exit;
end;

procedure C_Deposit;
var
I: Integer;
Box: TBox;
begin
for I := 1 to 28 do
begin
Box := InvBox(I);
if CountColorTolerance(470582, Box.x1, Box.y1, Box.x2, Box.y2, 20) > 75 then
Break;
end;
case I of
1 : Deposit(2, 28, True);
2..27 : begin
Deposit(1, I - 1, True);
Deposit(I + 1, 28, True);
end;
28 : Deposit(1, 27, True);
end;
end;

function C_OpenGeneralStore: Boolean;
var
Colors: TIntegerArray;
I: Integer;
temp, TPA: TPointArray;
ATPA: T2DPointArray;
begin
Colors := [12766155, 5790556, 1381910, 12041617, 5599083];
for I := 0 to High(Colors) do
begin
FindColorsToleranceOptimised(temp, Colors[i], MSX1, MSY1, MSX2, MSY2, 5);
TPA := CombineTPA(TPA, temp);
end;
ATPA := TPAToATPA(TPA, 10);
SortATPASize(ATPA, True);
for I := 0 to High(ATPA) do
begin
MMouse(ATPA[i][Random(Length(ATPA[i]))].x, ATPA[i][Random(Length(ATPA[i]))].y, 2, 2);
if WaitUpTextMulti(['alk-', 'k-to', 'Shop', 'assi', 'sist', 'stant', 'keep', 'eper'], 50) then
begin
ClickMouse2(False);
Result := WaitOptionMulti(['Trad', 'rade', 'ade ', ' de S', 'e Sh'], 50);
if Result then
Exit;
end;
end;
end;

function C_BestYCoordinate(MinY, MaxY: Integer): Integer;
var
Temp: TPoint;
Minimum, I, HighestY: Integer;
Colours: TIntegerArray;
Lowest: TBoolArray;
begin
ClickNorth(True);
Temp := C_GetMyPos;
HighestY := (temp.y - MaxY) * 4 + 84;
SetLength(Colours, 1 + MaxY - MinY);
SetLength(Lowest, 1 + MaxY - MinY);
for I := 0 to High(Colours) do
Colours[i] := CountColorTolerance(60909, MMX1, HighestY - (4 * I), MMX1, HighestY - 3 - (4 * I), 5);
Minimum := AMin(Colours);
for I := 0 to High(Colours) do
Lowest[i] := (Colours[i] = Minimum);
repeat
Result := MinY + Random(MaxY - MinY + 1)
until Lowest[Result - MinY];
end;

procedure P_Debug(Str: string);
begin
Writeln('[' + TheTime + ']: ' + Str);
end;

procedure P_ProgressBar(Percentage, PosX, PosY: Integer);
{P_ProgressBar - Creates a progress bar filled a certain percentage at (PosX, PosY)}
begin
Smart_DrawDotsEx(False, ReturnPointsNotInTPA(TPAFromBox(IntToBox(PosX + 2, PosY + 2, PosX + 102, PosY + 12)), IntToBox(PosX, PosY, PosX + 104, PosY + 14)), ClRed);
if Percentage <> 0 then
Smart_DrawDotsEx(False, TPAFromBox(IntToBox(PosX + 2, PosY + 2, PosX + 2 + Percentage, PosY + 12)), ClGreen);
if Percentage <> 100 then
Smart_DrawDotsEx(False, TPAFromBox(IntToBox(PosX + 2 + Percentage, PosY + 2, PosX + 102, PosY + 12)), ClWhite);
end;

procedure P_DrawReportOnSMART;
begin
SMART_DrawTextEx(True, 10, 20, 'UpChars', 'Current Player: ', clRed);
SMART_DrawTextEx(False, 140, 20, 'UpChars', Players[CurrentPlayer].Name, clRed);
SMART_DrawTextEx(False, 10, 35, 'UpChars', 'Logs Burnt: ', ClRed);
SMART_DrawTextEx(False, 140, 35, 'UpChars', IntToStr(Players[CurrentPlayer].Integers[LogsBurnt]), clRed);
SMART_DrawTextEx(False, 10, 50, 'UpChars', 'Experience Gained: ', ClRed);
SMART_DrawTextEx(False, 140, 50, 'UpChars', FloatToStr(Players[CurrentPlayer].Extendeds[ExpGained]), clRed);
SMART_DrawTextEx(False, 10, 65, 'UpChars', 'Levels Gained: ', ClRed);
SMART_DrawTextEx(False, 140, 65, 'UpChars', IntToStr(Players[CurrentPlayer].Integers[LevelsGained]), clRed);
P_ProgressBar(100 * Players[CurrentPlayer].Integers[LogsBurnt] / Players[CurrentPlayer].Integers[BurnHowMany], 10, 80);

SMART_DrawTextEx(False, 310, 20, 'UpChars', 'Time Running', clRed);
SMART_DrawTextEx(False, 450, 20, 'UpChars', MsToTime(GetTimeRunning, Time_Short), clRed);
SMART_DrawTextEx(False, 310, 35, 'UpChars', 'Players Active', clRed);
SMART_DrawTextEx(False, 450, 35, 'UpChars', IntToStr(PlayersActive) + '/' + IntToStr(HowManyPlayers), clRed);
end;

procedure P_TextProgressReportSingle;
begin
P_Debug('*****************************************************************');
P_Debug('****************Welcome To Bad Boy JH''s Firemaker****************');
P_Debug('*****************************************************************');
P_Debug(PadR('**** Players Name: ' + Players[CurrentPlayer].Name, 60) + ' ****');
P_Debug(PadR('**** Players Loads Done: ' + IntToStr(Players[CurrentPlayer].Integers[LoadsDone]), 60) + ' ****');
P_Debug(PadR('**** Players Exp Gained: ' + FloatToStr(Players[CurrentPlayer].Extendeds[ExpGained]), 60) + ' ****');
P_Debug(PadR('**** Players Levels Gained: ' + IntToStr(Players[CurrentPlayer].Integers[LevelsGained]), 60) + ' ****');
P_Debug('*****************************************************************');
end;

procedure P_TextProgressReportMulti;
var
I: integer;
begin
P_Debug('*************************************************************************');
P_Debug('********************Welcome To Bad Boy JH''s Firemaker********************');
P_Debug('*************************************************************************');
P_Debug('**** Nick * Active * Loads * Logs Burnt * Exp Gained * Levels Gained ****');
for I := 0 to High(Players) do
P_Debug('**** ' +
PadR(Players[i].Nick, 4) + ' * ' +
PadR(BoolToStr(Players[i].Active), 6) + ' * ' +
PadR(IntToStr(Players[i].Integers[LoadsDone]), 5) + ' * ' +
PadR(IntToStr(Players[i].Integers[LogsBurnt]), 10) + ' * ' +
PadR(FloatToStr(Players[i].Extendeds[ExpGained]), 10) + ' * ' +
PadR(IntToStr(Players[i].Integers[LevelsGained]), 13) + ' ****');
P_Debug('*************************************************************************');
end;

procedure AntiRandoms;
{AntiRandoms - Straight forward, It checks for randoms}
begin
{$ifdef Reflection}
R_FindRandoms;
{$endif}
FindNormalRandoms;
end;

function WalkTo(Tile: TPoint; Dist: Integer): Boolean;
{WalkTo - Walks to the specified tile, if it cannot do with reflection,
it will attempt to do it with the colour equivilant}
begin
{$ifdef Reflection}
Result := WalkToTile(Tile, 0, Dist);
if Result then
Exit;
{$endif}
Result := C_WalkToTile(Tile, Dist);
end;

function WalkToStartPos: Boolean;
{WalkToStartPos - Walks to one of the better spots to start burning logs
if you have burnt part of a load, it will not use the same Y coordinate}
var
X, Y: Integer;
begin
AntiRandoms;
Players[CurrentPlayer].Status := ' walking to starting position';
X := 3095+ Random(3);
{$ifdef Reflection}
Y := R_BestYCoordinate(3247, 3250);
{$else}
Y := C_BestYCoordinate(3247, 3250);
{$endif}
if Y = 0 then
begin
AntiRandoms;
Y := Random(4) + 3247;
end;
Result := WalkTo(Point(X, Y), 0);
if Result then
Exit;
Wait(RandomRange(50, 125));
AntiRandoms;
end;

function WalkToBank: Boolean;
{WalkToBank - Walks inside the bank}
begin
AntiRandoms;
Players[CurrentPlayer].Status := ' walking into bank';
Result := WalkTo(Point(3092 + Random(4), 3242 + Random(4)), 0);
Inc(Players[CurrentPlayer].Integers[LoadsDone]);
AntiRandoms;
end;

procedure WalkToDraynor;
begin
{$ifdef Reflection}
if not WalkToTile(Tile(3091,3243), 2, 0) then
WorldWalkTo(Point(3091,3243));
{$else}
WW_Walk(Point(686, 389));
{$endif}
end;

function Bank: Boolean;
{Bank - Opens Bank and withdraws the logs}
var
I: Integer;
begin
Players[CurrentPlayer].Status := ' opening Bank';
AntiRandoms;
{$ifdef Reflection}
if not R_OpenBankBooth('db') then
{$endif}
if not OpenBank('db', False, False) then
if not OpenBank('db', True, True) then
Exit;
AntiRandoms;
if Players[CurrentPlayer].Integers[TinderboxFindingStatus] = CheckBank then
begin
Players[CurrentPlayer].Status := ' searching bank for tinderbox';
P_Debug('Searching bank for tinderbox...');
{$ifdef Reflection}
if R_WithdrawItemID(TinderboxID, I, 1) then
begin
P_Debug('Found tinderbox in bank');
Players[CurrentPlayer].Integers[TinderboxFindingStatus] := Found;
end else begin
Players[CurrentPlayer].Status := ' trying to get tinderbox from lumbridge';
P_Debug('Tinderbox not found in bank');
P_Debug('Walking to Lumbridge general store to take the free tinderbox');
WorldWalkTo(Point(3214, 3241))
if not DistanceFrom(Tile(3214, 3241)) < 10 then
Exit;
if not R_OpenGeneralStore then
Exit;
MouseBox(935, 255, 970, 280, 2);
if not R_ChooseOption('Take 1') then
Exit;
P_Debug('Taken free tinderbox, walking back to draynor');
WorldWalkTo(Point(3091,3243))
if not DistanceFrom(Point(3091,3243)) < 10 then
Exit;
Players[CurrentPlayer].Integers[TinderboxFindingStatus] := Found;
end;
{$else}
if C_WithdrawTinderbox then
begin
P_Debug('Found tinderbox in bank');
Players[CurrentPlayer].Integers[TinderboxFindingStatus] := Found;
end else begin
Players[CurrentPlayer].Status := ' trying to get tiderbox from lumbdridge';
P_Debug('Tinderbox not found in bank');
P_Debug('Walking to Lumbridge general store to take the free tinderbox');
if not WW_Walk(Point(695, 389)) then
Exit;
if not C_OpenGeneralStore then
Exit;
MouseBox(935, 255, 970, 280, 2);
if not ChooseOption('ake 1') then
Exit;
P_Debug('Taken free tinderbox, walking back to draynor');
Players[CurrentPlayer].Integers[TinderboxFindingStatus] := Found;
end;
{$endif}
{$ifdef Reflection}
Players[CurrentPlayer].Status := ' opening Bank';
if not R_OpenBankBooth('db') then
{$endif}
if not OpenBank('db', False, False) then
if not OpenBank('db', True, True) then
Exit;
end;
{$ifdef Reflection}
Players[CurrentPlayer].Status := ' depositing';
R_Deposit;
Players[CurrentPlayer].Status := ' withdrawing';
Result := R_WithdrawLogs;
{$ELSE}
Players[CurrentPlayer].Status := ' depositing';
C_Deposit;
Players[CurrentPlayer].Status := ' withdrawing';
Result := C_WithdrawLogs;
{$endif}
end;

function WaitLogsBurnt(var CantLight: Boolean): Boolean;
{WaitLogsBurnt Waits for the logs to catch alight}
var
Mark: Integer;
{$ifdef Reflection}
StartTile: TTile;
{$endif}
begin
CantLight := False;
{$ifdef Reflection}
StartTile := GetMyPos;
MarkTime(Mark);
while TimeFromMark(Mark) < 5000 do
begin
if LevelUp then
Inc(Players[CurrentPlayer].Integers[LevelsGained]);
if (GetMyPos <> StartTile) then
begin
Result := True;
Exit;
end;
AntiRandoms;
if GetAnimation = 733 then
MarkTime(Mark);
if R_CantLightFire then
CantLight := True;
Wait(RandomRange(125, 375));
end;
{$ELSE}
MarkTime(Mark);
while TimeFromMark(Mark) < 5000 do
begin
if C_CantLightFire then
begin
CantLight := True;
Exit;
end;
AntiRandoms;
if Animating(IntToBox(MSCX - 10, MSCY - 25, MSCX + 20, MSCY + 17), 25, 200) then
MarkTime(Mark);
if LevelUp then
Inc(Players[CurrentPlayer].Integers[LevelsGained]);
if PixelShift(MMBox, 100) > 400 then
begin
Result := True;
Exit;
end;
Wait(RandomRange(25, 75));
end;
{$endif}
end;

function BurnLogs: Boolean;
{BurnLogs - Burns the full inventory of logs}
var
Temp: TPoint;
TinderboxSlot, I: Integer;
CantLight, TinderFirst: Boolean;
BurnPattern: TIntegerArray;
{$ifndef Reflection}
Box: TBox;
{$endif}
begin
Players[CurrentPlayer].Status := ' looking in inventory for tinderbox';
{$ifdef Reflection}
for I := 1 to 28 do
if GetItemIDAt(I) = TinderboxID then
TinderboxSlot := I;
if TinderboxSlot = 29 then
Exit;
{$ELSE}
for I := 1 to 28 do
begin
Box := InvBox(I);
if CountColorTolerance(470582, Box.x1, Box.y1, Box.x2, Box.y2, 20) > 75 then
begin
TinderboxSlot := I;
Break;
end;
end;
if I = 29 then
Exit;
{$endif}
Players[CurrentPlayer].Status := ' burning logs';
while InvCount > 1 do
begin
BurnPattern := LoadRandomPattern;
for I := 0 to 27 do
begin
if BurnPattern[i] = TinderboxSlot then
Continue;
if not ExistsItem(BurnPattern[i]) then
Continue;
if TinderFirst then
MouseItem(TinderboxSlot, True);
MouseItem(BurnPattern[i], True);
if not TinderFirst then
MouseItem(TinderboxSlot, True);
TinderFirst := not TinderFirst;
if not WaitLogsBurnt(CantLight) then
if CantLight then
begin
Dec(I);
WalkToStartPos;
P_DrawReportOnSmart;
Continue;
end else
Exit;
{$ifdef Reflection}
Temp := GetMyPos;
{$else}
Temp := C_GetMyPos;
{$endif}
if Temp.x <= 3079 then
begin
WalkToStartPos;
P_DrawReportOnSmart;
end;
Players[CurrentPlayer].Extendeds[ExpGained] := Players[CurrentPlayer].Extendeds[ExpGained] + LoadEXPValue;
Inc(Players[CurrentPlayer].Integers[LogsBurnt]);
if LevelUp then
Inc(Players[CurrentPlayer].Integers[LevelsGained]);
end;
end;
Result := True;
end;

function BreakTime: Boolean;
begin
Result := (TimeFromMark(LoginTime) > TimeBetweenBreaks) and TakeBreaks;
end;

procedure TakeBreak;
begin
Players[CurrentPlayer].Status := ' taking break';
if TakeBreaks and (not AllPlayersInactive) then
Wait(RandomRange(BreakFor * 85 / 100, BreakFor * 115 / 100));
end;

procedure Setup;
begin
F_CreatePlayerForm;
SetupSRL;
SmartSetDebug(true);
{$ifdef Reflection}
SetupReflectionEx(True);
SetupNodesAndPaths;
{$endif}
CurrentPlayer := High(Players);
// AddOnTerminate(0);
end;

procedure Login;
var
{$ifdef Reflection}
Item: TInvItem;
{$else}
X, Y: Integer;
{$endif}
begin
CurrentPlayer := (CurrentPlayer + 1) mod HowManyPlayers;
LoginPlayer;
MarkTime(LoginTime);
SetAngle(True);
SetRun(True);
Wait(RandomRange(2500, 5000));
{$ifdef Reflection}
while not R_LoggedIn do
{$else}
while not LoggedIn do
{$endif}
begin
Wait(RandomRange(50, 100));
if TimeFromMark(LoginTime) > 60000 then
Break
end;
{$ifdef Reflection}
if not R_ItemExists(TinderboxID, Item) then
{$else}
if not False then
{$endif}
begin
P_Debug(Players[CurrentPlayer].Name + ' doesn''t have a tinderbox in their inventory');
P_Debug('Walking to Draynor, and checking the bank for one');
Players[CurrentPlayer].Integers[TinderboxFindingStatus] := CheckBank;
end else
Players[CurrentPlayer].Integers[TinderboxFindingStatus] := Found;
{$ifdef Reflection}
if not MeInBox(IntToBox(3084, 3249, 3102, 3235)) then
{$else}
WW_GetPos(X, Y);
if not InRange(X, 685, 686) and InRange(Y, 388, 389) then
{$endif}
WalkToDraynor;
end;

procedure PlayerLoop;
{PlayerLoop - Plays out a player until they
are finished or it is time to take a break}
begin
Login;
while (Players[CurrentPlayer].Integers[BurnHowMany] > Players[CurrentPlayer].Integers[LogsBurnt]) or (Players[CurrentPlayer].Integers[BurnHowMany] = 0) do
begin
if not Bank then
Break;
P_Debug('Banked Successfully');
P_DrawReportOnSmart;

if not WalkToStartPos then
Break;
P_Debug('Walked to starting position');
P_DrawReportOnSmart;

if not BurnLogs then
Break;
P_Debug('Logs burnt');
P_DrawReportOnSmart;

if not WalkToBank then
Break;
P_Debug('Walked to bank');
P_DrawReportOnSmart;

if HowManyPlayers = 1 then
P_TextProgressReportSingle else
P_TextProgressReportMulti;
if BreakTime then
Exit;
end;
if (Players[CurrentPlayer].Integers[BurnHowMany] <= Players[CurrentPlayer].Integers[LogsBurnt]) then
P_Debug(Players[CurrentPlayer].Name + ' finished successfully!') else
P_Debug(Players[CurrentPlayer].Name + ' failed whilst' + Players[CurrentPlayer].Status);
Players[CurrentPlayer].Active := False;
Logout;
end;

begin
Setup;
while not AllPlayersInactive do
begin
PlayerLoop;
TakeBreak;
end;
end.