www.pudn.com > Client599.rar > MapUnit.pas


unit MapUnit; 
 
interface 
 
uses 
   Windows, Classes, SysUtils, Grobal2, HUtil32, DXDraws, CliUtil; 
 
const 
   MAPDIR = 'Map\'; 
   MAXX = 40; 
   MAXY = 40; 
 
type 
// ------------------------------------------------------------------------------- 
// Map 
// ------------------------------------------------------------------------------- 
 
  TMapPrjInfo = record 
     Ident: string[16]; 
     ColCount: integer; 
     RowCount: integer; 
  end; 
 
{  TMapHeader = record 
     Width  : word; 
     Height : word; 
     Title: string[16]; 
     UpdateDate: TDateTime; 
     Reserved  : array[0..19] of char; 
  end;} 
 
  TMapHeader = packed record 
     Width  : word; 
     Height : word; 
     Title: string[20]; 
     UpdateDate: TDateTime; 
     Reserved  : array[0..18] of char; 
  end; 
 
  TMapHeader_AntiHack = packed record //#### 
     Title: string[30]; 
     Width  : word; 
     CheckKey : word; //üũ°ª=43576 
     Height : word; 
     UpdateDate: TDateTime; 
     Reserved  : array[0..18] of char; 
  end; 
 
  TMapInfo = record 
      BkImg: word; 
      MidImg: word; 
      FrImg: word; 
      DoorIndex: byte;  //$80 (¹®Â¦), ¹®ÀÇ ½Äº° À妽º 
      DoorOffset: byte;  //´ÝÈù ¹®ÀÇ ±×¸²ÀÇ »ó´ë À§Ä¡, $80 (¿­¸²/´ÝÈû(±âº»)) 
      AniFrame: byte;      //$80(Draw Alpha) +  ÇÁ·¡ÀÓ ¼ö 
      AniTick: byte; 
      Area: byte;        //Áö¿ª Á¤º¸ 
      light: byte;       //0..1..4 ±¤¿ø È¿°ú 
  end; 
  PTMapInfo = ^TMapInfo; 
 
  TMapInfoArr = array[0..MaxListSize] of TMapInfo; 
  PTMapInfoArr = ^TMapInfoArr; 
 
  TMap = class 
  private 
     function  loadmapinfo (mapfile: string; var width, height: integer): Boolean; 
     procedure updatemapseg (cx, cy: integer); //, maxsegx, maxsegy: integer); 
     procedure updatemap (cx, cy: integer); 
  public 
     MapBase: string; 
     MArr: array[0..MAXX*3, 0..MAXY*3] of TMapInfo; 
     ClientRect: TRect; 
     OldClientRect: TRect; 
     BlockLeft, BlockTop: integer; //ŸÀÏ ÁÂÇ¥·Î ¿ÞÂÊ, ²À´ë±â ÁÂÇ¥ 
     oldleft, oldtop: integer; 
     oldmap: string; 
     CurUnitX, CurUnitY: integer; 
     CurrentMap: string; 
     Segmented: Boolean; 
     SegXCount, SegYCount: integer; 
     constructor Create; 
     destructor Destroy; 
     procedure UpdateMapSquare (cx, cy: integer); 
     procedure UpdateMapPos (mx, my: integer); 
     procedure ReadyReload; 
     procedure LoadMap (mapname: string; mx, my: integer); 
     procedure MarkCanWalk (mx, my: integer; bowalk: Boolean); 
     function  CanMove (mx, my: integer): Boolean; 
     function  CanFly  (mx, my: integer): Boolean; 
     function  GetDoor (mx, my: integer): Integer; 
     function  IsDoorOpen (mx, my: integer): Boolean; 
     function  OpenDoor (mx, my: integer): Boolean; 
     function  CloseDoor (mx, my: integer): Boolean; 
  end; 
 
  procedure DrawMiniMap; 
 
implementation 
 
uses 
   ClMain; 
 
 
constructor TMap.Create; 
begin 
   inherited Create; 
   //GetMem (MInfoArr, sizeof(TMapInfo) * LOGICALMAPUNIT * 3 * LOGICALMAPUNIT * 3); 
   ClientRect := Rect (0,0,0,0); 
   MapBase := '.\Map\'; 
   CurrentMap := ''; 
   Segmented := FALSE; 
   SegXCount := 0; 
   SegYCount := 0; 
   CurUnitX := -1; 
   CurUnitY := -1; 
   BlockLeft := -1; 
   BlockTop := -1; 
   oldmap := ''; 
end; 
 
destructor TMap.Destroy; 
begin 
   inherited Destroy; 
end; 
 
function  TMap.loadmapinfo (mapfile: string; var width, height: integer): Boolean; 
var 
   flname: string; 
   fhandle: integer; 
   header: TMapHeader; 
begin 
   Result := FALSE; 
   flname := MapBase + mapfile; 
   if FileExists (flname) then begin 
      fhandle := FileOpen (flname, fmOpenRead or fmShareDenyNone); 
      if fhandle > 0 then begin 
         FileRead (fhandle, header, sizeof(TMapHeader)); 
         width := header.Width; 
         height := header.Height; 
      end; 
      FileClose (fhandle); 
   end; 
end; 
 
//segmented map ÀÎ °æ¿ì 
procedure TMap.updatemapseg (cx, cy: integer); //, maxsegx, maxsegy: integer); 
begin 
 
end; 
 
{procedure TMap.updatemap (cx, cy: integer); 
var 
   fhandle, i, k, aline, lx, rx, ty, by: integer; 
   header: TMapHeader; 
   flname: string; 
begin 
   FillChar (MArr, sizeof(MArr), 0); 
   flname := MapBase + CurrentMap + '.map'; 
   if FileExists (flname) then begin 
      fhandle := FileOpen (flname, fmOpenRead or fmShareDenyNone); 
      if fhandle > 0 then begin 
         FileRead (fhandle, header, sizeof(TMapHeader)); 
         lx := (cx - 1) * LOGICALMAPUNIT; 
         rx := (cx + 2) * LOGICALMAPUNIT;    //rx 
         ty := (cy - 1) * LOGICALMAPUNIT; 
         by := (cy + 2) * LOGICALMAPUNIT; 
         if lx < 0 then lx := 0; 
         if ty < 0 then ty := 0; 
         if by >= header.Height then by := header.Height; 
         aline := sizeof(TMapInfo) * header.Height; 
         for i:=lx to rx-1 do begin 
            if (i >= 0) and (i < header.Width) then begin 
               FileSeek (fhandle, sizeof(TMapHeader) + (aline * i) + (sizeof(TMapInfo) * ty), 0); 
               FileRead (fhandle, MArr[i-lx, 0], sizeof(TMapInfo) * (by-ty)); 
            end; 
         end; 
         FileClose (fhandle); 
      end; 
   end; 
end;} 
 
//single mapÀÎ °æ¿ì 
procedure TMap.updatemap (cx, cy: integer); 
var 
   fhandle, i, j, k, aline, lx, rx, ty, by: integer; 
   header: TMapHeader; 
   header2: TMapHeader_AntiHack; 
   flname, Tempstr: string; 
begin 
   FillChar (MArr, sizeof(MArr), 0); 
   flname := MapBase + CurrentMap + '.map'; 
   Tempstr := UpperCase(CurrentMap); 
   if FileExists (flname) then begin 
      if (Tempstr = 'LABY01') or (Tempstr = 'LABY02') or (Tempstr = 'LABY03') or (Tempstr = 'LABY04') or 
         (Tempstr = 'SNAKE') then begin 
         fhandle := FileOpen (flname, fmOpenRead or fmShareDenyNone); 
         if fhandle > 0 then begin 
            FileRead (fhandle, header2, sizeof(TMapHeader_AntiHack)); 
            header2.Width := header2.Width xor header2.CheckKey; 
            header2.Height := header2.Height xor header2.CheckKey; 
 
            lx := (cx - 1) * LOGICALMAPUNIT; 
            rx := (cx + 2) * LOGICALMAPUNIT;    //rx 
            ty := (cy - 1) * LOGICALMAPUNIT; 
            by := (cy + 2) * LOGICALMAPUNIT; 
            if lx < 0 then lx := 0; 
            if ty < 0 then ty := 0; 
            if by >= header2.Height then by := header2.Height; 
            aline := sizeof(TMapInfo) * header2.Height; 
            for i:=lx to rx-1 do begin 
               for j:=ty to by do begin 
//                  if (i >= 0) and (i < header.Width) then begin 
            FileSeek (fhandle, sizeof(TMapHeader_AntiHack) + (aline * i) + (sizeof(TMapInfo) * j), 0); 
                     FileRead (fhandle, MArr[i-lx, j-ty], sizeof(TMapInfo)); 
                     MArr[i-lx, j-ty].BkImg := MArr[i-lx, j-ty].BkImg xor header2.CheckKey; 
                     MArr[i-lx, j-ty].MidImg := MArr[i-lx, j-ty].MidImg xor header2.CheckKey; 
                     MArr[i-lx, j-ty].FrImg := MArr[i-lx, j-ty].FrImg xor header2.CheckKey; 
//                  end; 
               end; 
            end; 
            FileClose (fhandle); 
         end; 
      end 
      else begin 
         fhandle := FileOpen (flname, fmOpenRead or fmShareDenyNone); 
         if fhandle > 0 then begin 
            FileRead (fhandle, header, sizeof(TMapHeader)); 
            lx := (cx - 1) * LOGICALMAPUNIT; 
            rx := (cx + 2) * LOGICALMAPUNIT;    //rx 
            ty := (cy - 1) * LOGICALMAPUNIT; 
            by := (cy + 2) * LOGICALMAPUNIT; 
            if lx < 0 then lx := 0; 
            if ty < 0 then ty := 0; 
            if by >= header.Height then by := header.Height; 
            aline := sizeof(TMapInfo) * header.Height; 
            for i:=lx to rx-1 do begin 
               if (i >= 0) and (i < header.Width) then begin 
                  FileSeek (fhandle, sizeof(TMapHeader) + (aline * i) + (sizeof(TMapInfo) * ty), 0); 
                  FileRead (fhandle, MArr[i-lx, 0], sizeof(TMapInfo) * (by-ty)); 
               end; 
            end; 
            FileClose (fhandle); 
         end; 
      end; 
   end; 
end; 
 
procedure TMap.ReadyReload; 
begin 
   CurUnitX := -1; 
   CurUnitY := -1; 
end; 
 
//cx, cy: Áß¾Ó, Counted by unit.. 
procedure TMap.UpdateMapSquare (cx, cy: integer); 
begin 
   if (cx <> CurUnitX) or (cy <> CurUnitY) then begin 
      if Segmented then 
         updatemapseg (cx, cy) 
      else 
         updatemap (cx, cy); 
      CurUnitX := cx; 
      CurUnitY := cy; 
   end; 
end; 
 
//ÁÖij¸¯ÀÌ À̵¿½Ã ºó¹øÀÌ È£Ãâ.. 
procedure TMap.UpdateMapPos (mx, my: integer); 
var 
   cx, cy: integer; 
   procedure Unmark (xx, yy: integer); 
   var 
      ax, ay: integer; 
   begin 
      if (cx = xx div LOGICALMAPUNIT) and (cy = yy div LOGICALMAPUNIT) then begin 
         ax := xx - BlockLeft; 
         ay := yy - BlockTop; 
         MArr[ax,ay].FrImg := MArr[ax,ay].FrImg and $7FFF; 
         MArr[ax,ay].BkImg := MArr[ax,ay].BkImg and $7FFF; 
      end; 
   end; 
begin 
   cx := mx div LOGICALMAPUNIT; 
   cy := my div LOGICALMAPUNIT; 
   BlockLeft := _MAX (0, (cx - 1) * LOGICALMAPUNIT); 
   BlockTop  := _MAX (0, (cy - 1) * LOGICALMAPUNIT); 
 
   UpdateMapSquare (cx, cy); 
 
   if (oldleft <> BlockLeft) or (oldtop <> BlockTop) or (oldmap <> CurrentMap) then begin 
      //3¹ø¸Ê ¼ºº®ÀÚ¸® ¹ö±× º¸Á¤ (2001-7-3) 
      if CurrentMap = '3' then begin 
         Unmark (624, 278); 
         Unmark (627, 278); 
         Unmark (634, 271); 
 
         Unmark (564, 287); 
         Unmark (564, 286); 
         Unmark (661, 277); 
         Unmark (578, 296); 
      end; 
   end; 
   oldleft := BlockLeft; 
   oldtop := BlockTop; 
end; 
 
//¸Êº¯°æ½Ã óÀ½ Çѹø È£Ãâ.. 
procedure TMap.LoadMap (mapname: string; mx, my: integer); 
begin 
   CurUnitX := -1; 
   CurUnitY := -1; 
   CurrentMap := mapname; 
   Segmented := FALSE; //Segmented µÇ¾î ÀÖ´ÂÁö °Ë»çÇÑ´Ù. 
   UpdateMapPos (mx, my); 
   oldmap := CurrentMap; 
end; 
 
procedure TMap.MarkCanWalk (mx, my: integer; bowalk: Boolean); 
var 
   cx, cy: integer; 
begin 
   cx := mx - BlockLeft; 
   cy := my - BlockTop; 
   if (cx < 0) or (cy < 0) then exit; 
   if bowalk then //°ÉÀ» ¼ö ÀÖÀ½ 
      Map.MArr[cx, cy].FrImg := Map.MArr[cx, cy].FrImg and $7FFF 
   else //¸·ÇûÀ½ 
      Map.MArr[cx, cy].FrImg := Map.MArr[cx, cy].FrImg or $8000;  //¸ø¿òÁ÷ÀÌ°Ô ÇÑ´Ù. 
end; 
 
function  TMap.CanMove (mx, my: integer): Boolean; 
var 
   cx, cy: integer; 
begin 
   cx := mx - BlockLeft; 
   cy := my - BlockTop; 
   if (cx < 0) or (cy < 0) then exit; 
   Result := ((Map.MArr[cx, cy].BkImg and $8000) + (Map.MArr[cx, cy].FrImg and $8000)) = 0; 
   if Result then begin //¹®°Ë»ç 
      if Map.MArr[cx, cy].DoorIndex and $80 > 0 then begin  //¹®Â¦ÀÌ ÀÖÀ½ 
         if (Map.MArr[cx, cy].DoorOffset and  $80) = 0 then 
            Result := FALSE; //¹®ÀÌ ¾È ¿­·ÈÀ½. 
      end; 
   end; 
end; 
 
function  TMap.CanFly  (mx, my: integer): Boolean; 
var 
   cx, cy: integer; 
begin 
   cx := mx - BlockLeft; 
   cy := my - BlockTop; 
   if (cx < 0) or (cy < 0) then exit; 
   Result := (Map.MArr[cx, cy].FrImg and $8000) = 0; 
   if Result then begin //¹®°Ë»ç 
      if Map.MArr[cx, cy].DoorIndex and $80 > 0 then begin  //¹®Â¦ÀÌ ÀÖÀ½ 
         if (Map.MArr[cx, cy].DoorOffset and  $80) = 0 then 
            Result := FALSE; //¹®ÀÌ ¾È ¿­·ÈÀ½. 
      end; 
   end; 
end; 
 
function  TMap.GetDoor (mx, my: integer): Integer; 
var 
   cx, cy: integer; 
begin 
   Result := 0; 
   cx := mx - BlockLeft; 
   cy := my - BlockTop; 
   if Map.MArr[cx, cy].DoorIndex and $80 > 0 then begin 
      Result := Map.MArr[cx, cy].DoorIndex and $7F; 
   end; 
end; 
 
function  TMap.IsDoorOpen (mx, my: integer): Boolean; 
var 
   cx, cy: integer; 
begin 
   Result := FALSE; 
   cx := mx - BlockLeft; 
   cy := my - BlockTop; 
   if Map.MArr[cx, cy].DoorIndex and $80 > 0 then begin 
      Result := (Map.MArr[cx, cy].DoorOffset and $80 <> 0); 
   end; 
end; 
 
function  TMap.OpenDoor (mx, my: integer): Boolean; 
var 
   i, j, cx, cy, idx: integer; 
begin 
   Result := FALSE; 
   cx := mx - BlockLeft; 
   cy := my - BlockTop; 
   if (cx < 0) or (cy < 0) then exit; 
   if Map.MArr[cx, cy].DoorIndex and $80 > 0 then begin 
      idx := Map.MArr[cx, cy].DoorIndex and $7F; 
      for i:=cx-10 to cx+10 do 
         for j:=cy-10 to cy+10 do begin 
            if (i > 0) and (j > 0) then 
               if (Map.MArr[i, j].DoorIndex and $7F) = idx then 
                  Map.MArr[i, j].DoorOffset := Map.MArr[i, j].DoorOffset or $80; 
         end; 
   end; 
end; 
 
function  TMap.CloseDoor (mx, my: integer): Boolean; 
var 
   i, j, cx, cy, idx: integer; 
begin 
   Result := FALSE; 
   cx := mx - BlockLeft; 
   cy := my - BlockTop; 
   if (cx < 0) or (cy < 0) then exit; 
   if Map.MArr[cx, cy].DoorIndex and $80 > 0 then begin 
      idx := Map.MArr[cx, cy].DoorIndex and $7F; 
      for i:=cx-8 to cx+10 do 
         for j:=cy-8 to cy+10 do begin 
            if (Map.MArr[i, j].DoorIndex and $7F) = idx then 
               Map.MArr[i, j].DoorOffset := Map.MArr[i, j].DoorOffset and $7F; 
         end; 
   end; 
end; 
 
 
const 
   SCALE = 4; 
 
procedure DrawMiniMap; 
var 
   sx, sy, ex, ey, i, j, imgnum, wunit, ani, ny, oheight, MX, MY: integer; 
   d: TDirectDrawSurface; 
begin 
   MiniMapSurface.Erase(0); 
   MX := UNITX div SCALE; 
   MY := UNITY div SCALE; 
   sx := _MAX(0,      (Myself.XX - Map.BlockLeft) div 2 * 2 - 22); 
   ex := _MIN(MAXX*3, (Myself.XX - Map.BlockLeft) div 2 * 2 + 22); 
   sy := _MAX(0,      (Myself.YY - Map.BlockTop) div 2 * 2 - 22); 
   ey := _MIN(MAXY*3, (Myself.YY - Map.BlockTop) div 2 * 2 + 22); 
 
   for i:=0 to ex-sx do begin 
      for j:=0 to ey-sy do begin 
         if (i >= 0) and (j < MAXY*3) and ((i+sx) mod 2 = 0) and ((j+sy) mod 2 = 0) then begin 
            imgnum := (Map.MArr[sx+i, sy+j].BkImg and $7FFF); 
            if imgnum > 0 then begin 
               imgnum := imgnum - 1; 
               d := FrmMain.WTiles.Images[imgnum]; 
               if d <> nil then 
                  MiniMapSurface.StretchDraw ( 
                                 Rect (i*MX, j*MY, i*MX + d.Width div SCALE, j*MY + d.Height div SCALE), 
                                 d.ClientRect, 
                                 d, 
                                 FALSE); 
            end; 
         end; 
      end; 
   end; 
   for i:=0 to ex-sx-1 do begin 
      for j:=0 to ey-sy-1 do begin 
         imgnum := Map.MArr[sx+i, sy+j].MidImg; 
         if imgnum > 0 then begin 
            imgnum := imgnum - 1; 
            d := FrmMain.WSmTiles.Images[imgnum]; 
            if d <> nil then 
               MiniMapSurface.StretchDraw ( 
                              Rect (i*MX, j*MY, i*MX + d.Width div SCALE, j*MY + d.Height div SCALE), 
                              d.ClientRect, 
                              d, 
                              TRUE); 
         end; 
      end; 
   end; 
   for j:=0 to ey-sy-1+25 do begin 
      for i:=0 to ex-sx do begin 
         if (i >= 0) and (i < MAXX*3) and (j < MAXY*3) then begin 
            imgnum := (Map.MArr[sx+i, sy+j].FrImg and $7FFF); 
            if imgnum > 0 then begin 
               wunit := Map.MArr[sx+i, sy+j].Area; 
               ani := Map.MArr[sx+i, sy+j].AniFrame; 
               if (ani and $80) > 0 then begin 
                  continue; 
               end; 
               imgnum := imgnum - 1; 
               d := FrmMain.GetObjs(wunit, imgnum); 
               if d <> nil then begin 
                  ny := j*MY - d.Height div SCALE + MY; 
                  if ny < 360 then 
                     MiniMapSurface.StretchDraw ( 
                                 Rect (i*MX, ny, i*MX + d.Width div SCALE, ny + d.Height div SCALE), 
                                 d.ClientRect, 
                                 d, 
                                 TRUE); 
               end; 
            end; 
         end; 
      end; 
   end; 
   //DrawEffect (0, 0, MiniMapSurface.Width, MiniMapSurface.Height, MiniMapSurface, ceGrayScale); 
end; 
 
 
end.