/lib/core/tiles.simba
http://github.com/Drags111/Reflection_Dev · Unknown · 622 lines · 481 code · 141 blank · 0 comment · 0 complexity · 468d429787a9957bc464d23b8515eda5 MD5 · raw file
- (*
- Tiles
- =====
-
- This file relates to Map and Screen locations and converting them to Tiles. The
- methods and formulas here relate to hooks into the Runescape Client's rendering
- system, and therefore a brief description about how those work will help a lot.
-
- The Runescape world is laid out on a large grid. A coordinate on this grid is
- called a Tile. The origin (0,0) is somewhere in the South Western corner of the
- world, and the coordinates increase in the North Easternly direction.
-
- A loading area is a smaller grid 104x104 tiles in size whose bounds can be
- variable. The origin of the loading area is stored in the client as the global
- tile position (BaseX, BaseY), therefore your local Tile position is your global
- Tile position minux the origin of the loading area.
-
- A tile is rendered as 512x512 pixels. Most positions in the renderer data are
- measured in pixels. This means the loading area is 13312x13312 pixels in size.
- to convert a local Tile into a pixel measurement, simply multiply the local Tile
- coordinates by 512.
-
- Each corner of a tile has a height stored in a 2D array in the current Plane
- object. To calculate the average height of a tile, simply average the height of
- its corners.
-
- The client provides a rotation matrix, offset, and scaling values to transform
- a "world" pixel coordinate into a "screen" coordinate. The formula for doing
- this is found in the TileToMSEx function. Since one often requires sub tile
- accuracy, offset values in the range of [0,1] are provided. (0.5,0.5) would be
- the center, and (0,0) would be the south-west corner of the tile.
-
- The minimap is simply a perfectly verticle view of the ground as if it were
- perfectly flat. Tiles here have a size of 4x4 pixels, and the map is rotated
- around your current position by an angle stored in MapAngle. The angle is in
- the range [0,16384], with 0 being North and increasing counter-clockwise. The
- math for converting a Tile into a "minimap" coordinate is provided in TileToMM.
-
- *)
-
- function R_GetPlaneIndex : Integer;
- begin
- Result := SmartGetFieldInt(0, hook_static_LoadedPlane);
- end;
-
- (*
- R_UpdateRenderInfo
- ~~~~~~~~~~~~~~~~~~
-
- .. code-block:: pascal
-
- procedure R_UpdateRenderInfo(var Render : TRender; var RenderData : TRenderData);
-
- Fills a pair of TRender and TRenderData structures with data.
-
- .. note::
-
- by Benland100
-
- *)
- procedure R_UpdateRenderInfo(var Render : TRender; var RenderData : TRenderData);
- var
- tk, vp, t: Integer;
- begin
- MarkTime(t);
- while ((RenderData.zX <= 0) and (RenderData.zY <= 0) and (TimeFromMark(t) < 10000)) do
- begin
- tk := SmartGetFieldObject(0, hook_static_Toolkit);
- vp := SmartGetFieldObject(tk, hook_sdtoolkit_Viewport);
- with RenderData do
- begin
- xOff := SmartGetFieldFloat(vp,hook_sdviewport_xOff);
- xX := SmartGetFieldFloat(vp,hook_sdviewport_xX);
- xY := SmartGetFieldFloat(vp,hook_sdviewport_xY);
- xZ := SmartGetFieldFloat(vp,hook_sdviewport_xZ);
- yOff := SmartGetFieldFloat(vp,hook_sdviewport_yOff);
- yX := SmartGetFieldFloat(vp,hook_sdviewport_yX);
- yY := SmartGetFieldFloat(vp,hook_sdviewport_yY);
- yZ := SmartGetFieldFloat(vp,hook_sdviewport_yZ);
- zOff := SmartGetFieldFloat(vp,hook_sdviewport_zoff);
- zX := SmartGetFieldFloat(vp,hook_sdviewport_zX);
- zY := SmartGetFieldFloat(vp,hook_sdviewport_zY);
- zZ := SmartGetFieldFloat(vp,hook_sdviewport_zZ);
- end;
- with Render do
- begin
- xScale := SmartGetFieldInt(tk, hook_sdtoolkit_xScale);
- yScale := SmartGetFieldInt(tk, hook_sdtoolkit_yScale);
- xMin := SmartGetFieldInt(tk, hook_sdtoolkit_xMin);
- xMax := SmartGetFieldInt(tk, hook_sdtoolkit_xMax);
- yMin := SmartGetFieldInt(tk, hook_sdtoolkit_yMin);
- yMax := SmartGetFieldInt(tk, hook_sdtoolkit_yMax);
- zMin := SmartGetFieldInt(tk, hook_sdtoolkit_zMin);
- zMax := SmartGetFieldInt(tk, hook_sdtoolkit_zMax);
- end;
- SmartFreeObject(tk);
- SmartFreeObject(vp);
- end;
- end;
-
- (*
- R_EmptyRenderInfo
- ~~~~~~~~~~~~~~~~~
-
- .. code-block:: pascal
-
- procedure R_EmptyRenderInfo(var Render : TRender; var RenderData : TRenderData);
-
- Empties a pair of TRender and TRenderData structures.
-
- .. note::
-
- by Drags111
-
- *)
- procedure R_EmptyRenderInfo(var Render : TRender; var RenderData : TRenderData);
- begin
- with RenderData do
- begin
- xOff := NULL_INT;
- xX := NULL_INT;
- xY := NULL_INT;
- xZ := NULL_INT;
- yOff := NULL_INT;
- yX := NULL_INT;
- yY := NULL_INT;
- yZ := NULL_INT;
- zOff := NULL_INT;
- zX := NULL_INT;
- zY := NULL_INT;
- zZ := NULL_INT;
- end;
- with Render do
- begin
- xScale := NULL_INT;
- yScale := NULL_INT;
- xMin := NULL_INT;
- xMax := NULL_INT;
- yMin := NULL_INT;
- yMax := NULL_INT;
- zMin := NULL_INT;
- zMax := NULL_INT;
- end;
- end;
-
- (*
- R_GetTileHeight
- ~~~~~~~~~~~~~~~
-
- .. code-block:: pascal
-
- function R_GetTileHeight(tile: TTile) : integer;
-
- Finds the average height of the global tile provided the tile is in the current
- loading area and on a loaded plane.
-
- .. note::
-
- by BenLand100
-
- *)
- function R_GetTileHeight(tile: TTile) : integer;
- var
- x, y, CurPlane, GroundSetting, PlaneInstance : integer;
- begin
- x := tile.x - SmartGetFieldInt(0, hook_static_BaseX);
- y := tile.y - SmartGetFieldInt(0, hook_static_BaseY);
- if ((x < 0) or (x > 104) or (y < 0) or (y > 104)) then
- begin
- result := 0;
- exit;
- end;
- CurPlane := SmartGetFieldInt(0, hook_static_LoadedPlane);
- GroundSetting := SmartGetFieldArray3DByte(0, hook_static_GroundSettingsArray, 1, X, Y);
- if ((CurPlane < 3) and ((GroundSetting and 2) <> 0)) then
- CurPlane:= CurPlane + 1;
- PlaneInstance := SmartGetFieldArrayObject(0, hook_static_PlaneArray, CurPlane);
- result:= (SmartGetFieldArray2DInt(PlaneInstance, hook_sdplane_TileHeights, x, y) +
- SmartGetFieldArray2DInt(PlaneInstance, hook_sdplane_TileHeights, x + 1, y) +
- SmartGetFieldArray2DInt(PlaneInstance, hook_sdplane_TileHeights, x, y + 1) +
- SmartGetFieldArray2DInt(PlaneInstance, hook_sdplane_TileHeights, x + 1, y + 1)) / 4;
- if(Result = -1)then
- writeln('****************TileHight hooks are incorrect.*****************');
- SmartFreeObject(PlaneInstance);
- end;
-
- (*
- R_World3DToScreen
- ~~~~~~~~~~~~~~~~~
-
- .. code-block:: pascal
-
- function R_World3DToScreen(xx, yy, zz: Extended): TPoint;
-
- Converts a RS 3D point to a coordinate on the screen.
-
- .. note::
-
- by Benland100
-
- *)
- function R_World3DToScreen(xx, yy, zz: Extended): TPoint;
- var
- rd : TRenderData;
- r : TRender;
- x, y, z: extended;
- tries: integer;
- label
- ProcStart;
- begin;
- ProcStart:
- R_EmptyRenderInfo(r, rd);
- x := 0;
- y := 0;
- z := 0;
- Inc(tries);
- result:= point(-1,-1);
- R_UpdateRenderInfo(r,rd);
- z:= rd.zOff + (rd.zX * xx + rd.zY * yy + rd.zZ * zz);
- if ((z < r.zMin) or (z > r.zMax)) then
- exit;
- x:= r.xScale * (rd.xOff + (rd.xX * xx + rd.xY * yy + rd.xZ * zz)) / z;
- y:= r.yScale * (rd.yOff + (rd.yX * xx + rd.yY * yy + rd.yZ * zz)) / z;
- if ((x >= r.xMin) and (x <= r.xMax) and (y >= r.yMin) and (y <= r.yMax)) then
- begin
- result.x:= Round((x - r.xMin)+4);
- result.y:= Round((y - r.yMin)+4);
- end else
- begin
- if (tries > 30)then Exit;
- goto ProcStart;
- end;
- end;
-
- (*
- R_TileToMSEx
- ~~~~~~~~~~~~
-
- .. code-block:: pascal
-
- function R_TileToMSEx(tile: TTile; offx, offy : extended; height : integer) : TPoint;
-
- Converts the global tile position, a position on that tile in the range
- [(0,0), (1,1)] with (0.5, 0.5) being center and a height above ground level to
- a screen location on the main screen, taking camera position and rotation into
- account.
-
- .. note::
-
- by Benland100
-
- *)
- function R_TileToMSEx(tile: TTile; offx, offy : extended; height : integer) : TPoint;
- var
- pixelX, pixelY, pixelZ: extended;
- begin
- pixelX:= (tile.x - SmartGetFieldInt(0, hook_static_BaseX) + offX) * 512.0;
- pixelY:= R_GetTileHeight(tile) - height;
- pixelZ:= (tile.y - SmartGetFieldInt(0, hook_static_BaseY) + offY) * 512.0;
- Result := R_World3DToScreen(pixelX, pixelY, pixelZ);
- if not PointInBox(Result, IntToBox(MSX1, MSY1, MSX2, MSY2))then
- begin
- Result.x := -1;
- Result.y := -1;
- end;
- end;
-
- (*
- R_TileToMS
- ~~~~~~~~~~
-
- .. code-block:: pascal
-
- function R_TileToMS(tile: TTile; height : integer): TPoint;
-
- Converts the center of a global tile position and a height above ground level
- to a screen location on the main screen, taking camera position and rotation
- into account.
-
- .. note::
-
- by BenLand100
-
- *)
- function R_TileToMS(TheTile: TTile; height : integer) : TPoint;
- begin
- result:= R_TileToMSEx(TheTile, 0.5, 0.5, height);
- end;
-
- (*
- R_TileOnMS
- ~~~~~~~~~~
-
- .. code-block:: pascal
-
- function R_TileOnMS(TheTile: TTile; Height : Integer) : Boolean;
-
- Results true if the Tile is on the MS.
-
- .. note::
-
- by Drags111
-
- *)
- function R_TileOnMS(TheTile: TTile; Height : Integer) : Boolean;
- begin
- Result := PointInBox(R_TileToMS(TheTile, Height), IntToBox(MSX1, MSY1, MSX2, MSY2));
- end;
-
- (*
- R_TileOnMSEx
- ~~~~~~~~~~~~
-
- .. code-block:: pascal
-
- function R_TileOnMSEx(T: TTile; offX, offY: extended; Height : Integer) : Boolean;
-
- Results true if the Tile is on the MS.
-
- .. note::
-
- by Drags111
-
- *)
- function R_TileOnMSEx(T: TTile; offX, offY: extended; Height : Integer) : Boolean;
- begin
- Result := PointInBox(R_TileToMSEx(T, offX, offY, Height),
- IntToBox(MSX1, MSY1, MSX2, MSY2));
- end;
-
- (*
- R_TileBoxOnMSEx
- ~~~~~~~~~~~~
-
- .. code-block:: pascal
-
- function R_TileBoxOnMSEx(Box: TBox; Height : Integer) : Boolean;
-
- Results true if the whole box of tiles with the given Height is on the MS.
-
- .. note::
-
- by mormonman
-
- *)
- function R_TileBoxOnMSEx(Box: TBox; Height : Integer) : Boolean;
- begin
- Result := R_TileOnMS(Point(Box.X1, Box.Y1), Height) and
- R_TileOnMS(Point(Box.X2, Box.Y2), Height);
- end;
-
- (*
- R_TileBoxOnMS
- ~~~~~~~~~~~~
-
- .. code-block:: pascal
-
- function R_TileBoxOnMS(Box: TBox) : Boolean;
-
- Results true if the whole box of tiles is on the MS.
-
- .. note::
-
- by mormonman
-
- *)
- function R_TileBoxOnMS(Box: TBox) : Boolean;
- begin
- Result := R_TileBoxOnMSEx(Box, 0);
- end;
-
- (*
- R_TileInBox
- ~~~~~~~~~~~
-
- .. code-block:: pascal
-
- function R_TileInBox(Bounds: TBox; T: TTile): boolean;
-
- Results true if the tile is in the box. TOP LEFT TO BOTTOM RIGHT.
-
- .. note::
-
- by Drags111
-
- *)
- function R_TileInBox(Bounds: TBox; T: TTile): boolean;
- var
- tx, ty, x1, y1, x2, y2: integer;
- begin
- x1 := Bounds.X1; y1 := Bounds.Y1;
- x2 := Bounds.X2; y2 := Bounds.Y2;
- tx := T.X; ty := T.Y;
- Result := ((tx >= x1) and (tx <= x2) and (ty <= y1) and (ty >= y2));
- end;
-
- (*
- R_SelfInBox
- ~~~~~~~~~~~
-
- .. code-block:: pascal
-
- function R_SelfInBox(Bounds: TBox): boolean;
-
- Results true if your char is in the box of tiles. TOP LEFT TO BOTTOM RIGHT.
-
- .. note::
-
- by Drags111
-
- *)
- function R_SelfInBox(Bounds: TBox): boolean;
- var
- tx, ty, x1, y1, x2, y2: integer;
- T: TTile;
- begin
- T := R_GetMyPos;
- x1 := Bounds.X1; y1 := Bounds.Y1;
- x2 := Bounds.X2; y2 := Bounds.Y2;
- tx := T.X; ty := T.Y;
- Result := ((tx >= x1) and (tx <= x2) and (ty <= y1) and (ty >= y2));
- end;
-
- (*
- R_GetMidTile
- ~~~~~~~~~~~~
-
- .. code-block:: pascal
-
- function R_GetMidTile(Tile1, Tile2: TTile): TTile;
-
- Returns the midway point of the 2 given tiles.
-
- .. note::
-
- by Drags111
-
- *)
- function R_GetMidTile(Tile1, Tile2: TTile): TTile;
- begin
- Result := Point((Tile1.x+Tile2.x)/2, (Tile1.y+Tile2.y)/2);
- end;
-
- (*
- R_GetCollisionMap
- ~~~~~~~~~~~~~~~~~
-
- .. code-block:: pascal
-
- function R_GetCollisionMap(var Blocks: array of TIntegerArray): Boolean;
-
- Returns a 2-dimensional array of the information stored in each tile in
- a loaded plane. Used to calculate if a tile is reachable or not.
-
- .. note::
-
- by Drags111
-
- *)
- function R_GetCollisionMap(var CollisionMap: array of TIntegerArray): Boolean;
- var
- X, Y: Integer;
- GroundDataArray, MyPlayer, Plane, GroundData, BlocksObj: Integer;
- begin
- GroundDataArray := SmartGetFieldObject(0, hook_static_GroundDataArray);
- MyPlayer := SmartGetFieldObject(0, hook_static_MyPlayer);
- Plane := SmartGetFieldByte(MyPlayer, hook_animable_Plane);
-
- if(SmartGetFieldArraySize(GroundDataArray, '', 1) < Plane)then
- begin
- Result := False;
- SmartFreeObject(GroundDataArray);
- SmartFreeObject(MyPlayer);
- R_Debug('GroundDataArray Length is less than Plane', 'R_GetCollisionMap');
- Exit;
- end;
-
- GroundData := SmartGetFieldArrayObject(GroundDataArray, '', Plane);
- BlocksObj := SmartGetFieldObject(GroundData, hook_grounddata_CollisionFlags);
-
- if(GroundData = 0) or (BlocksObj = 0)then
- begin
- Result := False;
- SmartFreeObject(GroundDataArray);
- SmartFreeObject(MyPlayer);
- SmartFreeObject(GroundData);
- SmartFreeObject(BlocksObj);
- R_Debug('GroundData or BlocksObj is null', 'R_GetCollisionMap');
- Exit;
- end;
-
- Result := True;
-
- SetLength(CollisionMap, 104);
- for X := 0 to 103 do
- begin
- SetLength(CollisionMap[X], 104);
- for Y := 0 to 103 do
- begin
- CollisionMap[X][Y] := SmartGetFieldArray2DInt(BlocksObj, '', X, Y);
- end;
- end;
- SmartFreeObject(GroundDataArray);
- SmartFreeObject(MyPlayer);
- SmartFreeObject(GroundData);
- SmartFreeObject(BlocksObj);
- end;
-
- (*
- R_PathLengthBetweenEx
- ~~~~~~~~~~~~~~~~~~~~~
-
- .. code-block:: pascal
-
- function R_PathLengthBetweenEx(Start, Dest: TTile; IsObject: Boolean; Blocks: array of TIntegerArray): Integer;
-
- Returns the length between 2 tiles via path distance. (Going around objects and
- such).
-
- .. note::
-
- by Drags111
-
- *)
- function R_PathLengthBetweenEx(Start, Dest: TTile; IsObject: Boolean; CollisionMap: array of TIntegerArray): Integer;
- var
- BaseX, BaseY: Integer;
- x1, y1, x2, y2: Integer;
- begin
- try
- BaseX := SmartGetFieldInt(0, hook_static_BaseX);
- BaseY := SmartGetFieldInt(0, hook_static_BaseY);
- x1 := Start.X - BaseX;
- y1 := Start.Y - BaseY;
- x2 := Dest.X - BaseX;
- y2 := Dest.Y - BaseY;
-
- Result := DijkstraDist(x1, y1, x2, y2, isObject, CollisionMap); // From the plugin
- except
- Result := -1;
- end;
- end;
-
- (*
- R_PathLengthBetween
- ~~~~~~~~~~~~~~~~~~~~~
-
- .. code-block:: pascal
-
- function R_PathLengthBetween(Start, Dest: TTile; IsObject: Boolean): Integer;
-
- Returns the length between 2 tiles via path distance. (Going around objects and
- such).
-
- .. note::
-
- by Drags111
-
- *)
- function R_PathLengthBetween(Start, Dest: TTile; IsObject: Boolean): Integer;
- var
- CollisionMap: array of TIntegerArray;
- begin
- try
- if not R_GetCollisionMap(CollisionMap)then
- begin
- R_Debug('Unable to retrieve collision map.', 'R_PathLengthBetween');
- Exit;
- end;
- Result := R_PathLengthBetweenEx(Start, Dest, IsObject, CollisionMap);
- except
- Result := -1;
- end;
- end;
-
- (*
- R_PathLengthBetween
- ~~~~~~~~~~~~~~~~~~~~~
-
- .. code-block:: pascal
-
- function R_CanReachEx(Tile: TTile; IsObject: Boolean; CollisionMap: array of TIntegerArray): Boolean;
-
- Returns true if a tile is reachable from your current position.
-
- .. note::
-
- by Drags111
-
- *)
- function R_CanReachEx(Tile: TTile; IsObject: Boolean; CollisionMap: array of TIntegerArray): Boolean;
- begin
- try
- Result := R_PathLengthBetweenEx(R_GetMyPos, Tile, IsObject, CollisionMap) <> -1;
- except
- Result := False;
- end;
- end;
-
- (*
- R_PathLengthBetween
- ~~~~~~~~~~~~~~~~~~~~~
-
- .. code-block:: pascal
-
- function R_CanReach(Tile: TTile; IsObject: Boolean): Boolean;
-
- Returns true if a tile is reachable from your current position.
-
- .. note::
-
- by Drags111
-
- *)
- function R_CanReach(Tile: TTile; IsObject: Boolean): Boolean;
- begin
- try
- Result := R_PathLengthBetween(R_GetMyPos, Tile, IsObject) <> -1;
- except
- Result := False;
- end;
- end;