пишешь дллку, примерно такую (за точность не ручаюсь):
Code: library Project2;
uses SysUtils, Classes, Types, Math;
const TILE_Z_DONT_CARE = 32767; TILE_Z_EQUAL_OR_ABOVE = 32766; TILE_Z_BELOW = 32765;
type StaIdxRecord = packed record Start : DWORD; //the Start position (0xFFFFFFFF if no static objects exist for this block) Length : DWORD; //the Length of the data segment Unknown: DWORD; end;
TileInfoStruct = record Graphic : WORD; X : DWORD; Y : DWORD; Z : Smallint; end;
StaticRecord = packed record ID : WORD; //Color/Object ID (add 16384 to offset it for RADARCOL.MUL) X : Byte;// X Offset in block (0..7) Y : Byte;// Y Offset in block (0..7) Z : Smallint ;// Altitude (-128..127 units above/below sea level, like MAP0) Unknown : WORD; end; TileSearchStruct = ^TTileSearchStruct; TTileSearchStruct = record Tile : TileInfoStruct; Distance : Byte; Graphic : WORD; X : DWORD; Y : DWORD; Z : integer; handle : DWORD; next,prev : TileSearchStruct; end;
TStaticSearcher = class (TObject) Path : string; StaticFile : File of byte; Start : TileSearchStruct; Finish : TileSearchStruct; StaIdx : packed array [0..65535] of StaIdxRecord; function AddTileSearch(Distance : Byte; Graphic : WORD; X : DWORD; Y : DWORD; Z : integer) : DWORD; procedure DeleteTileSearch(deltile : TileSearchStruct); destructor Destroy; override; end;
var StaticSearcher : TStaticSearcher;
function GetTileX(hnd : DWORD): DWORD; var ct : TileSearchStruct; begin with staticSearcher do begin result := 4294967295; ct := Start; while ct <> nil do begin if ct = TileSearchStruct(hnd) then begin result := ct.Tile.X; end; ct := ct.next; end; end; end;
function GetTileY(hnd : DWORD): DWORD; var ct : TileSearchStruct; begin result := 4294967295; ct := staticsearcher.Start; while ct <> nil do begin if ct = TileSearchStruct(hnd) then begin result := ct.Tile.Y; end; ct := ct.next; end; end;
function GetTileZ(hnd : DWORD): Smallint; var ct : TileSearchStruct; begin result := -32768; ct := StaticSearcher.Start; while ct <> nil do begin if ct = TileSearchStruct(hnd) then begin result := ct.Tile.Z; end; ct := ct.next; end; end;
function GetTileGraphic(hnd : DWORD): WORD; var ct : TileSearchStruct; begin result := 0; ct := StaticSearcher.Start; while ct <> nil do begin if ct = TileSearchStruct(hnd) then begin result := ct.Tile.Graphic; end; ct := ct.next; end; end;
function FindTile(Distance : Byte; Graphic : WORD; X : DWORD; Y : DWORD; Z : integer) : DWORD; var BlockNumber,BlockX,BlockY : DWORD; BlockDistance : byte; XinBlock,YinBlock : byte; h,i,j,k : integer; Static : StaticRecord; ct : TileSearchStruct; begin with StaticSearcher do begin result := 0; ct := TileSearchStruct(AddTileSearch(Distance,Graphic,X,Y,Z)); BlockX := trunc(CT.X/8); BlockY := trunc(ct.Y/8); XinBlock := (ct.X mod 8); YinBlock := (ct.Y mod 8); BlockDistance := max(trunc(abs(XinBlock+ct.Distance)/8),trunc(abs(YinBlock+ct.Distance)/8)); BlockNumber := (BlockX * 512) + BlockY; for i := BlockX-BlockDistance to BlockX+BlockDistance do begin for j := BlockY-BlockDistance to BlockY+BlockDistance do begin if StaticSearcher.StaIdx[((i * 512) + j)].Start <> $FFFFFFFF then begin Seek(StaticFile,StaIdx[((i * 512) + j)].Start); for k := 0 to StaIdx[((i * 512) + j)].Length div 7 - 1 do begin BlockRead(StaticFile,Static,7); ct.Tile.Graphic := Static.ID; ct.Tile.X := i*8 + Static.X; ct.Tile.Y := j*8 + Static.Y; ct.Tile.Z := Static.Z; If ( (ct.Z = TILE_Z_DONT_CARE) or ((ct.Z = TILE_Z_EQUAL_OR_ABOVE) and (ct.Tile.Z >= ct.Z)) or ((ct.Z = TILE_Z_BELOW) and (ct.Tile.Z < ct.Z)) ) and (ct.X > ct.Tile.X-ct.Distance) and (ct.X < ct.Tile.X+ct.Distance) and (ct.Y > ct.Tile.Y-ct.Distance) and (ct.Y < ct.Tile.Y+ct.Distance) and ((ct.Graphic = ct.Tile.Graphic) or (ct.Graphic = 0)) then begin result := DWORD(ct); exit; end; end; end; end; end; end; result := 0; end;
function FindTileNext(hnd : DWORD) : integer; var BlockNumber,BlockX,BlockY : DWORD; BlockDistance : byte; XinBlock,YinBlock : byte; h,i,j,k : integer; Static : StaticRecord; foundold : boolean; ct : TileSearchStruct; begin with StaticSearcher do begin ct := Start; while ct <> nil do begin if ct = TileSearchStruct(hnd) then begin BlockX := trunc(ct.X/8); BlockY := trunc(ct.Y/8); XinBlock := (ct.X mod 8); YinBlock := (ct.Y mod 8); BlockDistance := max(trunc(abs(XinBlock+ct.Distance)/8),trunc(abs(YinBlock+ct.Distance)/8)); BlockNumber := (BlockX * 512) + BlockY; foundold := false; for i := BlockX-BlockDistance to BlockX+BlockDistance do begin for j := BlockY-BlockDistance to BlockY+BlockDistance do begin if StaIdx[((i * 512) + j)].Start <> $FFFFFFFF then begin Seek(StaticFile,StaIdx[((i * 512) + j)].Start); for k := 0 to StaIdx[((i * 512) + j)].Length div 7 - 1 do begin BlockRead(StaticFile,Static,7); if ((Static.ID <> ct.Tile.Graphic) or (ct.Tile.X <> i*8 + Static.X) or (ct.Tile.Y <> j*8 + Static.Y) or (ct.Tile.Z <> Static.Z)) and foundold then begin ct.Tile.Graphic := Static.ID; ct.Tile.X := i*8 + Static.X; ct.Tile.Y := j*8 + Static.Y; ct.Tile.Z := Static.Z; If ( (ct.Z = TILE_Z_DONT_CARE) or ((ct.Z = TILE_Z_EQUAL_OR_ABOVE) and (ct.Tile.Z >= ct.Z)) or ((ct.Z = TILE_Z_BELOW) and (ct.Tile.Z < ct.Z)) ) and (ct.X > ct.Tile.X-ct.Distance) and (ct.X < ct.Tile.X+ct.Distance) and (ct.Y > ct.Tile.Y-ct.Distance) and (ct.Y < ct.Tile.Y+ct.Distance) and ((ct.Graphic = ct.Tile.Graphic) or (ct.Graphic = 0)) then begin result := 1; exit; end; end; if (Static.ID = ct.Tile.Graphic) and (ct.Tile.X = i*8 + Static.X) and (ct.Tile.Y = j*8 + Static.Y) and (ct.Tile.Z = Static.Z) and not foundold then foundold := true; end; end; end; end; DeleteTileSearch(ct); end; ct := ct.next; end; end; result := 0; end;
procedure LoadSearch(uopath : pchar); var f : file of byte; i : integer; begin FileMode := 0; if StaticSearcher <> nil then StaticSearcher.Free; StaticSearcher := TStaticSearcher.Create; StaticSearcher.path := uopath; if FileExists(StaticSearcher.path + 'staidx0.mul') then AssignFile(f,StaticSearcher.path + 'staidx0.mul') else begin exit; end; reset(f); BlockRead(f,StaticSearcher.StaIdx,65536*12); CloseFile(f); if FileExists(StaticSearcher.path + 'statics0.mul') then begin Assignfile(StaticSearcher.StaticFile,StaticSearcher.path + 'statics0.mul'); Reset(StaticSearcher.StaticFile); end; end;
procedure UnloadSearch(); begin if StaticSearcher <> nil then StaticSearcher.Free; end;
function TStaticSearcher.AddTileSearch(Distance : Byte; Graphic : WORD; X : DWORD; Y : DWORD; Z : integer) : DWORD; var newtile : TileSearchStruct; begin newtile := new(TileSearchStruct); newtile.Distance := Distance; newtile.Graphic := Graphic; newtile.X := X; newtile.Y := Y; newtile.Z := Z; if Start <> nil then newtile.prev := Finish else begin newtile.prev := nil; Start := newtile; end; if Finish <> nil then Finish.next := newtile; Finish := newtile; newtile.next := nil; result := integer(pointer(newtile)); end;
procedure TStaticSearcher.DeleteTileSearch(deltile : TileSearchStruct); begin if deltile <> nil then begin if deltile.prev <> nil then deltile.prev.next := deltile.next; if deltile.next <> nil then deltile.next.prev := deltile.prev; if deltile = Start then Start := deltile.next; if deltile = Finish then Finish := deltile.prev; Dispose(deltile); end; end;
destructor TStaticSearcher.Destroy; var del,ct : TileSearchStruct; begin CloseFile(StaticSearcher.StaticFile); ct := Start; while ct <> nil do begin del := ct; ct := ct.next; Dispose(del); end; StaticSearcher := nil; inherited Destroy; end;
exports FindTile, FindTileNext, GetTileX, GetTileY, GetTileZ, GetTileGraphic, LoadSearch, UnloadSearch;
{$R *.res}
begin
end.
Дописываешь к ней сопли (инициализация, деинициализация и прочие системные радости), отсылаешь Йоко и просишь подклбчить к инжекшну.
P.S. Ищет только статики (т.е, как правило, деревья), для тайлов земли нужно другой mul читать.
|