unit _World;

{

world unit 

}

interface

Uses
  QuadEngine,
  _SysUtils,
  _Geometry,
  _forms,
  _Units,
  _Render;

Const
 //map settings
 map_x = 255;
 map_y = 255;

 //Units
 Max_Units = 500;
 Max_Wave = 100;
 //Bullets
 Max_Bullets = 100;
 //weapon types
 wt_none = 0;
 wt_cannon = 1;
 wt_heavy_cannon = 2;


type
  TTile = record
   tip:byte;
  end;

  TSelection = record
   start_point,
   end_point:TCoord;
   Selection:boolean;//flag means selection process
   Started:boolean;//flag means selection start - need set start point
   Selected:Array [0..Max_Units] of boolean;
  end;


  TWorld = class
    private
     Map:array [0..Map_x,0..Map_y] of TTile;
     //Screen View params
     Tiles_On_Screen:TCoord;
     //Units
     Units:array [0..Max_Units] of TBaseUnit;
     //ai_timer - for free some takts in unit ai
     ai_timer:byte;
     //Selection
     Sel:TSelection;
     Player_side:byte;
     procedure Render_Map;
     procedure Render_Units;
     procedure Select;                                                   
     procedure Render_Selection_Rect;
     procedure Fire(unit_index:word); 
     procedure Draw_Interface;
     function Create_Unit(tip:byte;Crd,Vp:TVector;Ang:Single;Unit_Side:byte):Word;       
     procedure Act(num:byte);   
     Procedure Show_Mess(num:byte;Alpha:integer);
    public
     //Level
     Num_level:byte;
     Points:Integer;
     Btns:array [0..3] of boolean;
     Cost:array [0..3] of byte;
     Base_num:word;
     Mess:byte;
     Mess_life:integer;
     Wave:byte;
     Wave_units:array [0..Max_Wave] of word;
     //Game_settings
     Min_Camera,
     Max_Camera:TVector;
     Camera:TVector;
     Scale,
     Need_Scale:Single;
     Show_Add_info:boolean;
     //textures
     Ground_1_tex,
     Ground_2_tex,
     trees_tex,
     Interface_tex,
     River_tex:IQuadTexture;
     Constructor CreateWorld;
     Destructor Destroy;
     procedure Move;//all characters actions/moves
     procedure Render;
     Procedure Mouse_Selection(Coord:TCoord);
     Procedure Mouse_Send(Coord:TCoord);
     Procedure Change_Selected_State;      
     procedure Load_level(Lev:byte);
  end;

Var
  Timer:IQuadTimer;

implementation
                      
{$REGION 'Create_Unit'}
function TWorld.Create_Unit(tip:byte;Crd,Vp:TVector;Ang:Single;Unit_Side:byte):word;
var i:word;
begin  
 for i := 0 to Max_Units do
  if (Units[i]=nil) then
   begin
    case tip of
     0:Units[i]:=TBasePlatform.Create(Crd,Vp,Ang,Unit_Side);
     1:Units[i]:=TTurret.Create(Crd,Vp,Ang,Unit_Side);
     2:Units[i]:=TGaus.Create(Crd,Vp,Ang,Unit_Side);
     3:Units[i]:=TTank.Create(Crd,Vp,Ang,Unit_Side);
     4:Units[i]:=THeli.Create(Crd,Vp,Ang,Unit_Side);
     5:Units[i]:=TBase.Create(Crd,Vp,Ang,Unit_Side);
     6:Units[i]:=TTransport.Create(Crd,Vp,Ang,Unit_Side);
     7:Units[i]:=THeavyTank.Create(Crd,Vp,Ang,Unit_Side);
     8:Units[i]:=THeliTank.Create(Crd,Vp,Ang,Unit_Side);
    end;
    break;
   end;
 Create_Unit:=i;
end;
{$ENDREGION}

{$REGION 'Act'}
procedure TWorld.Act(num:byte);
var
 i:word;
 Coord:TVector;
begin
 case num of
  0:begin //turret
     for i:=0 to Max_Units do
      if (Units[i]<>nil) then
       if (Sel.Selected[i]) then
        if (Units[i].Action=a_ready) then
         if (cost[num]<=Points) then
          begin //set turret on the platform place
           Coord:=Units[i].Coord;
           Units[i].Free;
           Units[i]:=TTurret.Create(Coord,Vector(0,0),Random(360),1);
           Points:=Points-cost[num];
          end;
    end;
  1:begin //gaus   
     for i:=0 to Max_Units do
      if (Units[i]<>nil) then
       if (Sel.Selected[i]) then
        if (Units[i].Action=a_ready) then
         if (cost[num]<=Points) then
          begin //set turret on the platform place
           Coord:=Units[i].Coord;
           Units[i].Free;
           Units[i]:=TGaus.Create(Coord,Vector(0,0),Random(360),1);
           Points:=Points-cost[num];
          end;
    end;
  2:if (cost[num]<=Points) then
     begin //set turret on the platform place
      Units[Create_Unit(3,Units[Base_num].Coord,Vector(250,Random(200)-100),Random(360),1)].Next_Way_Point:=plus(Units[Base_num].Coord,Vector(300,Random(500)-250));
      Points:=Points-cost[num];
     end;
  3:if (cost[num]<=Points) then
     begin //set turret on the platform place
      Units[Create_Unit(4,Units[Base_num].Coord,Vector(250,Random(200)-100),Random(360),1)].Next_Way_Point:=plus(Units[Base_num].Coord,Vector(300,Random(500)-250));
      Points:=Points-cost[num];
     end;
 end;
end; 
{$ENDREGION}

{$REGION 'Message'}
Procedure TWorld.Show_Mess(num:byte;alpha:integer);
var
 Color,
 BC:Cardinal;
begin
if alpha>255 then
 Color:=$ffffffff
  else
 Color:=alpha*$1000000+$ffffff;
if alpha>$80 then
 BC:=$80555555
  else
 BC:=alpha*$1000000+$555555;
 case num of
 {$REGION '1-st mission'}
  0:begin
     Quad.Rectangle(45,395,700,705,BC);
     Font.TextOut(50,400,1,'Противник напал внезапно и вероломно',Color);
     Font.TextOut(50,430,1,'наша секретная база оказалась',Color);
     Font.TextOut(50,460,1,'в глубоком тылу врага. Севернее нас идут',Color);
     Font.TextOut(50,490,1,'тяжелые бои - враг прорывается к Столице.',Color);
     Font.TextOut(50,520,1,'По дороге восточнее противник ',Color);
     Font.TextOut(50,550,1,'доставляет боеприпасы для тяжелых орудий.',Color);
     Font.TextOut(50,580,1,'Бери под командование танки ',Color);
     Font.TextOut(50,610,1,'и устрой засаду на дороге',Color);
     Font.TextOut(50,640,1,'Ни один конвой не должен пройти,',Color);
     Font.TextOut(50,670,1,'иначе мы не удержим нашу столицу!',Color);
    end;
  1:begin
     Quad.Rectangle(45,395,700,645,BC);
     Font.TextOut(50,400,1,'Отлично!',Color);
     Font.TextOut(50,430,1,'Первый конвой уничтожен.',Color);
     Font.TextOut(50,460,1,'Следующий на подходе.',Color);
     Font.TextOut(50,490,1,'Возможно с конвоем будет сопровождение',Color);
     Font.TextOut(50,520,1,'Мы захватили немного топлива ',Color);
     Font.TextOut(50,550,1,'построй еще пару танков.',Color);
     Font.TextOut(50,580,1,'Для постройки танка нажми значок с танком.',Color);
     Font.TextOut(50,610,1,'созданный танк появится из базы.',Color);
    end;
  2:begin
     Quad.Rectangle(45,395,700,615,BC);
     Font.TextOut(50,400,1,'Внимание! Следующую колонну',Color);
     Font.TextOut(50,430,1,'сопровождает тяжелая техника.',Color);
     Font.TextOut(50,460,1,'Враг знает, что на пути засада.',Color);
     Font.TextOut(50,490,1,'Необходимо окопать технику.',Color);
     Font.TextOut(50,520,1,'Для окапывания, выделите танки',Color);
     Font.TextOut(50,550,1,'и нажмите пробел.',Color);
     Font.TextOut(50,580,1,'Колонна не должна пройти!',Color);
    end;
  3:begin
     Quad.Rectangle(45,395,700,645,BC);
     Font.TextOut(50,400,1,'Разведка докладывает о приближении',Color);
     Font.TextOut(50,430,1,'следующей колонны.',Color);
     Font.TextOut(50,460,1,'Необходимо пополнить войска. ',Color);
     Font.TextOut(50,490,1,'Можно построить вертолеты для ',Color);
     Font.TextOut(50,520,1,'обстрела прорвавшейся техники.',Color);
     Font.TextOut(50,550,1,'Внимание! Транспорты вооружены',Color);
     Font.TextOut(50,580,1,'зенитной артиллерией.',Color);
     Font.TextOut(50,610,1,'Не пытайтесь обстреливать колонну.',Color);
    end;
  4:begin
     Quad.Rectangle(45,395,700,525,BC);
     Font.TextOut(50,400,1,'Приближается огромная колонна!',Color);
     Font.TextOut(50,430,1,'Противник сконцентрировал для ',Color);
     Font.TextOut(50,460,1,'прорыва все силы в районе. ',Color);
     Font.TextOut(50,490,1,'Держитесь!',Color);
    end;
  5:begin
     Quad.Rectangle(145,395,800,525,BC);
     Font.TextOut(150,400,1,'Мы одолели их! Столица спасена!',Color);
     Font.TextOut(150,430,1,'На базе уже начато производство',Color);
     Font.TextOut(150,460,1,'супер оружия по новейшему проекту.',Color);
     Font.TextOut(150,490,1,'Победа будет за нами!',Color);
    end;
  6:begin
     Quad.Rectangle(145,395,800,495,BC);
     Font.TextOut(150,400,1,'Мы пропустили транспорт с тяжелыми снарядами.',Color);
     Font.TextOut(150,430,1,'Мы потеряем столицу. Ничто нас не спасет.',Color);
     Font.TextOut(150,460,1,'Это провал.',Color);
    end;
  {$ENDREGION}
 {$REGION '2-nd Heli mission'}
 16:begin
     Quad.Rectangle(45,395,700,705,BC);
     Font.TextOut(50,400,1,'Наша задача - уничтожить авиабазу противника.',Color);
     Font.TextOut(50,430,1,'Базируемая на ней авиация совершает налеты на столицу.',Color);
     Font.TextOut(50,460,1,'Уничтожение этой базы даст нам время,',Color);
     Font.TextOut(50,490,1,'необходимое для завершения проекта.',Color);
     Font.TextOut(50,520,1,'База расположена к востоку от вашей позиции',Color);
     Font.TextOut(50,550,1,'и хорошо защищена поясами обороны.',Color);
     Font.TextOut(50,580,1,'Под твое командование поступают секретные танколеты -',Color);
     Font.TextOut(50,610,1,'уникальная единица, совмещающая лучшие качества танков и вертолетов.',Color);
     Font.TextOut(50,640,1,'Для изменения положения выдели танколет и нажми пробел.',Color);
     Font.TextOut(50,670,1,'До конца операции объявляется режим радиомолчания. Удачи.',Color);
    end;
 17:begin
     Quad.Rectangle(145,395,700,525,BC);
     Font.TextOut(150,400,1,'Ура!',Color);
     Font.TextOut(150,430,1,'База противника разрушена!',Color);
     Font.TextOut(150,460,1,'Теперь мы получили передышку и время,',Color);
     Font.TextOut(150,490,1,'необходимое для завершения проекта.',Color);
    end;
 18:begin
     Quad.Rectangle(145,395,700,705,BC);
     Font.TextOut(150,400,1,'Операция провалена...',Color);
     Font.TextOut(150,430,1,'Авиация противника продолжит ',Color);
     Font.TextOut(150,460,1,'атаки - Столица долго не продержится.',Color);
     Font.TextOut(150,490,1,'Мы проиграли.',Color);
    end;
{$ENDREGION}
 {$REGION '3-rd mission'}
  7:begin
     Quad.Rectangle(45,395,700,705,BC);
     Font.TextOut(50,400,1,'Необходимо отстоять базу.',Color);
     Font.TextOut(50,430,1,'Противник стягивает все войска в регионе.',Color);
     Font.TextOut(50,460,1,'Секретный проект должен быть завершен.',Color);
     Font.TextOut(50,490,1,'Используйте мощности базы .',Color);
     Font.TextOut(50,520,1,'и захваченное топливо для производства',Color);
     Font.TextOut(50,550,1,'защитных орудий и техники.',Color);
     Font.TextOut(50,580,1,'Для постройки орудий необходимо выделить ',Color);
     Font.TextOut(50,610,1,'пустую платформу и нажать на значок',Color);
     Font.TextOut(50,640,1,'Построй несколько противотанковых орудий -',Color);
     Font.TextOut(50,670,1,'с севера на базу движется несколько танков.',Color);
    end;
  8:begin
     Quad.Rectangle(45,395,700,495,BC);
     Font.TextOut(50,400,1,'Неплохо.',Color);
     Font.TextOut(50,430,1,'Следующая колонна идет с востока.',Color);
     Font.TextOut(50,460,1,'Построй орудия с правой стороны.',Color);
    end;
  9:begin
     Quad.Rectangle(45,395,700,525,BC);
     Font.TextOut(50,400,1,'Еще одна колонна с востока.',Color);
     Font.TextOut(50,430,1,'На этот раз очень большая.',Color);
     Font.TextOut(50,460,1,'Попробуй построить вертолеты, - они смогут',Color);
     Font.TextOut(50,490,1,'начать обстрел танков с дальних расстояний.',Color);
    end;
  10:begin
     Quad.Rectangle(45,395,700,525,BC);
     Font.TextOut(50,400,1,'Поврежденные башни можно прятать и ремонтировать.',Color);
     Font.TextOut(50,430,1,'Выдели башню и нажми пробел.',Color);
     Font.TextOut(50,460,1,'Спрятанная под землю башня восстанавливает защиту.',Color);
     Font.TextOut(50,490,1,'Внимание! Колонны с севера и востока.',Color);
    end;
  11:begin
     Quad.Rectangle(45,395,700,525,BC);
     Font.TextOut(50,400,1,'Вражеские вертолеты!',Color);
     Font.TextOut(50,430,1,'Нужно построить зенитную турель или вертолеты.',Color);
     Font.TextOut(50,460,1,'Обычные турели можно спрятать, но помни -',Color);
     Font.TextOut(50,490,1,'они отвлекают огонь от базы.',Color);
    end;
  12:begin
     Quad.Rectangle(45,395,700,495,BC);
     Font.TextOut(50,400,1,'Приблжаются следующие колонны!',Color);
     Font.TextOut(50,430,1,'Следи за защитой турелей.',Color);
     Font.TextOut(50,460,1,'Они со всех сторон!',Color);
     end;
  13:begin
     Quad.Rectangle(45,395,700,495,BC);
     Font.TextOut(50,400,1,'Дъявол!',Color);
     Font.TextOut(50,430,1,'Они бросили на нас все!',Color);
     Font.TextOut(50,460,1,'Держитесь!',Color);
     end;
  14:begin
     Quad.Rectangle(145,395,800,525,BC);
     Font.TextOut(150,400,1,'Мы отстояли базу!',Color);
     Font.TextOut(150,430,1,'Проект будет закончен!',Color);
     Font.TextOut(150,460,1,'Вероломный враг будет разбит!',Color);
     Font.TextOut(150,490,1,'Мы победим!',Color);
    end;
  15:begin
     Quad.Rectangle(145,395,800,525,BC);
     Font.TextOut(150,400,1,'База уничтожена!',Color);
     Font.TextOut(150,430,1,'Проект пропал..',Color);
     Font.TextOut(150,460,1,'Мы не сможем победить ',Color);
     Font.TextOut(150,490,1,'в этой войне...',Color);
    end;  
{$ENDREGION}
 end;
end;
{$ENDREGION}

{$REGION 'Load_Level'}
procedure TWorld.Load_level(Lev:byte);
Var
 i,j:word;
 nv:TVector;
begin
 nv:=Vector(0,0);
 //Camera
 Min_Camera:=Vector(30*Tile_Size,30*Tile_Size);
 Max_Camera:=Vector(70*Tile_Size,70*Tile_Size);
{$REGION 'Random_map'}
 if Lev<5 then
 begin
 //Random_map
 for i:=0 to Map_x do
  for j:=0 to Map_y do
   begin
    Map[i,j].tip:= 0;
    if random(3)=1 then
     begin
      Map[i,j].tip:=3+Random(4);
     end;
   end;
 //river
 for i:=0 to Map_x div 5 do
  begin
   Map[8,i].tip:=Random(2)*Random(2)*Random(2)+1;
  end;
 for i:=0 to Map_x div 5 do
  begin
   Map[17,i].tip:=Random(2)*Random(2)*Random(2)+7;
  end;
 end;
{$ENDREGION}
 //Units
 case Lev of
 {$REGION '0-demo'}
  0:begin //Menu_Back_Level
     for i:=0 to 7 do
      Create_Unit(4,Vector((45+Random(10))*Tile_Size,(26+Random(6))*Tile_Size),Vector(-20000,0),Random(360),2);
     for i:=0 to 7 do
      Create_Unit(3,Vector((20+Random(10))*Tile_Size,(65+Random(6))*Tile_Size),Vector(0,-20000),Random(360),2);
     for i:=0 to 7 do
      Create_Unit(4,Vector((43+Random(10))*Tile_Size,(106+Random(6))*Tile_Size),Vector(-40000,0),Random(360),2);
     for i:=0 to 7 do
      Create_Unit(3,Vector((20+Random(10))*Tile_Size,(165+Random(6))*Tile_Size),Vector(0,-80000),Random(360),2);
    end;
 {$ENDREGION}
 {$REGION '1-Ambush'}
  1:begin //Ambush
    Num_level:=1;
    for i := 0 to Max_Units do
     if (Units[i]<>nil) then
      begin
       Units[i].Free;
       Units[i]:=nil;
      end;
     btns[0]:=false;
     btns[1]:=false;
     btns[2]:=true;
     btns[3]:=false;
     Base_num:=Create_Unit(5,Vector((50)*Tile_Size,(50)*Tile_Size),nv,Random(360),1);
    Create_Unit(3,Vector((50+5)*Tile_Size,(50+4)*Tile_Size),nv,Random(360),1);
    Create_Unit(3,Vector((50+5)*Tile_Size,(50-2)*Tile_Size),nv,Random(360),1);
    Create_Unit(3,Vector((50+5)*Tile_Size,(50  )*Tile_Size),nv,Random(360),1);
    Create_Unit(3,Vector((50+5)*Tile_Size,(50+2)*Tile_Size),nv,Random(360),1);     
    Create_Unit(3,Vector((50+5)*Tile_Size,(50-4)*Tile_Size),nv,Random(360),1);
    Wave:=0;
    Mess_life:=1200;
    Mess:=0;
    Load_Level(9);
    Camera:=Vector(50*Tile_Size-Win.Width,50*Tile_Size-Win.Height);
  end;
{$ENDREGION}
 {$REGION '2-Heli Mission'}
  2:begin //Heli mission    
    Min_Camera:=Vector(40*Tile_Size,40*Tile_Size);
    Max_Camera:=Vector(180*Tile_Size,60*Tile_Size);
    Camera:=Vector(50*Tile_Size-Win.Width,50*Tile_Size-Win.Height);
    Num_level:=2;
    for i:=0 to 3  do
     btns[i]:=false;    
    for i := 0 to Max_Units do
     if (Units[i]<>nil) then
      begin
       Units[i].Free;
       Units[i]:=nil;
      end;
     for i:=0 to 5 do
       Wave_units[i]:=Create_Unit(8,Vector((50+Random(6))*Tile_Size,(45+random(10))*Tile_Size),nv,Random(360),1);
     for i:=0 to 20 do
      Create_Unit(6,Vector((70+Random(10))*Tile_Size,(40+random(20))*Tile_Size),nv,Random(360),2);
     for i:=0 to 16 do
      Create_Unit(3,Vector((90+Random(10))*Tile_Size,(40+random(20))*Tile_Size),nv,Random(360),2);
     for i:=0 to 1 do
      Create_Unit(6,Vector((90+Random(10))*Tile_Size,(40+random(20))*Tile_Size),nv,Random(360),2);

     for i:=0 to 7 do
      Create_Unit(1,Vector((115)*Tile_Size,(36+i*4)*Tile_Size),nv,Random(360),2);

     for i:=0 to 5 do
      Create_Unit(2,Vector((130)*Tile_Size,(36+i*4)*Tile_Size),nv,Random(360),2);
     for i:=0 to 4 do
      Create_Unit(4,Vector((125+Random(10))*Tile_Size,(40+random(20))*Tile_Size),nv,Random(360),2);
     Base_num:=Create_Unit(5,Vector((140+Random(10))*Tile_Size,(40+random(20))*Tile_Size),nv,Random(360),2);
     Mess_life:=1300;
     Mess:=16;
     Wave:=16;
    end;
 {$ENDREGION}
 {$REGION '3-base protect mission'}
  3:begin//Base Protection
     Points:=60;
     Num_level:=3;      
    Camera:=Vector(50*Tile_Size-Win.Width,50*Tile_Size-Win.Height);
     for i := 0 to Max_Units do
      if (Units[i]<>nil) then
       begin
        Units[i].Free;
        Units[i]:=nil;
       end;
   //turrets
 //  for i:=0 to 10 do
//   Units[i]:=TBasePlatform.Create(Vector(40*Tile_Size+Random(200)*Tile_Size/10,30*Tile_Size+Random(1000)),Random(360),1);
   for i:=0 to 3  do
    btns[i]:=true;
   Base_num:=Create_Unit(5,Vector((50)*Tile_Size,(50)*Tile_Size),nv,Random(360),1);

   Create_Unit(0,Vector((50+3)*Tile_Size,(50+3)*Tile_Size),nv,Random(360),1);
   Create_Unit(0,Vector((50+3)*Tile_Size,(50-3)*Tile_Size),nv,Random(360),1);
   Create_Unit(0,Vector((50-3)*Tile_Size,(50+3)*Tile_Size),nv,Random(360),1);
   Create_Unit(0,Vector((50-3)*Tile_Size,(50-3)*Tile_Size),nv,Random(360),1);

   Create_Unit(0,Vector((50+5)*Tile_Size,(50+5)*Tile_Size),nv,Random(360),1);
   Create_Unit(0,Vector((50+5)*Tile_Size,(50-5)*Tile_Size),nv,Random(360),1);
   Create_Unit(0,Vector((50-5)*Tile_Size,(50+5)*Tile_Size),nv,Random(360),1);
   Create_Unit(0,Vector((50-5)*Tile_Size,(50-5)*Tile_Size),nv,Random(360),1);

   Create_Unit(0,Vector((50-7)*Tile_Size,(50+2)*Tile_Size),nv,Random(360),1);
   Create_Unit(0,Vector((50-7)*Tile_Size,(50-2)*Tile_Size),nv,Random(360),1);
   Create_Unit(0,Vector((50+7)*Tile_Size,(50+2)*Tile_Size),nv,Random(360),1);
   Create_Unit(0,Vector((50+7)*Tile_Size,(50-2)*Tile_Size),nv,Random(360),1);

   Create_Unit(0,Vector((50-2)*Tile_Size,(50+7)*Tile_Size),nv,Random(360),1);
   Create_Unit(0,Vector((50-2)*Tile_Size,(50-7)*Tile_Size),nv,Random(360),1);
   Create_Unit(0,Vector((50+2)*Tile_Size,(50+7)*Tile_Size),nv,Random(360),1);
   Create_Unit(0,Vector((50+2)*Tile_Size,(50-7)*Tile_Size),nv,Random(360),1);
   Wave:=7;
   Mess_life:=1600;
   Mess:=7;

   for i:=0 to 5 do
    Wave_units[i]:=Create_Unit(3,Vector((46+Random(8))*Tile_Size,(Random(8))*Tile_Size),Vector(0,46*Tile_Size),Random(360),2);

  end;
 {$ENDREGION}
 {$REGION '1 mission additional actions'}
  7:begin //win
     If (Mess_Life=0) then Mess_life:=600;
     Mess:=5;
     if Mess_life<40 then Load_Level(2);
   end;
  8:begin //lose
     If (Mess_Life=0) then Mess_life:=600;
     Mess:=6;
     if Mess_life<20 then Num_Level:=0;
   end;
  9:begin //reinforsment
    for i:=0 to Max_Wave do
      Wave_units[i]:=0;
    for i:=0 to 5  do
     begin
      Wave_units[i]:=Create_Unit(6,Vector((67.9)*Tile_Size,(55+1.2*i+50)*Tile_Size),Vector(0,-500*Tile_Size),270,2);
      wave:=1;
     end;
   end;
   10:begin //reinforsment
     Points:=Points+30;
     for i:=0 to Max_Wave do
       Wave_units[i]:=0;
     Wave_units[i]:=Create_Unit(7,Vector((67.9+1)*Tile_Size,(50+1.1*1+40)*Tile_Size),Vector(0,-500*Tile_Size),270,2);
     Wave_units[i]:=Create_Unit(7,Vector((67.9-1)*Tile_Size,(50+1.1*1+40)*Tile_Size),Vector(0,-500*Tile_Size),270,2);
     for i:=0 to 7  do
      begin
       Wave_units[i]:=Create_Unit(6,Vector((67.9)*Tile_Size,(50+1.1*i+40)*Tile_Size),Vector(0,-500*Tile_Size),270,2);
       Mess_life:=600;
       Mess:=1;
       Wave:=2;
      end;
    end;
   11:begin //reinforsment
     Points:=Points+50;
     for i:=0 to Max_Wave do
       Wave_units[i]:=0;
     Wave_units[i]:=Create_Unit(7,Vector((67.9+1)*Tile_Size,(50+1.1*1+40)*Tile_Size),Vector(0,-500*Tile_Size),270,2);
     Wave_units[i]:=Create_Unit(7,Vector((67.9-1)*Tile_Size,(50+1.1*1+40)*Tile_Size),Vector(0,-500*Tile_Size),270,2);
     Wave_units[i]:=Create_Unit(7,Vector((67.9+1)*Tile_Size,(50+1.1*2+40)*Tile_Size),Vector(0,-500*Tile_Size),270,2);
     Wave_units[i]:=Create_Unit(7,Vector((67.9-1)*Tile_Size,(50+1.1*2+40)*Tile_Size),Vector(0,-500*Tile_Size),270,2);
     Wave_units[i]:=Create_Unit(6,Vector((67.9+1)*Tile_Size,(50+1.1*3+40)*Tile_Size),Vector(0,-500*Tile_Size),270,2);
     Wave_units[i]:=Create_Unit(6,Vector((67.9-1)*Tile_Size,(50+1.1*3+40)*Tile_Size),Vector(0,-500*Tile_Size),270,2);
     Wave_units[i]:=Create_Unit(7,Vector((67.9+1)*Tile_Size,(50+1.1*4+40)*Tile_Size),Vector(0,-500*Tile_Size),270,2);
     Wave_units[i]:=Create_Unit(7,Vector((67.9-1)*Tile_Size,(50+1.1*4+40)*Tile_Size),Vector(0,-500*Tile_Size),270,2);
     for i:=0 to 8  do
      begin
       Wave_units[i]:=Create_Unit(6,Vector((67.9)*Tile_Size,(50+1*i+40)*Tile_Size),Vector(0,-500*Tile_Size),270,2);
       Mess_life:=600;
       Mess:=2;
       Wave:=3;
      end;
    end;
   12:begin //reinforsment
     Points:=Points+100;
     for i:=0 to Max_Wave do
       Wave_units[i]:=0;
     Wave_units[i]:=Create_Unit(7,Vector((67.9+1)*Tile_Size,(50+1.1*1+40)*Tile_Size),Vector(0,-500*Tile_Size),270,2);
     Wave_units[i]:=Create_Unit(7,Vector((67.9-1)*Tile_Size,(50+1.1*1+40)*Tile_Size),Vector(0,-500*Tile_Size),270,2);
     Wave_units[i]:=Create_Unit(7,Vector((67.9+1)*Tile_Size,(50+1.1*2+40)*Tile_Size),Vector(0,-500*Tile_Size),270,2);
     Wave_units[i]:=Create_Unit(7,Vector((67.9-1)*Tile_Size,(50+1.1*2+40)*Tile_Size),Vector(0,-500*Tile_Size),270,2);
     Wave_units[i]:=Create_Unit(6,Vector((67.9+1)*Tile_Size,(50+1.1*3+40)*Tile_Size),Vector(0,-500*Tile_Size),270,2);
     Wave_units[i]:=Create_Unit(6,Vector((67.9-1)*Tile_Size,(50+1.1*3+40)*Tile_Size),Vector(0,-500*Tile_Size),270,2);
     Wave_units[i]:=Create_Unit(7,Vector((67.9+1)*Tile_Size,(50+1.1*4+40)*Tile_Size),Vector(0,-500*Tile_Size),270,2);
     Wave_units[i]:=Create_Unit(7,Vector((67.9-1)*Tile_Size,(50+1.1*4+40)*Tile_Size),Vector(0,-500*Tile_Size),270,2);
     Wave_units[i]:=Create_Unit(6,Vector((67.9+1)*Tile_Size,(50+1.1*5+40)*Tile_Size),Vector(0,-500*Tile_Size),270,2);
     Wave_units[i]:=Create_Unit(6,Vector((67.9-1)*Tile_Size,(50+1.1*5+40)*Tile_Size),Vector(0,-500*Tile_Size),270,2);
     for i:=0 to 10  do
      begin
       Wave_units[i]:=Create_Unit(6,Vector((67.9)*Tile_Size,(50+1*i+40)*Tile_Size),Vector(0,-500*Tile_Size),270,2);
       Mess_life:=600;
       Mess:=3;
       Wave:=4;        
       btns[3]:=true;
      end;
    end;   
   13:begin //reinforsment
     Points:=Points+120;
     for i:=0 to Max_Wave do
       Wave_units[i]:=0;
     Wave_units[i]:=Create_Unit(7,Vector((67.9+2)*Tile_Size,(50+1.1*1+40)*Tile_Size),Vector(0,-500*Tile_Size),270,2);
     Wave_units[i]:=Create_Unit(7,Vector((67.9-2)*Tile_Size,(50+1.1*1+40)*Tile_Size),Vector(0,-500*Tile_Size),270,2);
     Wave_units[i]:=Create_Unit(7,Vector((67.9+2)*Tile_Size,(50+1.1*2+40)*Tile_Size),Vector(0,-500*Tile_Size),270,2);
     Wave_units[i]:=Create_Unit(7,Vector((67.9-2)*Tile_Size,(50+1.1*2+40)*Tile_Size),Vector(0,-500*Tile_Size),270,2);
     Wave_units[i]:=Create_Unit(7,Vector((67.9+2)*Tile_Size,(50+1.1*3+40)*Tile_Size),Vector(0,-500*Tile_Size),270,2);
     Wave_units[i]:=Create_Unit(7,Vector((67.9-2)*Tile_Size,(50+1.1*3+40)*Tile_Size),Vector(0,-500*Tile_Size),270,2);
     Wave_units[i]:=Create_Unit(7,Vector((67.9+2)*Tile_Size,(50+1.1*4+40)*Tile_Size),Vector(0,-500*Tile_Size),270,2);
     Wave_units[i]:=Create_Unit(7,Vector((67.9-2)*Tile_Size,(50+1.1*4+40)*Tile_Size),Vector(0,-500*Tile_Size),270,2);
     Wave_units[i]:=Create_Unit(7,Vector((67.9+2)*Tile_Size,(50+1.1*5+40)*Tile_Size),Vector(0,-500*Tile_Size),270,2);
     Wave_units[i]:=Create_Unit(7,Vector((67.9-2)*Tile_Size,(50+1.1*5+40)*Tile_Size),Vector(0,-500*Tile_Size),270,2);

     Wave_units[i]:=Create_Unit(6,Vector((67.9+1)*Tile_Size,(50+1.1*2+40)*Tile_Size),Vector(0,-500*Tile_Size),270,2);
     Wave_units[i]:=Create_Unit(6,Vector((67.9-1)*Tile_Size,(50+1.1*2+40)*Tile_Size),Vector(0,-500*Tile_Size),270,2);
     Wave_units[i]:=Create_Unit(6,Vector((67.9+1)*Tile_Size,(50+1.1*3+40)*Tile_Size),Vector(0,-500*Tile_Size),270,2);
     Wave_units[i]:=Create_Unit(6,Vector((67.9-1)*Tile_Size,(50+1.1*3+40)*Tile_Size),Vector(0,-500*Tile_Size),270,2);
     Wave_units[i]:=Create_Unit(6,Vector((67.9+1)*Tile_Size,(50+1.1*4+40)*Tile_Size),Vector(0,-500*Tile_Size),270,2);
     Wave_units[i]:=Create_Unit(6,Vector((67.9-1)*Tile_Size,(50+1.1*4+40)*Tile_Size),Vector(0,-500*Tile_Size),270,2);
     Wave_units[i]:=Create_Unit(6,Vector((67.9+1)*Tile_Size,(50+1.1*5+40)*Tile_Size),Vector(0,-500*Tile_Size),270,2);
     Wave_units[i]:=Create_Unit(6,Vector((67.9-1)*Tile_Size,(50+1.1*5+40)*Tile_Size),Vector(0,-500*Tile_Size),270,2);
     for i:=0 to 6  do
      begin
       Wave_units[i]:=Create_Unit(6,Vector((67.9)*Tile_Size,(50+1*i+40)*Tile_Size),Vector(0,-500*Tile_Size),270,2);
       Mess_life:=600;
       Mess:=4;
       Wave:=5;
      end;
    end;
{$ENDREGION}
 {$REGION '3 mission adittional'}
   14:begin         
       Points:=Points+60;
       Mess_life:=600;
       Mess:=8;
       Wave:=Wave+1;
       for i:=0 to 8 do
        Wave_units[i]:= Create_Unit(3,Vector((50+46+Random(8))*Tile_Size,(46+Random(8))*Tile_Size),Vector(-46*Tile_Size,0),Random(360),2);
   end;
   15:begin         
       Points:=Points+30;
       Mess_life:=600;
       Mess:=9;
       Wave:=Wave+1;
       for i:=0 to 14 do
        Wave_units[i]:= Create_Unit(3,Vector((50+46+Random(8))*Tile_Size,(46+Random(8))*Tile_Size),Vector(-46*Tile_Size,0),Random(360),2);
   end;
   16:begin         
       Points:=Points+50;
       Mess_life:=600;
       Mess:=10;
       Wave:=Wave+1;
       for i:=0 to 4 do
        Wave_units[i]:=Create_Unit(3,Vector((46+Random(8))*Tile_Size,(Random(8))*Tile_Size),Vector(0,46*Tile_Size),Random(360),2);
       for i:=0 to 4 do
        Wave_units[i]:=Create_Unit(7,Vector((46+Random(8))*Tile_Size,(Random(8))*Tile_Size),Vector(0,46*Tile_Size),Random(360),2);
       for i:=0 to 8 do
        Wave_units[i]:= Create_Unit(3,Vector((50+46+Random(8))*Tile_Size,(46+Random(8))*Tile_Size),Vector(-46*Tile_Size,0),Random(360),2);
       for i:=0 to 6 do
        Wave_units[i]:= Create_Unit(7,Vector((50+46+Random(8))*Tile_Size,(46+Random(8))*Tile_Size),Vector(-46*Tile_Size,0),Random(360),2);
   end;
   17:begin
       Points:=Points+70;
       Mess_life:=600;
       Mess:=11;
       Wave:=Wave+1;
       for i:=0 to 3 do
        Wave_units[i]:= Create_Unit(4,Vector((-50+46+Random(8))*Tile_Size,(46+Random(8))*Tile_Size),Vector(+46*Tile_Size,0),Random(360),2);
   end;
   18:begin
       Points:=Points+90;
       Mess_life:=600;
       Mess:=12;
       Wave:=Wave+1;
       for i:=0 to 5 do
        Wave_units[i]:=Create_Unit(3,Vector((46+Random(8))*Tile_Size,(Random(8))*Tile_Size),Vector(0,46*Tile_Size),Random(360),2);
       for i:=0 to 7 do
        Wave_units[i]:=Create_Unit(7,Vector((46+Random(8))*Tile_Size,(Random(8))*Tile_Size),Vector(0,46*Tile_Size),Random(360),2);
       for i:=0 to 9 do
        Wave_units[i]:= Create_Unit(3,Vector((50+46+Random(8))*Tile_Size,(46+Random(8))*Tile_Size),Vector(-46*Tile_Size,0),Random(360),2);
       for i:=0 to 3 do
        Wave_units[i]:= Create_Unit(7,Vector((50+46+Random(8))*Tile_Size,(46+Random(8))*Tile_Size),Vector(-46*Tile_Size,0),Random(360),2);
       for i:=0 to 2 do
        Wave_units[i]:= Create_Unit(6,Vector((50+46+Random(8))*Tile_Size,(46+Random(8))*Tile_Size),Vector(-46*Tile_Size,0),Random(360),2);
       for i:=0 to 5 do
        Wave_units[i]:= Create_Unit(4,Vector((50+46+Random(8))*Tile_Size,(46+Random(8))*Tile_Size),Vector(-46*Tile_Size,0),Random(360),2);
       for i:=0 to 4 do
        Wave_units[i]:= Create_Unit(4,Vector((-50+46+Random(8))*Tile_Size,(46+Random(8))*Tile_Size),Vector(+46*Tile_Size,0),Random(360),2);
   end;
   19:begin
       Points:=Points+90;
       Mess_life:=600;
       Mess:=13;
       Wave:=Wave+1;
       for i:=0 to 5 do
        Wave_units[i]:=Create_Unit(3,Vector((46+Random(8))*Tile_Size,(Random(8))*Tile_Size),Vector(0,46*Tile_Size),Random(360),2);
       for i:=0 to 7 do
        Wave_units[i]:=Create_Unit(7,Vector((46+Random(8))*Tile_Size,(Random(8))*Tile_Size),Vector(0,46*Tile_Size),Random(360),2);
       for i:=0 to 9 do
        Wave_units[i]:= Create_Unit(3,Vector((50+46+Random(8))*Tile_Size,(46+Random(8))*Tile_Size),Vector(-46*Tile_Size,0),Random(360),2);
       for i:=0 to 3 do
        Wave_units[i]:= Create_Unit(7,Vector((50+46+Random(8))*Tile_Size,(46+Random(8))*Tile_Size),Vector(-46*Tile_Size,0),Random(360),2);
       for i:=0 to 2 do
        Wave_units[i]:= Create_Unit(5,Vector((50+46+Random(8))*Tile_Size,(46+Random(8))*Tile_Size),Vector(-46*Tile_Size,0),Random(360),2);
       for i:=0 to 4 do
        Wave_units[i]:= Create_Unit(4,Vector((-50+46+Random(8))*Tile_Size,(46+Random(8))*Tile_Size),Vector(+46*Tile_Size,0),Random(360),2);

       for i:=0 to 4 do
        Wave_units[i]:=Create_Unit(7,Vector((46+Random(8))*Tile_Size,(Random(8))*Tile_Size),Vector(0,46*Tile_Size),Random(360),2);
       for i:=0 to 3 do
        Wave_units[i]:= Create_Unit(3,Vector((50+46+Random(8))*Tile_Size,(46+Random(8))*Tile_Size),Vector(-46*Tile_Size,0),Random(360),2);
       for i:=0 to 3 do
        Wave_units[i]:= Create_Unit(7,Vector((50+46+Random(8))*Tile_Size,(46+Random(8))*Tile_Size),Vector(-46*Tile_Size,0),Random(360),2);
       for i:=0 to 2 do
        Wave_units[i]:= Create_Unit(6,Vector((50+46+Random(8))*Tile_Size,(46+Random(8))*Tile_Size),Vector(-46*Tile_Size,0),Random(360),2);
       for i:=0 to 5 do
        Wave_units[i]:= Create_Unit(4,Vector((50+46+Random(8))*Tile_Size,(46+Random(8))*Tile_Size),Vector(-46*Tile_Size,0),Random(360),2);
       for i:=0 to 4 do
        Wave_units[i]:= Create_Unit(4,Vector((-50+46+Random(8))*Tile_Size,(46+Random(8))*Tile_Size),Vector(+46*Tile_Size,0),Random(360),2);
   end;
  20:begin //win
     If (Mess_Life=0) then Mess_life:=600;
     Mess:=14;
     if Mess_life<10 then Num_Level:=0;
   end;
  21:begin //lose
     If (Mess_Life=0) then Mess_life:=600;
     Mess:=15;
     if Mess_life<40 then Num_Level:=0;
     Wave:=14;
   end;
 {$ENDREGION}
 {$REGION '2 mission helitank add'}
   22:begin //helitank lose
     If (Mess_Life=0) then Mess_life:=600;
     Mess:=18;
     if Mess_life<40 then Num_Level:=0;
   end;
   23:begin //helitank win
     If (Mess_Life=0) then Mess_life:=600;
     Mess:=17;
     if Mess_life<50 then Load_Level(3);
   end;
 {$ENDREGION}
 end;
end;
{$ENDREGION}

{$REGION 'Create'}
constructor TWorld.CreateWorld;
Var
 i:byte;
begin
 Num_level:=0;
 Need_Scale:=0.5;
 Scale:=0.5;
 Ground_1_tex:=Quad.CreateAndLoadTexture(0,'data/ground.jpg');
 Ground_2_tex:=Quad.CreateAndLoadTexture(0,'data/ground_.jpg');
 River_tex:=Quad.CreateAndLoadTexture(0,'data/river.png',256,512);
 trees_tex:=Quad.CreateAndLoadTexture(0,'data/trees.png',256,256);
 Interface_tex:=Quad.CreateAndLoadTexture(0,'data/Interface.png',64,64);
 Load_Units_Texture;
 Tiles_On_Screen:=Coord(
                  Round((Win.ScreenWidth/ground_size))+1,
                  Round((Win.ScreenHeight/ground_size))+1);
 Quad.SetTextureFiltering(1);

 Player_side:=1;
 Emiter:=TEmiter.Create;
 Emiter.Wind:=Vector(0.3,0.4);
 cost[0]:=20;
 cost[1]:=25;
 cost[2]:=15;
 cost[3]:=20;
 Points:=0;  
//random map
 Load_Level(0);
end;

Destructor TWorld.Destroy;
var i:word;
begin      
 for i := 0 to Max_Units do
  if (Units[i]<>nil) then
   Units[i].Free;
end;
{$ENDREGION}

{$REGION 'Move'}
procedure TWorld.Move;
Var
 i,j:word;
 nearest:single;
 flag:boolean;
begin
 //Next_Wave
 if Random(20)=0 then
  begin
   j:=0;
   for i:=0 to Max_Wave do
    if Wave_Units[i]<>0 then
     if Units[Wave_Units[i]]<>nil then
     if Units[Wave_Units[i]].Action<a_die then
     begin
      inc(j);
     end;
   //lose params
   if Num_Level=1 then
    for i:=0 to Max_Wave do
     if Wave_Units[i]<>0 then
      if Units[Wave_Units[i]]<>nil then
       if (Units[Wave_Units[i]].Coord[1]<(30)*Tile_Size) then
         Load_Level(8);
   if Num_Level=3 then
    if Units[Base_num].Action>=a_die then
     Load_Level(21);
   if Num_Level=2 then
    if Units[Base_num].Action>=a_die then
     Load_Level(23);
   if (j=0) then
    case Wave of
     0:;
     1:Load_Level(10);
     2:Load_Level(11);
     3:Load_Level(12);
     4:Load_Level(13);
     5:Load_Level(7);
     6:Load_Level(25);
     7:Load_Level(14);
     8:Load_Level(15);
     9:Load_Level(16);
     10:Load_Level(17);
     11:Load_Level(18);
     12:Load_Level(19);
     13:Load_Level(20);
     14:Load_Level(21);
     16:Load_Level(22);
    end;
  end;
 //moving
 Emiter.move;
 Select;
 //tact timer
 ai_timer:=ai_timer+1;
 if (ai_timer=100) then ai_timer:=0; 
 //smoothing Camera Scale
 if (Need_Scale<0.4) then Need_Scale:=0.4;
 if (Need_Scale>2) then Need_Scale:=2;
 //set camera on center
 Camera[0]:=Camera[0]+(Win.ScreenWidth/2)/Scale;
 Camera[1]:=Camera[1]+(Win.ScreenHeight/2)/Scale;
 if (Camera[0]<Min_Camera[0]) then Camera[0]:=Min_Camera[0];
 if (Camera[1]<Min_Camera[1]) then Camera[1]:=Min_Camera[1];
 if (Camera[0]>Max_Camera[0]) then Camera[0]:=Max_Camera[0];
 if (Camera[1]>Max_Camera[1]) then Camera[1]:=Max_Camera[1];
 //Scale camera
 Scale:=Scale*0.9+Need_Scale*0.1;      
 //set camera back after scale
 Camera[0]:=Camera[0]-(Win.ScreenWidth/2)/Scale;
 Camera[1]:=Camera[1]-(Win.ScreenHeight/2)/Scale;
 //Units move
 for i := 0 to Max_Units do
  if (Units[i]<>nil) then
   Units[i].Move;
 //Units die
 for i := 0 to Max_Units do
  if (Units[i]<>nil) then
  if (Units[i].Action=a_free) then
   begin
    if Units[i].Anim=to_platform then
     Create_Unit(0, Units[i].Coord,Vector(0,0),Random(360),1);
    Units[i].Free;
    Units[i]:=nil;
   end;

 //units_fire
 for i := 0 to Max_Units do
  if (Units[i]<>nil) then
//   if Units[i].has_target then
   if Units[i].Fire then
    Fire(i);
 for i := 0 to Max_Units do
  if (Units[i]<>nil) then
  begin
   //:)
//   if (Units[i].Action=a_none) then if (random(3000)=0) then Units[i].Need_Cannon_Angle:=Random(360);
   //AI                        
   //find nearest enemy
//   if (ai_timer mod 3 +1 = i mod 3) then
   begin
    flag:=true;
    nearest:=Units[i].View_Radius;
    if (Units[i].Action=a_none) or (Units[i].Action=a_move) then
    for j:= 0 to Max_Units do
     if (Units[j]<> nil) then
      if (Units[j].Side<>Units[i].Side) then
      if (Units[j].Action<a_die) then
      if (Units[j].Life>0) then
      if (Units[i].Can_Hit(Units[j].tip)) then
      if (Units[i].Coord[0]>Units[j].Coord[0]-Units[i].View_Radius) then
      if (Units[i].Coord[1]>Units[j].Coord[1]-Units[i].View_Radius) then
      if (Units[i].Coord[0]<Units[j].Coord[0]+Units[i].View_Radius) then
      if (Units[i].Coord[1]<Units[j].Coord[1]+Units[i].View_Radius) then
      if (Get_S(Units[i].Coord,Units[j].Coord)<Units[i].View_Radius) then
      if (Get_S(Units[i].Coord,Units[j].Coord)<nearest) then
       begin
        nearest:=Get_S(Units[i].Coord,Units[j].Coord);
        Units[i].Target:=j;
        Units[i].Has_target:=true;
        Units[i].Target_Coord:=Units[j].Coord;
        flag:=false;
       end;
     if flag then Units[i].has_target:=false;             
    end;
  end;
end;
{$ENDREGION}

{$REGION 'Unit Fire'}
procedure TWorld.Fire(unit_index:word);
var i:byte;
begin
 if Units[unit_index]<>nil then
  if Units[Units[unit_index].Target]<>nil then
  begin
   Units[Units[unit_index].Target].Life:=Units[Units[unit_index].Target].Life-Units[unit_index].Enemy_Hit(Units[Units[unit_index].Target].tip);
   if (Units[Units[unit_index].Target].Life<=0) then
   if (Units[Units[unit_index].Target].Action<>a_die) then
    begin
     for i:=0 to 40 do         
      Emiter.add_particle(
                  plus(Units[Units[unit_index].Target].Coord,Vector((Random(30)-15),(Random(30)-15)/2)),
                  Vector((Random(10)-5)/2,(Random(10)-5)/2),
                  random(2),
                  30);
     Units[Units[unit_index].Target].Action:=a_die;
    end;
  end;
end;
{$ENDREGION}

{$REGION 'RenderMap'}
procedure TWorld.Render_Map;
Var
 i,j:word;
 tlCorner,brCorner:TCoord;  
 Tile_scale:TCoord;
begin
 Tile_scale[0]:=trunc(Camera[0]/ground_size);
 Tile_scale[1]:=trunc(Camera[1]/ground_size);
 if (Tile_scale[0]<0) then Tile_scale[0]:=0;
 if (Tile_scale[1]<0) then Tile_scale[1]:=0;
 if (Tile_scale[0]>Map_X) then Tile_scale[0]:=Map_X;
 if (Tile_scale[1]>Map_Y) then Tile_scale[1]:=Map_Y;
 tlCorner:=Tile_scale;
 if (tlCorner[0]<0) then tlCorner[0]:=0;
 if (tlCorner[1]<0) then tlCorner[1]:=0;
 brCorner:=plus(Tile_scale,Coord(Trunc(Tiles_On_Screen[0]/Scale)+1,Trunc(Tiles_On_Screen[1]/Scale)+1));
 if (brCorner[0]>Map_X) then brCorner[0]:=Map_X;
 if (brCorner[1]>Map_Y) then brCorner[1]:=Map_Y;

 for i:=tlCorner[0] to brCorner[0] do
  for j:=tlCorner[1] to brCorner[1]do
   begin
    if ((i+j) mod 2 = 0) then
    Ground_1_tex.DrawRot(
       (i*ground_size-Camera[0])*Scale,
       (j*ground_size-Camera[1])*Scale,
       0,
       Scale,
       $ffffffff) else
    Ground_2_tex.DrawRot(
       (i*ground_size-Camera[0])*Scale,
       (j*ground_size-Camera[1])*Scale,
       0,
       Scale,
       $ffffffff);
    if (map[i,j].tip=1) or (map[i,j].tip=2) then
    River_tex.DrawRot(
       (i*ground_size-Camera[0])*Scale,
       (j*ground_size-Camera[1])*Scale,
       0,
       Scale,
       $ffffffff,
       map[i,j].tip-1);
    if (map[i,j].tip>2) and (map[i,j].tip<7) then
    Trees_tex.DrawRot(
       (i*ground_size-Camera[0]+map[i,j].tip*10)*Scale,
       (j*ground_size-Camera[1]+map[i,j].tip*20)*Scale,
       0,
       Scale,
       $ffffffff,
       map[i,j].tip-3);
    if (map[i,j].tip=7) or (map[i,j].tip=8) then
    River_tex.DrawRot(
       (i*ground_size-Camera[0])*Scale,
       (j*ground_size-Camera[1])*Scale,
       0,
       Scale,
       $ffffffff,
       map[i,j].tip-7+2);
      
   end;
end;
{$ENDREGION}

{$REGION 'Render Units'}
procedure TWorld.Render_Units;
var
 i:word;
 c:cardinal;
begin
{//tmp
 for i:=0 to Max_Units do
  if (Units[i]<>nil) then
  begin
   Quad.DrawLine((Units[i].Coord[0]-Camera[0])*scale,
                 (Units[i].Coord[1]-Camera[1])*scale,
                 (Units[i].Next_Way_Point[0]-Camera[0])*scale,
                 (Units[i].Next_Way_Point[1]-Camera[1])*scale,$ffffffff);
  end;
//tmp   }
 //render units
 for i:=0 to Max_Units do
  if (Units[i]<>nil) then
  begin
   Units[i].Draw(Camera,Scale);
   if Sel.Selected[i] or Show_Add_info then
    Quad.Rectangle(
      (Units[i].Coord[0]+30-Camera[0])*Scale,
      (Units[i].Coord[1]-3-Camera[1])*Scale,
      (Units[i].Coord[0]+30+60*(Units[i].Life/100)-Camera[0])*Scale,
      (Units[i].Coord[1]+3-Camera[1])*Scale,$6f00ff00);
  end;  
end;
{$ENDREGION}

{$REGION 'Render Selection Rect'}
procedure TWorld.Render_Selection_Rect;
begin
 Quad.Rectangle(Sel.start_point[0],Sel.start_point[1],Sel.end_point[0],Sel.end_point[1],$6f00FF00);
 Quad.Rectangle(Sel.start_point[0],Sel.end_point[1],Sel.end_point[0],Sel.start_point[1],$6f00FF00);
end;
{$ENDREGION}

{$REGION 'draw_interface'}
procedure TWorld.Draw_Interface;
var
 i:byte;
 clr:Cardinal;
begin
 if Points>0 then 
  Font.TextOut(50,20,1,PChar('Топливо: '+IntToStr(Points)) ,$FFFFFFFF);
 for i:=0 to 3 do
 if btns[i] then 
 begin
  if not Point_in_Rect(Vector(Win.mx,Win.my),Vector(50,90+74*i),Vector(50+64,80+74+74*i)) then
    clr:=$80808080 else if (Cost[i]<=Points) then clr:=$8010d010 else clr:=$80d01010; 
  Quad.Rectangle(50,90+74*i,50+64,80+74+74*i,clr);
  Interface_tex.Draw(50,90+74*i,$ffffffff,i);
 end;
 if Mess_Life>0 then dec(Mess_Life); 
 Show_Mess(Mess,Mess_Life);
end;
{$ENDREGION}

{$REGION 'Render'}
procedure TWorld.Render;
begin
 Quad.Clear($FF000000);
 Render_Map;
 Render_Units;
 if Sel.Selection then
  Render_Selection_Rect;  
 Sel.Selection:=false;
 Emiter.Render(Camera,Scale);
 Draw_Interface;
end;
{$ENDREGION}

{$REGION 'Mouse_Selection'}
procedure TWorld.Mouse_Selection(Coord: TCoord);
var                              
 i:byte;
 flag:boolean;
begin
 Sel.end_point:=Coord;
 if Sel.Started then
 begin
  //push button
  flag:=true;
  for i:=0to 3 do  
   if btns[i] then 
   if Point_in_Rect(Vector(Win.mx,Win.my),Vector(50,90+74*i),Vector(50+64,80+74+74*i)) then
   begin
    Act(i);
    Win.mbl:=false;
    flag:=false;
   end;
  if flag then
   begin
    Sel.start_point:=Coord;
    Sel.Started:=false;
   end;
 end;
 Sel.Selection:=true;
end;
{$ENDREGION}

{$REGION 'Select units'}
procedure TWorld.Select;
var
 i:word;
 s,e:TVector;
 t:single;
begin
 if not Sel.Started then 
 if not Sel.Selection then //end selection - find selected units
   begin
    s:=plus(multi(Vector(Sel.start_point),1/Scale),Camera);
    e:=plus(multi(Vector(Sel.end_point  ),1/Scale),Camera);
    if (s[0]>e[0]) then begin t:=s[0];s[0]:=e[0];e[0]:=t; end;
    if (s[1]>e[1]) then begin t:=s[1];s[1]:=e[1];e[1]:=t; end;
    for i:=0 to Max_Units do
     begin
      Sel.Selected[i]:=false;
      if (units[i]<>nil) then      
      if (Units[i].Side=Player_side) then
      if (Units[i].Coord[0]-Units[i].Size<=e[0]) then
      if (Units[i].Coord[1]-Units[i].Size<=e[1]) then
      if (Units[i].Coord[0]+Units[i].Size>=s[0]) then
      if (Units[i].Coord[1]+Units[i].Size>=s[1]) then
       begin
        Sel.Selected[i]:=true;
       end;
     end;
    Sel.Started:=true;
   end;
end;
{$ENDREGION}

{$REGION 'Mouse_Send - give some order'}
procedure TWorld.Mouse_Send(Coord: TCoord);
var i,count:word;
 oldpoint,newpoint:TVector;
begin
 newpoint:=plus(multi(Vector(Coord),1/Scale),Camera);
 oldpoint:=Vector(0,0);
 count:=0;
 //find central oldPoint
 for i:=0 to Max_Units do
 if (Units[i]<>nil) then
 if (Sel.Selected[i]) then
  begin
   oldpoint:=plus(oldpoint,Units[i].Coord);
   inc(count);
  end;
 if (count=0) then exit; //no units selected
 oldpoint:=multi(oldpoint,1/count);//find central point
 for i:=0 to Max_Units do
 if (Units[i]<>nil) then
 if (Sel.Selected[i]) then
  begin
   Units[i].Next_Way_Point:=plus(newpoint,minus(Units[i].Coord,oldpoint));
   inc(count);
  end;
end;
{$ENDREGION}

{$REGION 'Change_Selected_State'}
Procedure TWorld.Change_Selected_State;
var i:Word;
begin            
 for i:=0 to Max_Units do
 if (Units[i]<>nil) then
 if (Sel.Selected[i]) then
  begin
   Units[i].Change_State;
  end;                   
end;
{$ENDREGION}

end.
