SRL Archive - Devs' Corner

Objects - Fixed!


Drakan

2010-05-23 12:26:16

So guys, I've been working with people, and thanks to the help of Benland, Cohen, and anyone else that gave me some input, I have come up with a working GetObjectAt. Now, the problem is I don't have the hooks on our updater. However, Cohen does, so I'll be talking to him when I get home later today and see what we can work out. For now, here is my hooks list and Objects.simba:
EDIT: Heres my current Objects.simba.
Now, I did things in here that are kinda different then we used to do them. However, look around, read through the functions, and look at the test mining script that I made. It works very well this way and is pretty flawless. If you have questions on how I decided to do things, feel free to ask.

const
INTERACTABLE = 0;
WALLOBJECT = 1;
WALLDECOR = 2;
FLOORDECOR = 3;


Type
TRSObject = Record
objType: integer;
ID: Integer;
Tile: TTile;
End;

TRSObjectArray = array of TRSObject;

{*******************************************************************************
function NullObject: TRSObject;
By: Drags111
Description: Returns a "null" object.
Uses:
Result := NullObject;...
If(GetObjectBlah() = NullObject)then... etc
*******************************************************************************}
function NullObject: TRSObject;
begin
Result.ID := -1;
Result.objType := -1;
Result.Tile := PointToTile(-1, -1);
end;

{*******************************************************************************
function NewObject(ID, objType, Tile): TRSObject;
By: Drags111
Description: Returns a new TRSObject with the specified values.
*******************************************************************************}
function NewObject(ID, objType: integer; Tile: TTile): TRSObject;
begin
Result.ID := ID;
Result.objType := objType;
Result.Tile := Tile;
end;

{*******************************************************************************
function RSObjectInArray(theArray: TRSObjectArray; obj: TRSObject): boolean;
By: Drags111
Description: Returns true if an object obj is in a TRSObjectArray theArray.
(like IntInArray).
*******************************************************************************}
function RSObjectInArray(theArray: TRSObjectArray; obj: TRSObject): boolean;
var
i: integer;
begin
for i := 0 to High(theArray) do
if(theArray[i] = obj)then
begin
Result := true;
Exit;
end;
Result := false;
end;

{*******************************************************************************
function GetObjectAt(Tile: TTile; objType: Integer): TRSObject;
By: Drags111
Description: Finds an object (specified by objType(INTERACTABLE, WALLOBJ, etc..))
at the specified tile.
*******************************************************************************}
function GetObjectAt(Tile: TTile; objType: Integer): TRSObject;
var
X, Y, Ground, CurrPlane, Node, Obj, ID: Integer;
TheType: integer;
IDHook: String;
begin
Result := NullObject;

X := Tile.X - SmartGetFieldInt(0, hook_static_BaseX);
Y := Tile.Y - SmartGetFieldInt(0, hook_static_BaseY);
CurrPlane := SmartGetFieldInt(0, hook_static_LoadedPlane);

try
Ground := SmartGetFieldArray3DObject(0, hook_static_GroundTiles, CurrPlane, X, Y);

case objType of
INTERACTABLE: begin
// Interactable objects like trees
Node := SmartGetFieldObject(Ground, AnimableList);
while(node <> 0)do
begin
SmartFreeObject(Obj);
Obj := SmartGetFieldObject(Node, hook_AnimableNode_GetAnimable);
if(Obj > 0)then
begin
ID := SmartGetFieldShort(Obj, hook_InteractiveObject_GetID);
Result := NewObject(ID and $FFFF, INTERACTABLE, Tile);
Exit;
end;
Node := SmartGetFieldObject(Node, hook_AnimableNode_GetNext);
end;
end;
WALLOBJECT: begin
Obj := SmartGetFieldObject(Ground, WallObject1);
if(Obj = 0)then
Obj := SmartGetFieldObject(Ground, WallObject2);
IDHook := hook_wallobjectdata_GetID;
end;
WALLDECOR: begin
Obj := SmartGetFieldObject(Ground, WallDecoration1);
if(Obj = 0)then
Obj := SmartGetFieldObject(Ground, WallDecoration2);
IDHook := hook_WallDecorationData_GetID;
end;
FLOORDECOR: begin
Obj := SmartGetFieldObject(Ground, FloorDecoration);
IDHook := hook_FloorDecorationData_GetID;
end;
end;
if(Obj > 0)then
begin
ID := SmartGetFieldShort(Obj, IDHook);
Result := NewObject(ID and $FFFF, objType, Tile);
Exit;
end;
finally
SmartFreeObject(Node);
SmartFreeObject(Obj);
SmartFreeObject(Ground);
end;
end;

{*******************************************************************************
function GetAllObjects(objType: integer): TRSObjectArray;
By: Drags111
Description: Gets all loaded objects of the type objType.
*******************************************************************************}
function GetAllObjects(objType: integer): TRSObjectArray;
var
bx, by, x, y, idx, i: integer;
obj: TRSObject;
begin
SetLength(Result, 1);
bx := SmartGetFieldInt(0, hook_static_BaseX);
by := SmartGetFieldInt(0, hook_static_BaseY);
for x := bx to (104 + bx) do
begin
for y := by to (104 + by) do
begin
Obj := GetObjectAt(PointToTile(x, y), objType);
if(Obj.ID = 0)then continue;
SetLength(Result, Length(Result)+1);
Result[High(Result)] := Obj;
end;
end;
end;

{*******************************************************************************
function FindRSObjectEx(Objs: TRSObjectArray): boolean;
By: Drags111
Description: Returns true if one of the objects in the TRSObjectArray is found.
The Object found must be the same tile and id as the original.
*******************************************************************************}
function FindRSObjectEx(Objs: TRSObjectArray): boolean;
var
i: integer;
begin
for i := 0 to High(Objs) do
begin
if(GetObjectAt(Objs[i].Tile, Objs[i].objType) = Objs[i])then
begin
Result := true;
Exit;
end
end;
Result := False;
end;

{*******************************************************************************
function FindRSObject(Obj : TRSObject): boolean;
By: Drags111
Description: Returns true if the object is found.
The Object found must be the same tile and id as the original.
*******************************************************************************}
function FindRSObject(Obj : TRSObject): boolean;
begin
Result := FindRSObjectEx([Obj]);
end;

{*******************************************************************************
function GetNearestObject(Objs: TRSObjectArray; MaxLength: Integer): TRSObject;
By: Drags111
Description: Returns True if any of the IDs from the IDs array are found. Returns
all occurances in Objs.
Objs: The RSObjects you are looking for.
IDs: The IDs of the objects you want to look for.
objType: The type of object it is.
-INTERACTABLE
-WALLOBJECT
-WALLDECOR
-FLOORDECOR
MaxLength: The maximum length from your position you want to look.
*******************************************************************************}
function GetNearestObject(Objs: TRSObjectArray; MaxLength: Integer): TRSObject;
//Yakman's spiral algorithm
var
Dir, tLength, f, X, Y, nL: Integer;
TP: TTile;
TileObject: TRSObject;
begin
TP := GetMyPos;
X := TP.X;
Y := TP.Y;
Dir := 0;
tLength := 1;
while (tLength < MaxLength) do
begin
for F := 0 to tLength - 1 do
begin
case Dir of
0: Dec(Y);
1: Inc(X);
2: Inc(Y);
3: Dec(X);
end;
TileObject := GetObjectAt(PointToTile(x, y), Objs[0].objType);
if RSObjectInArray(Objs, TileObject) then
begin
Result := TileObject;
Exit;
end else
end;
Inc(Dir);
dir := dir mod 4;
if Dir mod 2 = 0 then
Inc(tLength);
end;
end;

{*******************************************************************************
function GetObjectsIDEx(var Objs: TRSObjectArray; IDs: TIntegerArray; objType, MaxLength: Integer): Boolean;
By: Drags111, n3ss3s, Bobarkinator, Nava2
Description: Returns True if any of the IDs from the IDs array are found. Returns
all occurances in Objs.
Objs: Your TRSObjectArray to store the found objects in.
IDs: The IDs of the objects you want to look for.
objType: The type of object it is.
-INTERACTABLE
-WALLOBJECT
-WALLDECOR
-FLOORDECOR
MaxLength: The maximum length from your position you want to look.
*******************************************************************************}
function GetObjectsIDEx(var Objs: TRSObjectArray; IDs: TIntegerArray; objType, MaxLength: Integer): Boolean;
//Yakman's spiral algorithm
var
Dir, tLength, f, X, Y, nL: Integer;
TP: TTile;
TileObject: TRSObject;
begin
TP := GetMyPos;
X := TP.X;
Y := TP.Y;
Dir := 0;
tLength := 1;
while (tLength < MaxLength) do
begin
for F := 0 to tLength - 1 do
begin
case Dir of
0: Dec(Y);
1: Inc(X);
2: Inc(Y);
3: Dec(X);
end;
TileObject := GetObjectAt(PointToTile(x, y), objType);
if InIntArray(IDs, TileObject.ID) then
begin
Result := True;
SetArrayLength(Objs, Length(Objs) + 1);
Objs[High(Objs)] := TileObject;
end else
end;
Inc(Dir);
dir := dir mod 4;
if Dir mod 2 = 0 then
Inc(tLength);
end;
end;

{*******************************************************************************
function GetNearestObjectID(var obj: TRSObject; ID, objType, MaxLength: integer): boolean;
By: Drags111
Description: Returns true if the object id is found. Stores the found object in
the var "obj". Searches in a spiral from your position. Closest one
is returned;
*******************************************************************************}
function GetNearestObjectID(var obj: TRSObject; ID, objType, MaxLength: integer): boolean;
var
TempObjs: TRSObjectArray;
begin
Result := GetObjectsIDEx(TempObjs, [ID], objType, MaxLength);
if(Result)then
begin
obj := TempObjs[0];
Exit;
end;
obj := NullObject;
end;


program Test;
{.LoadLib Embedded_SMART}
{$define smart}
{$i srl/srl.scar}
{$i srl/srl/reflection/Reflection.simba}

var
CurrentRock: TRSObject;

function LoadPath(Which: integer) : TTileArray;
var
i: integer;
begin
case Which of
1:begin
SetLength(Result, 8);
Result := [
PointToTile(3292, 3377), PointToTile(3291, 3389), PointToTile(3290, 3402),
PointToTile(3288, 3414), PointToTile(3282, 3423), PointToTile(3271, 3428),
PointToTile(3260, 3427), PointToTile(3253, 3420)
];
end;
2:begin
SetLength(Result, 7);
Result := [
PointToTile(3261, 3428), PointToTile(3277, 3427), PointToTile(3285, 3417),
PointToTile(3289, 3403), PointToTile(3290, 3389), PointToTile(3291, 3376),
PointToTile(3286, 3368)
];
end;
end;
end;

function MineRocks: boolean;
var
i: integer;
P: TPoint;
IronRocks: TRSObjectArray;
begin
Result := false;
if not GetObjectsIDEx(IronRocks, [11956, 11954, 11955], INTERACTABLE, 20)then
Exit;
//Writeln('Loaded '+ToStr(Length(IronRocks))+' rocks.');
for i := 0 to High(IronRocks) do
begin
if not(TileOnMS(IronRocks[i].Tile, 20))then
continue;
P := TileToMSEx(IronRocks[i].Tile, 0.5, 0.5, 15+Random(6));
case Random(5) of
0: begin
Mouse(P.x, P.y, 4, 4, false);
Result := R_ChooseOption('Mine');
end;
1..4:begin
Mouse(P.x, P.y, 4, 4, true);
Result := true;
end;
end;
CurrentRock := IronRocks[i];
if Result then Exit;
end;
end;

procedure MiningLoop;
begin
while(InvCount <> 28)do
begin
if(MineRocks)then
begin
while(FindRSObject(CurrentRock))do
begin
case Random(100) of
0..49: SleepAndMoveMouse(500+Random(500));
50..99: wait(100+Random(400));
end;
end;
end;
end;
end;

function Banking: boolean;
var
t: integer;
begin
Result := R_OpenBankBooth('veb');
if not Result then Exit;
while(InvCount <> 0)do
begin
Mouse(395, 306, 5, 5, true);
MarkTime(t);
while((InvCount<> 0) and (TimeFromMark(t) < 3000)) do
wait(100+Random(100));
end;
CloseBank;
end;

procedure MainLoop;
begin
while(true)do
begin
SetRun(True);
MiningLoop;
SetRun(False);
if not WalkPath(LoadPath(1))then
begin
Writeln('Walking path 1 failed.');
Exit;
end;
Banking;
SetRun(True);
if not WalkPath(LoadPath(2))then
begin
Writeln('Walking path 2 failed.');
Exit;
end;
end;
end;

var
Me: TMe;

begin
Smart_Members := false;
Smart_Server := 118;
Smart_Signed := true;
Smart_SuperDetail := false;
SetupSRL;

Me := GetMe;
Writeln(Me.Tile);

MainLoop;
end.

Please note that variable names for some of these hooks WILL BE CHANGING. So don't think this is the permanent function, its a rough draft. Try it out though!

JPHamlett

2010-05-23 12:34:42

gratz

Method

2010-05-23 12:44:56

I have a few comments/concerns about this piece of code:

  • Why are you only returning one object per tile? A tile can have many objects and you should either return them all or have the user select which types they would like to have returned.
  • The check to make sure the IDs of objects are greater than zero is unnecessary. Doing a bitwise AND on the value with $FFFF will give you the correct ID.

Anyways, good job on getting it working again.

Drakan

2010-05-24 20:19:11

UPDATE:

Now, I did things in here that are kinda different then we used to do them. However, look around, read through the functions, and look at the test mining script that I made. It works very well this way and is pretty flawless. If you have questions on how I decided to do things, feel free to ask.

Remember, this is all on the SVN!