mormonman
2011-01-12 18:55:28
Made it more failsafed, could still use some work but I accidentally let it solve the random completely on my account.
//Special thanks to bolshak25.
const
LEO_GRAVESTONE_MIDDLE = 12718;
LEO_CASKET1 = 12721;
LEO_CASKET2 = 12722;
LEO_CASKET3 = 12723;
LEO_CASKET4 = 12724;
LEO_CASKET5 = 12725;
LEO_EMPTY_GRAVE1 = 12726;
LEO_EMPTY_GRAVE2 = 12727;
LEO_EMPTY_GRAVE3 = 12728;
LEO_EMPTY_GRAVE4 = 12729;
LEO_EMPTY_GRAVE5 = 12730;
LEO_INVENTORY_CASKET1 = 7587;
LEO_INVENTORY_CASKET2 = 7588;
LEO_INVENTORY_CASKET3 = 7589;
LEO_INVENTORY_CASKET4 = 7590;
LEO_INVENTORY_CASKET5 = 7591;
LEO_FLOWERPOTID = 7608;
LEO_PICKAXEID = 7607;
LEO_CHEFHATID = 7601;
LEO_HATCHETID = 7603;
LEO_SHEARSID = 7610;
{*******************************************************************************
function R_LeoComponentID (ParentI, ChildI : Integer) : Integer;
By: Cstrike
Description: This function wasn't in the core, so I made my own.
*******************************************************************************}
function R_LeoComponentID (ParentI, ChildI : Integer): Integer;
var
Child: Integer;
begin
Child := GetInterface(ParentI, ChildI);
Result := SmartGetFieldInt(Child, hook_interface_GetID);
SmartFreeObject(Child);
end;
{*******************************************************************************
procedure R_LeoInvDecrease (amount, timeout : Integer);
By: Cstrike
Description: Function used mainly for seeing when we have put the casket in the
grave.
*******************************************************************************}
procedure R_LeoInvDecrease(Amount, Timeout: Integer);
var
T, Count: Integer;
begin
If not LoggedIn then
Exit;
Count := R_InvCount;
MarkTime(T);
repeat
Wait(50+random(25));
until(TimeFromMark(t) > Amount)or(Count < R_InvCount)
Wait(4000+random(2500)); // More human?
end;
{*******************************************************************************
function R_InLeo : Boolean;
By: Cstrike
Description: Returns True if in Gravedigger.
*******************************************************************************}
function R_InLeo: Boolean;
begin
Result := ValidNPC('Leo');
end;
{*******************************************************************************
procedure R_LeoWalkToCenter;
By: Cstrike
Description: Moves us above middle grave so everything is in sight.
*******************************************************************************}
procedure R_LeoWalkToCenter;
var
GraveStone: TRSObject;
TP: TPoint;
begin
GraveStone := GetObjectByID (LEO_GRAVESTONE_MIDDLE, OBJECT_TYPE_INTERACTABLE, 52);
TP := TileToMM(Tile(GraveStone.Tile.X, GraveStone.Tile.Y+1));
Mouse (TP.X, TP.Y, 1, 1, True);
Wait (3000+Random(1200));
end;
{*******************************************************************************
function R_TalkToLeoStart : Boolean;
By: Cstrike
Description: Talks to Leo at start (if we are already, proceeds normally).
*******************************************************************************}
function R_TalkToLeoStart: Boolean;
var
T, X, Y: Integer;
NPCs: TNPCArray;
TP: TPoint;
begin
Result := False;
if not LoggedIn then
Exit;
if (not ValidInterface(242)) and (not ValidInterface(241)) and (not ValidInterface(243)) and (not ValidInterface(64)) then
begin
NPCs := SortNPCs(GetAllNPCs(False));
if Not TileOnMS(NPCs[0].Tile, 0)then
R_LeoWalkToCenter;
TP := TileToMS (NPCs[0].Tile, 0);
Mouse(TP.X, TP.Y, 3, 3, False);
Wait(500+Random(500));
if ChooseOptionMulti(['Ta','-to'])then
begin
Wait(1000+Random(1000));
Flag;
R_Debug('Talked to leo', 'Leo');
end;
Wait(2500+random(1500));
end else
R_Debug('Leo is already chatting with us', 'Leo');
Wait(3000+random(2000)); // Stops lag at start up from screwing us over
MarkTime(T);
repeat
if (GetInterfaceText(242, 6) = 'Click here to continue')then
Mouse(303, 452, 72, 7, True);
if (GetInterfaceText(241, 5) = 'Click here to continue') or (GetInterfaceText(243, 7) = 'Click here to continue') or (GetInterfaceText(64, 5) = 'Click here to continue') then
begin
GetMousePos(X, Y);
Mouse(X, Y, 0, 0, True);
end;
if (ValidInterface(220)) then
Mouse(456, 44, 6, 6, True);
Wait(670+random(600));
if (not ValidInterface(242)) and (not ValidInterface(241)) and (not ValidInterface(243)) and (not ValidInterface(64)) and (not ValidInterface(220)) then
begin
R_Debug('Successfully done talking to leo', 'Leo');
Result := True;
Exit;
end;
until (TimeFromMark(t) > 30000)
R_Debug('Timeout talking to Leo at start', 'Leo');
end;
{*******************************************************************************
function R_LeoDropInv : TIntegerArray;
By: Cstrike
Description: Makes space by dropping items farthest down in your inventory.
result := [tile x dropped, tile y dropped (, item1 (, item2 (, item 3...];
*******************************************************************************}
function R_LeoDropInv: TIntegerArray;
var
i, arrPos: Integer;
myTile: TTile;
begin
if not LoggedIn then
Exit;
Result := [];
if R_InvCount > 23 then
begin
R_Debug('Making space for random', 'Leo');
arrPos := 2; // 0 is Tile.x, 1 is Tile.y, 2 is item1, 3 is item2...etc, we want to start filling at index w/ arrPos
SetArrayLength (result, (R_InvCount-23)+2); // If count is 25, then we have the first 2 as tile, last two as ID's
myTile := GetMyPos;
result[0] := myTile.x;
result[1] := myTile.y;
for i:=28 downto 0 do // If there is that 'destroy crap' for whatever, then this will probably skip it... thus downto 0
begin
if R_InvCount < 24 then
Exit;
if R_ItemExists(i) then
begin
result[arrPos] := GetItemIDAt(i);
R_DropItem(i);
Wait (900+random(350));
Inc(arrPos);
end;
end;
end else R_Debug('We have 5+ inventory spaces for the Leo random, proceeding...', 'Leo');
end;
{*******************************************************************************
procedure R_LeoRetrieveInv (TIA : TIntegerArray);
By: Cstrike
Description: If you dropped anything, picks it up.
*******************************************************************************}
procedure R_LeoRetrieveInv(TIA: TIntegerArray);
var
GIA: TGroundItemArray;
t: Integer;
TP: TPoint;
begin
if not LoggedIn then
Exit;
if (high(TIA) < 0) then
Exit;
GIA := []; // Failsafe
MarkTime(t);
R_Debug('Picking up items dropped', 'Leo');
if (high(TIA) < 2) then
Exit
else // No items to retrieve
begin
if not TileOnMS(Tile(TIA[0],TIA[1]), 0)then
WalkToTile (Tile(TIA[0],TIA[1]), 1, 0);
repeat
GIA := GetItemsAt(Tile(TIA[0],TIA[1]));
if high(GIA) > -1 then
begin
TP := TileToMS(Tile(TIA[0],TIA[1]), 0);
Mouse(TP.x, TP.y, 2, 2, True);
Wait (500+random(250));
end;
until (high(GIA) < 0) or (TimeFromMark(t) > 15000)
end;
GIA := []; // Need to blank this for a memory reason
TIA := []; // Blank TIA in case we fail and need to start fresh
end;
{*******************************************************************************
function R_LeoGraveTiles (i : Integer) : TTile;
By: Cstrike
Description: Returns grave tile positions relative to Leo. This can be revamped
in the future with objects.
*******************************************************************************}
function R_LeoGraveTiles (i : Integer): TTile;
var
NPCs : TNPCArray;
LeoTile : TTile;
begin
if not LoggedIn then
Exit;
Result := Tile(0,0); // Failsafe
NPCs := SortNPCs(GetAllNPCs(False));
LeoTile := NPCs[0].Tile;
case i of // BL, TL, BM, TR, Bottom Right [BR]
0: result := Tile(LeoTile.x-4,LeoTile.y-7);
1: result := Tile(LeoTile.x-2,LeoTile.y-4);
2: result := Tile(LeoTile.x-0,LeoTile.y-7);
3: result := Tile(LeoTile.x+2,LeoTile.y-4);
4: result := Tile(LeoTile.x+4,LeoTile.y-7);
end;
end;
{*******************************************************************************
function R_LeoGravestoneTiles (i : Integer) : TTile;
By: Cstrike
Description: Returns graveSTONE tile positions relative to Leo. This can be
revamped in the future with objects.
*******************************************************************************}
function R_LeoGravestoneTiles (i : Integer): TTile;
var
NPCs : TNPCArray;
LeoTile : TTile;
begin
if not LoggedIn then
Exit;
Result := Tile(0,0);
NPCs := SortNPCs(GetAllNPCs(False));
LeoTile := NPCs[0].Tile;
case i of // BL, TL, BM, TR, Bottom Right [BR]
0: result := Tile(LeoTile.x-4,LeoTile.y-5);
1: result := Tile(LeoTile.x-2,LeoTile.y-2);
2: result := Tile(LeoTile.x-0,LeoTile.y-5);
3: result := Tile(LeoTile.x+2,LeoTile.y-2);
4: result := Tile(LeoTile.x+4,LeoTile.y-5);
end;
end;
{*******************************************************************************
function R_GraveObjectCoffinCollect : Boolean;
By: Cstrike
Description: Collects all the coffins. Returns True if successful.
*******************************************************************************}
// 12718 = middle gravestone
function R_GraveObjectCoffinCollect: Boolean;
var
ObjCasket, ObjCasketUpdated : TRSObjectArray;
t, InviCount : Integer;
TP : TPoint;
begin
if not LoggedIn then
Exit;
Result := False;
// Failsafe below
ObjCasket := GetObjectsByIDEx ([LEO_CASKET1, LEO_CASKET2, LEO_CASKET3, LEO_CASKET4, LEO_CASKET5], OBJECT_TYPE_INTERACTABLE, 12);
if high(ObjCasket) < 0 then
begin
R_Debug('We have all the coffins', 'Leo');
Result := True;
Exit;
end;
// Main part of script
SetAngle(True);
R_Debug('Grabbing coffins', 'Leo');
repeat
ObjCasketUpdated := GetObjectsByIDEx ([LEO_CASKET1, LEO_CASKET2, LEO_CASKET3, LEO_CASKET4, LEO_CASKET5], OBJECT_TYPE_INTERACTABLE, 12); // Allows for dynamic stuff
if high(ObjCasketUpdated) < 0 then
Break;
if not TileOnMS(ObjCasketUpdated[0].Tile, 0) then
R_LeoWalkToCenter;
TP := TileToMS (ObjCasketUpdated[0].Tile, 0);
Mouse (TP.x, TP.y, 2, 3, True);
InviCount := R_InvCount;
MarkTime(t);
repeat
Wait(50);
until (R_InvCount > InviCount) or (TimeFromMark(t) > 10000)
until (high(ObjCasketUpdated) < 0)
if (R_CountItemID(LEO_INVENTORY_CASKET1) = 1) and (R_CountItemID(LEO_INVENTORY_CASKET2) = 1) and (R_CountItemID(LEO_INVENTORY_CASKET3) = 1) and (R_CountItemID(LEO_INVENTORY_CASKET4) = 1) and (R_CountItemID(LEO_INVENTORY_CASKET5) = 1) then result := True;
end;
{*******************************************************************************
function R_LeoFindCasket (name : String) : Integer;
By: Cstrike
Description: Searches for the name of what casketID matches the name you give it
*******************************************************************************}
function R_LeoFindCasket (name : String): Integer;
var
i, j, IDToFind : Integer;
begin
if not LoggedIn then
Exit;
Result := 0;
case name of
'flowerpot': IDToFind := LEO_FLOWERPOTID;
'pickaxe': IDToFind := LEO_PICKAXEID;
'chef hat': IDToFind := LEO_CHEFHATID;
'hatchet': IDToFind := LEO_HATCHETID;
'watertank': IDToFind := LEO_SHEARSID;
end;
for i:=LEO_INVENTORY_CASKET1 to LEO_INVENTORY_CASKET5 do
begin
R_ClickItemID(i, True, 'open');
Wait(2000+random(1500));
for j:=3 to 11 do // Search interfaces for ID to find
begin
Wait(50+random(50)); // More human like waiting
if (R_LeoComponentID (141, j) = IDToFind) then // 141 is the ID
begin
R_Debug('Found proper casket for grave', 'Leo');
Result := i;
Mouse(493, 27, 3, 3, True);
Wait(700+random(500));
Exit;
end;
end;
end;
end;
{*******************************************************************************
function R_LeoFindEmptyGrave : Integer;
By: mormonman
Description: Finds an empty grave and returns its gravestone number.
*******************************************************************************}
function R_LeoFindEmptyGrave: Integer;
var
EmptyArr, FullArr: TIntegerArray;
obj: TRSObject;
i, Hi: Integer;
begin
Result := -1;
if not LoggedIn then
Exit;
EmptyArr := [LEO_EMPTY_GRAVE1, LEO_EMPTY_GRAVE2, LEO_EMPTY_GRAVE3,
LEO_EMPTY_GRAVE4, LEO_EMPTY_GRAVE5];
for i := 0 to 4 do
begin
obj := GetObjectAt(R_LeoGraveTiles(i), OBJECT_TYPE_INTERACTABLE);
if obj.ID = EmptyArr[i] then
begin
Result := i;
R_Debug('Empty Grave Index: ' + ToStr(i), 'Leo');
Exit;
end;
end;
end;
{*******************************************************************************
function R_LeoSolveGraves : Boolean;
By: Cstrike/mormonman
Description: This is the big procedure that solves the graves. False = failed.
*******************************************************************************}
function R_LeoSolveGraves : Boolean;
var
i, j, t, texID, CasketID, CurGrave, iTime : Integer;
GStoneTile : TTile;
TP : TPoint;
texName: String;
begin
Result := False;
if not LoggedIn then
Exit;
MarkTime(iTime);
repeat
CurGrave := R_LeoFindEmptyGrave;
if (CurGrave > -1) then
begin
R_Debug('Starting on grave[' +ToStr(CurGrave)+ ']', 'Leo');
GStoneTile := R_LeoGravestoneTiles(CurGrave);
if not TileOnMS(GStoneTile, 0) then
R_LeoWalkToCenter;
TP := TileToMS(GStoneTile, 0);
Mouse(TP.x, TP.y, 3, 3, True);
MarkTime(t);
repeat
Wait(500);
until(ValidInterface(143))or(TimeFromMark(t) > 10000);
if ValidInterface(143) then
begin
for j:=0 to 3 do // Search the 3x3 item square
begin
texID := R_LeoComponentID(143, j);
case texID of
7614: texName := 'hatchet';
7615: texName := 'chef hat';
7616: texName := 'pickaxe';
7617: texName := 'watertank';
7618: texName := 'flowerpot';
end;
R_Debug('Found '+texName+' model (ID Found: '+inttostr(texID)+')', 'Leo');
Wait(1100+random(1100)); // Seem human I guess?
Mouse(491, 29, 3, 3, True);
Wait(100+random(500)); // Exits the model view
CasketID := R_LeoFindCasket(texName);
R_Debug('Casket ID found = '+inttostr(casketID), 'Leo');
if R_ClickItemID(CasketID, false, 'use') then
begin
TP := TileToMS(Tile(GStoneTile.x, GStoneTile.y-1), 0);
Mouse (TP.x, TP.y, 3, 3, True);
R_LeoInvDecrease(1, 12000);
end;
end;
end;
Wait(1000+Random(1000)); // More Wait here, must replace thsi later on
end else R_Debug('CurGrave is -1', 'Leo');
until (R_LeoFindEmptyGrave = -1) or (TimeFromMark(iTime) > 300000);//5 minutes to solve
Result := (TimeFromMark(iTime) < 300000) and LoggedIn
and (R_CountItemIDEx([LEO_INVENTORY_CASKET1, LEO_INVENTORY_CASKET2,
LEO_INVENTORY_CASKET3, LEO_INVENTORY_CASKET4, LEO_INVENTORY_CASKET5]) < 1);
end;
{*******************************************************************************
function R_TalkToLeoEnd : Boolean;
By: Cstrike
Description: Talks to Leo to solve the random. If we mess up, returns false.
*******************************************************************************}
function R_TalkToLeoEnd : Boolean;
var
t: Integer;
NPCs: TNPCArray;
TP: TPoint;
begin
Result := False;
if not LoggedIn then
Exit;
if (not ValidInterface(241)) and (not ValidInterface(64)) then
begin
NPCs := SortNPCs(GetAllNPCs(False));
if not TileOnMS(NPCs[0].Tile, 0) then
begin
WalkToTile(NPCs[0].Tile, 0, 0);
Wait(2000+Random(1000));
end;
TP := TileToMS (NPCs[0].Tile, 0);
Mouse(TP.x, TP.y, 3, 3, false);
Wait(500+random(500));
if ChooseOptionMulti(['Ta','-to']) then
begin
R_Debug('Talked to leo at end', 'Leo');
Wait(1000+Random(1000));
Flag;
end;
Wait(2500+random(1500));
end else R_Debug('Leo is already chatting with us', 'Leo');
Wait (3000+random(2000)); // Stops lag at start up from screwing us over
MarkTime(t);
repeat
if (GetInterfaceText(241, 5) = 'Click here to continue') or (GetInterfaceText(64, 5) = 'Click here to continue') then Mouse (303, 452, 72, 7, True);
Wait (670+random(600));
if (not ValidInterface(241)) and (not ValidInterface(64)) then
begin
R_Debug('Done chatting with Leo at end', 'Leo');
Result := True;
Exit;
end;
until (TimeFromMark(t) > 20000)
R_Debug('Timeout talking to Leo at end, result = false', 'Leo');
end;
{*******************************************************************************
function R_SolveLeo : Boolean;
By: Cstrike
Description: Attempts to solve the random.
*******************************************************************************}
function R_SolveLeo : Boolean;
var failsafe : Integer;
ItemDropData : TIntegerArray;
begin
result := false;
ItemDropData := []; // Failsafe
if R_InLeo then
begin
failsafe := 0;
repeat
R_Debug('Leo Phase 1: Talk to Leo at start', 'Leo');
if R_TalkToLeoStart then
begin
if R_InvCount > 23 then
ItemDropData := R_LeoDropInv; // Declared it here so it can pick it up later
R_Debug('Leo Phase 2: Collect graves', 'Leo');
if R_GraveObjectCoffinCollect then
begin
R_Debug('Leo Phase 3: Solve the graves', 'Leo');
if R_LeoSolveGraves then
begin
if (high(ItemDropData) < 0) then
R_LeoRetrieveInv (ItemDropData); // If we dropped something, now is the time to pick it up
R_Debug('Leo Phase 4: Talk to Leo at end', 'Leo');
if R_TalkToLeoEnd then
begin
Wait(3000+Random(2000));
result := True;
Exit;
end;
end else
begin
R_Debug('Failed solving graves', 'Leo');
if (high(ItemDropData) < 0) then
R_LeoRetrieveInv (ItemDropData); // If we dropped something, now is the time to pick it up
Inc(failsafe);
end;
end else
begin
R_Debug('Had trouble grabbing all the ground coffins', 'Leo');
Inc(failsafe);
end;
end else
begin
R_Debug('Had trouble talking to leo @ start', 'Leo');
Inc(failsafe);
end;
if failsafe < 3 then
R_Debug('Re-attempting Leo', 'Leo');
until (failsafe > 2)
if failsafe > 2 then
begin
R_Debug('We have failed leo too many times, aborting Leo solving procedure', 'Leo');
Exit;
end;
end;
end;