unit g_basic; {$INCLUDE ../shared/a_modes.inc} interface uses LCLIntf, LCLType, LMessages; const EDITOR_VERSION = '0.667'; EDITOR_BUILDDATE = {$I %DATE%}; EDITOR_BUILDTIME = {$I %TIME%}; Type String16 = String[16]; Char16 = packed array[0..15] of Char; Char32 = packed array[0..31] of Char; Char64 = packed array[0..63] of Char; Char256 = packed array[0..255] of Char; ArrayStr16 = Array of String16; SArray = Array of String; DWArray = Array of DWORD; TDirection = (D_LEFT, D_RIGHT); function g_GetBuilderName (): AnsiString; function g_GetBuildHash (full: Boolean = True): AnsiString; function g_Collide(X1, Y1: Integer; Width1, Height1: Word; X2, Y2: Integer; Width2, Height2: Word): Boolean; function g_CollidePoint(X, Y, X2, Y2: Integer; Width, Height: Word): Boolean; function g_CollideLevel(X, Y: Integer; Width, Height: Word): Boolean; function g_CollideLevel2(X, Y: Integer; Width, Height: Word; _ID: DWORD; var PanelID: DWORD): Boolean; function g_PatchLength(X1, Y1, X2, Y2: Integer): Word; procedure IncMax(var A: Integer; B, Max: Integer); overload; procedure IncMax(var A: Single; B, Max: Single); overload; procedure IncMax(var A: Integer; Max: Integer); overload; procedure IncMax(var A: Single; Max: Single); overload; procedure IncMax(var A: Word; B, Max: Word); overload; procedure IncMax(var A: Word; Max: Word); overload; procedure IncMax(var A: SmallInt; B, Max: SmallInt); overload; procedure IncMax(var A: SmallInt; Max: SmallInt); overload; procedure DecMin(var A: Integer; B, Min: Integer); overload; procedure DecMin(var A: Single; B, Min: Single); overload; procedure DecMin(var A: Integer; Min: Integer); overload; procedure DecMin(var A: Single; Min: Single); overload; procedure DecMin(var A: Word; B, Min: Word); overload; procedure DecMin(var A: Word; Min: Word); overload; procedure DecMin(var A: Byte; B, Min: Byte); overload; procedure DecMin(var A: Byte; Min: Byte); overload; function Sign(A: Integer): ShortInt; overload; function Sign(A: Single): ShortInt; overload; function PointToRect(X, Y: Integer; X1, Y1, Width, Height: Integer): Integer; procedure g_ChangeDir(var dir: TDirection); function g_GetFileTime(fileName: String): Integer; function g_SetFileTime(fileName: String; time: Integer): Boolean; implementation uses Math, g_map, MAPDEF, SysUtils; {$PUSH} {$WARN 2054 OFF} // unknwon env var {$WARN 6018 OFF} // unreachable code function g_GetBuilderName (): AnsiString; begin if {$I %D2DF_BUILD_USER%} <> '' then result := {$I %D2DF_BUILD_USER%} // custom else if {$I %USER%} <> '' then result := {$I %USER%} // unix username else if {$I %USERNAME%} <> '' then result := {$I %USERNAME%} // windows username else result := 'unknown' end; function g_GetBuildHash (full: Boolean = True): AnsiString; begin if {$I %D2DF_BUILD_HASH%} <> '' then if full then result := {$I %D2DF_BUILD_HASH%} else result := Copy({$I %D2DF_BUILD_HASH%}, 1, 7) else result := 'custom build' end; {$POP} procedure g_ChangeDir(var dir: TDirection); begin if dir = D_LEFT then dir := D_RIGHT else dir := D_LEFT; end; function g_GetFileTime(fileName: String): Integer; var F: File; begin if not FileExists(fileName) then begin Result := -1; Exit; end; AssignFile(F, fileName); Reset(F); Result := FileGetDate(TFileRec(F).Handle); CloseFile(F); end; function g_SetFileTime(fileName: String; time: Integer): Boolean; var F: File; begin if (not FileExists(fileName)) or (time < 0) then begin Result := False; Exit; end; AssignFile(F, fileName); Reset(F); Result := (FileSetDate(TFileRec(F).Handle, time) = 0); CloseFile(F); end; function g_PatchLength(X1, Y1, X2, Y2: Integer): Word; begin Result := Trunc(Hypot(Abs(X2-X1), Abs(Y2-Y1))); end; function g_CollideLevel(X, Y: Integer; Width, Height: Word): Boolean; var a: Integer; begin Result := False; if gPanels = nil then Exit; for a := 0 to High(gPanels) do if gPanels[a].PanelType = PANEL_WALL then if not (((Y + Height <= gPanels[a].Y) or (Y >= gPanels[a].Y + gPanels[a].Height)) or ((X + Width <= gPanels[a].X) or (X >= gPanels[a].X + gPanels[a].Width))) then begin Result := True; Exit; end; end; {function g_CollideLevel2(X, Y, X2, Y2: Integer): Boolean; var a: Integer; begin Result := False; if gWalls = nil then Exit; for a := 0 to High(gWalls) do if not (((Y2 <= gWalls[a].Y) or (Y >= gWalls[a].Y + gWalls[a].Height)) or ((X2 <= gWalls[a].X) or (X >= gWalls[a].X + gWalls[a].Width))) then begin Result := True; Exit; end; end;} function g_CollideLevel2(X, Y: Integer; Width, Height: Word; _ID: DWORD; var PanelID: DWORD): Boolean; var a: DWORD; begin Result := False; if gPanels = nil then Exit; for a := 0 to High(gPanels) do if (gPanels[a].PanelType = PANEL_WALL) and (_ID <> a) then if not (((Y + Height <= gPanels[a].Y) or (Y >= gPanels[a].Y + gPanels[a].Height)) or ((X + Width <= gPanels[a].X) or (X >= gPanels[a].X + gPanels[a].Width))) then begin Result := True; PanelID := a; Exit; end; end; function g_Collide(X1, Y1: Integer; Width1, Height1: Word; X2, Y2: Integer; Width2, Height2: Word): Boolean; begin Result := not (((Y1 + Height1 <= Y2) or (Y1 >= Y2 + Height2)) or ((X1 + Width1 <= X2) or (X1 >= X2 + Width2))); end; function g_CollidePoint(X, Y, X2, Y2: Integer; Width, Height: Word): Boolean; begin {X := X-X2; Y := Y-Y2; Result := (x >= 0) and (x <= Width) and (y >= 0) and (y <= Height);} Result := (X >= X2) and (X <= (X2+Width)) and (Y >= Y2) and (Y <= (Y2+Height)); end; procedure IncMax(var A: Integer; B, Max: Integer); begin if A+B > Max then A := Max else A := A+B; end; procedure IncMax(var A: Single; B, Max: Single); begin if A+B > Max then A := Max else A := A+B; end; procedure DecMin(var A: Integer; B, Min: Integer); begin if A-B < Min then A := Min else A := A-B; end; procedure DecMin(var A: Word; B, Min: Word); begin if A-B < Min then A := Min else A := A-B; end; procedure DecMin(var A: Single; B, Min: Single); begin if A-B < Min then A := Min else A := A-B; end; procedure IncMax(var A: Integer; Max: Integer); begin if A+1 > Max then A := Max else A := A+1; end; procedure IncMax(var A: Single; Max: Single); begin if A+1 > Max then A := Max else A := A+1; end; procedure IncMax(var A: Word; B, Max: Word); begin if A+B > Max then A := Max else A := A+B; end; procedure IncMax(var A: Word; Max: Word); begin if A+1 > Max then A := Max else A := A+1; end; procedure IncMax(var A: SmallInt; B, Max: SmallInt); begin if A+B > Max then A := Max else A := A+B; end; procedure IncMax(var A: SmallInt; Max: SmallInt); begin if A+1 > Max then A := Max else A := A+1; end; procedure DecMin(var A: Integer; Min: Integer); begin if A-1 < Min then A := Min else A := A-1; end; procedure DecMin(var A: Single; Min: Single); begin if A-1 < Min then A := Min else A := A-1; end; procedure DecMin(var A: Word; Min: Word); begin if A-1 < Min then A := Min else A := A-1; end; procedure DecMin(var A: Byte; B, Min: Byte); begin if A-B < Min then A := Min else A := A-B; end; procedure DecMin(var A: Byte; Min: Byte); overload; begin if A-1 < Min then A := Min else A := A-1; end; function Sign(A: Integer): ShortInt; begin if A < 0 then Result := -1 else if A > 0 then Result := 1 else Result := 0; end; function Sign(A: Single): ShortInt; const Eps = 1.0E-5; begin if Abs(A) < Eps then Result := 0 else if A < 0 then Result := -1 else Result := 1; end; function PointToRect(X, Y: Integer; X1, Y1, Width, Height: Integer): Integer; begin X := X-X1; Y := Y-Y1; if X < 0 then begin if Y < 0 then Result := Round(Sqrt(Sqr(X)+Sqr(Y))) else if Y > Height then Result := Round(Sqrt(Sqr(X)+Sqr(Y-Height))) else Result := -X; end else if X > Width then begin X := X-width; if y < 0 then Result := Round(Sqrt(Sqr(X)+Sqr(Y))) else if Y > Height then Result := Round(Sqrt(Sqr(X)+Sqr(Y-Height))) else Result := X; end else begin if Y < 0 then Result := -Y else if Y > Height then Result := Y-Height else Result:=0; end; end; end.