unit uLiveObj;

interface
uses
  Windows, uMap, zglHeader;

type

  { TLiveObj }

  TLiveObj = class(TDynObj)
    otX, otY,
    ntX, ntY : Integer;
    pX, pY,
    mX, mY,
    gX, gY : Single;

    cmtX, cmtY : shortint;

    move : Boolean;
    move_count : Single;

    directions : array of Integer;
    direction_num, direct : Integer;

    //AtackTime : Integer;
    Walker : Boolean;

    Sprite : Integer;

    constructor Create(X, Y : Integer; PMap : TMap; Param : Integer; R : Boolean);
    procedure TileGo(X_, Y_ : Integer);
    procedure SetTo(X_, Y_ : Integer);
    procedure SetDirections;
    procedure NewDirection;
    function  Atack : boolean;
    procedure AI; virtual;
    procedure Update; override;
    procedure Draw; override;
  end;

implementation
uses
  uGlobal;

function CalcMove(p, g : Single) : Integer;
begin
  if (p = g) then
     result := 0
  else
	if (p < g) then
    result := 1
  else
    result := -1;
end;

{ TLiveObj }

function TLiveObj.Atack: boolean;
begin
  Map.Fight := true;
  Map.EnemyDynObj := Self;
end;

procedure TLiveObj.AI;
var
  wX, wY : Integer;
begin
  if not move and not TLiveObj(Map.Hero).move
  and (((abs(Map.Hero.tX - tX) = 1) and (Map.Hero.tY = tY))
    or ((abs(Map.Hero.tY - tY) = 1) and (Map.Hero.tX = tX))) then
    Atack;

  if Walker then
  begin
    wX := tX + cmtX;
    wY := tY + cmtY;
    if Map.FreeWay(wX, wY, false) then
      TileGo(wX, wY)
    else
      NewDirection();
  end;
end;

constructor TLiveObj.Create(X, Y: Integer; PMap: TMap; Param: Integer;
  R: Boolean);
begin
  Map := PMap;
  Map.Obj.Add(Self);

  ILiveObj := true;
  Live := 100;
  tX := X;
  tY := Y;

  pX := Map.TileA[X][Y].pX;
  pY := Map.TileA[X][Y].pY;
  mX := 0;
  mY := 0;
  gX := 0;
  gY := 0;

  move_count := 1;

  SetDirections;
  direction_num := 0;
  direct := 0;

  TileGo(X, Y);

  NewDirection();
  move := true;

  if Param > 0 then
  begin
    if R then
    Sprite := random(Param) + 2
    else
    Sprite := Param;
    if Sprite > 5 then
      Sprite := 5;
    case Sprite of
      2 : begin Walker := false; Heart := 3; Live := 3; end;
      3 : begin Walker := true; Heart := 7; Live := 4; end;
      4 : begin Walker := true; Heart := 4; Live := 6; end;
      5 : begin Walker := false; Heart := 12; Live := 9; end;
    end;
  end
  else
    Sprite := 1;


end;

procedure TLiveObj.Draw;
begin
  Asprite2d_Draw(cube, Map.camX + pX - 64 + 35, Map.camY + pY - 128, 128, 128, 0, Sprite);
end;

procedure TLiveObj.NewDirection;
begin
  if (direction_num < Length(directions) - 1) then
    direction_num := direction_num + 1
  else
    direction_num := 0;
  direct := directions[direction_num];
  cmtX := cAngleX[direct];
  cmtY := cAngleY[direct];
end;

procedure TLiveObj.SetDirections;
begin
  SetLength(directions, 4);
  directions[0] := 0;
  directions[1] := 1;
  directions[2] := 2;
  directions[3] := 3;
end;

procedure TLiveObj.TileGo(X_, Y_: Integer);
begin
  // Для изометрии менять здесь

  otX := tX;
  otY := tY;
  ntX := X_;
  ntY := Y_;

  Map.TileA[tX][tY].Free := false;
  Map.TileA[X_][Y_].Free := false;
  if (X_ > tX) or (Y_ > tY) then
  begin
    Map.TileA[X_][Y_].DObj := Self;
    Map.TileA[tX][tY].DObj := nil;
    tX := X_;
    tY := Y_;
  end
  else
  begin
    Map.TileA[X_][Y_].DObj := nil;
    Map.TileA[tX][tY].DObj := Self;
  end;

  gX := Map.TileA[X_][Y_].pX;
  gY := Map.TileA[X_][Y_].pY;
  mX := 2*move_count * CalcMove(pX, gX);
  mY := move_count * CalcMove(pY, gY);
  move := true;
end;

procedure TLiveObj.SetTo(X_, Y_: Integer);
begin
  Map.TileA[otX][otY].DObj := nil;
  Map.TileA[otX][otY].Free := true;
  Map.TileA[tX][tY].DObj := nil;
  Map.TileA[tX][tY].Free := true;
  Map.TileA[ntX][ntY].DObj := nil;
  Map.TileA[ntX][ntY].Free := true;

  Map.TileA[X_][Y_].DObj := Self;
  Map.TileA[X_][Y_].Free := false;

  otX := X_;
  otY := Y_;
  ntX := X_;
  ntY := Y_;
  tX := X_;
  tY := Y_;

  gX := Map.TileA[X_][Y_].pX;
  gY := Map.TileA[X_][Y_].pY;
  pX := Map.TileA[X_][Y_].pX;
  pY := Map.TileA[X_][Y_].pY;
  mX := 2*move_count * CalcMove(pX, gX);
  mY := move_count * CalcMove(pY, gY);

  move := false;
end;

procedure TLiveObj.Update;
begin
  if Live <= 0 then
  begin
    Map.TileA[tX][tY].DObj := nil;
    Map.TileA[otX][otY].DObj := nil;
    Map.TileA[ntX][ntY].DObj := nil;
    Map.TileA[tX][tY].Free := true;
    Map.TileA[otX][otY].Free := true;
    Map.TileA[ntX][ntY].Free := true;
    Map.Obj.Remove(Self);
  end
  else
  if (move) then
  begin
    if  (mX = 0)
    or ((mX > 0) and (pX >= gX))
    or ((mX < 0) and (pX <= gX)) then
    begin
      pX := gX;
      move := false
    end
    else
      pX := pX + mX;

    if not ((mY = 0)
    or ((mY > 0) and (pY >= gY))
    or ((mY < 0) and (pY <= gY))) then
    begin
      move := true;
      pY := pY + mY;
    end
    else
    if (not move) then
    begin
      // end move :
      Map.TileA[otX][otY].DObj := nil;
      Map.TileA[otX][otY].Free := true;
      Map.TileA[tX][tY].DObj := nil;
      Map.TileA[tX][tY].Free := true;
      Map.TileA[ntX][ntY].DObj := Self;
      Map.TileA[ntX][ntY].Free := false;
      tX := ntX;
      tY := ntY;
    end;
  end
  else
    AI;
end;


end.
