unit UWeapon;

interface

uses
  Squall,
  JEN_Header,
  JEN_Math,
  UCollide;

type
  TWeaponType = (wtNone, wtLaser1, wtLaser2, wtLaser3, wtLaser4, wtBFG, wtEnemyLaser1, wtEnemyPlasma, wtEnemyLaserGun, wtEnemyLaserGun2, wtBossGun);

const
  WeaponParam : array[TWeaponType] of record
    AttackDelay : LongInt;
    AttackTime  : LongInt;
    ShootDelay  : LongInt;
    Power       : Single;
    Speed       : Single;
    Color       : TVec4f;
    BulletSize  : Single;
    BulletLine  : Boolean;
    Player      : Boolean;
  end = (
         (AttackDelay: 0; AttackTime: 0; ShootDelay: 0; Power: 0; Speed: 0; Color: (X:1; Y:1; Z:1; W:1); BulletSize: 0; BulletLine: True; Player: False),
         (AttackDelay: 0; AttackTime: 0; ShootDelay: 60; Power: 25; Speed: 1.2; Color: (X:0.4; Y:0.8; Z:0.4; W:1); BulletSize: 40; BulletLine: True; Player: True),
         (AttackDelay: 0; AttackTime: 0; ShootDelay: 60; Power: 25; Speed: 1.2; Color: (X:0.4; Y:0.8; Z:0.4; W:1); BulletSize: 30; BulletLine: True; Player: True),
         (AttackDelay: 0; AttackTime: 0; ShootDelay: 70; Power: 25; Speed: 1.2; Color: (X:0.4; Y:0.8; Z:0.4; W:1); BulletSize: 20; BulletLine: True; Player: True),
         (AttackDelay: 0; AttackTime: 0; ShootDelay: 80; Power: 25; Speed: 1.0; Color: (X:0.4; Y:0.8; Z:0.4; W:1); BulletSize: 40; BulletLine: True; Player: True),
         (AttackDelay: 0; AttackTime: 0; ShootDelay: 4; Power: 200; Speed: 2.8; Color: (X:1; Y:1; Z:1; W:1); BulletSize: 60; BulletLine: False; Player: True),
         (AttackDelay: 0; AttackTime: 0; ShootDelay: 3000; Power: 5; Speed: 0.5; Color: (X:0.6; Y:0.2; Z:0.1; W:1); BulletSize: 30; BulletLine: True; Player: False),
         (AttackDelay: 0; AttackTime: 0; ShootDelay: 3000; Power: 8; Speed: 0.5; Color: (X:1.0; Y:0.2; Z:0.2; W:1); BulletSize: 15; BulletLine: False; Player: False),
         (AttackDelay: 3000; AttackTime: 1000; ShootDelay: 350; Power: 4.5; Speed: 0.5; Color: (X:1.0; Y:0.2; Z:1.0; W:1); BulletSize: 25; BulletLine: True; Player: False),
         (AttackDelay: 3000; AttackTime: 1000; ShootDelay: 250; Power: 3; Speed: 0.5; Color: (X:1.0; Y:1.0; Z:0.2; W:1); BulletSize: 25; BulletLine: True; Player: False),
         (AttackDelay: 3000; AttackTime: 1500; ShootDelay: 80; Power: 15; Speed: 0.5; Color: (X:1.0; Y:0.2; Z:0.2; W:1); BulletSize: 25; BulletLine: True; Player: False)
        );


type
  TWeapon = record
    private
      FWeapon     : TWeaponType;
      FAttackTime : LongInt;
      FShootTime  : LongInt;
      FFlag       : Boolean;
    public
      procedure SetWeapon(Weapon: TWeaponType);
      procedure Shoot(const Pos, Dir1, Dir2: TVec2f);
      procedure Upgrade;

      property ShootTime: LongInt read FShootTime write FShootTime;
  end;

  TWeaponEng = class
  constructor Create;
  destructor Destroy; override;
  private
    FSample: LongInt;
    FLaserTex : ITexture;
    FPlasmaTex : ITexture;
    FBullet   : array[1..120] of record
      Pos     : TVec2f;
      Dir     : TVec2f;
      Weapon  : TWeaponType;
      Enable  : Boolean;
    end;
  public
    procedure Restart;
    procedure AddBullet(const Dir, Pos: TVec2f; Weapon: TWeaponType);
    procedure OnUpdate(dt: LongInt);
    procedure OnRender;
  end;


implementation

uses
  UEnemy,
  UGameScene,
  Main;

constructor TWeaponEng.Create;
begin
  FSample := SQUALL_Sample_LoadFile('Media\laser.wav', 1, 0);
  ResMan.Load('Media\Laser.dds', FLaserTex);
  ResMan.Load('Media\Plasma.dds', FPlasmaTex);
end;

destructor TWeaponEng.Destroy;
begin
  SQUALL_Sample_Unload(FSample);
end;

procedure TWeaponEng.AddBullet(const Dir, Pos: TVec2f; Weapon: TWeaponType);
var
  i : Integer;
begin
  if WeaponParam[Weapon].Player then
    SQUALL_Channel_SetVolume(SQUALL_Sample_Play(FSample, 0, 0, 1), 80);
  for I := 1 to High(FBullet) do
    if not FBullet[i].Enable then
    begin
      FBullet[i].Pos := Pos;
      FBullet[i].Dir := Dir;
      FBullet[i].Weapon := Weapon;
      FBullet[i].Enable := True;
      Exit;
    end;
end;

procedure TWeaponEng.OnUpdate(dt: Integer);
var
  i,j : Integer;
  Pos1, Pos2 : TVec2f;
begin

  for I := 1 to High(FBullet) do
  with FBullet[i], WeaponParam[Weapon] do
    if Enable then
    begin
      Pos :=  Pos + Dir * Speed * dt;

      Pos1 := Pos - Dir * (BulletSize/2);
      Pos2 := Pos + Dir * (BulletSize/2);

      if Player then
      begin
        with Game.EnemyEng do
        for J := 1 to High(Enemies) do
        if (Enemies[j].Kind <> ekNone) and (Enemies[j].Dead <> True) then
          if LineVsCircle(Pos1, Pos2, Enemies[j].Pos, EnemyParam[Enemies[j].Kind].Size/2) then
          begin
            Hit(J, Weapon);
            Enable := False;
          end
      end else
        if LineVsCircle(Pos1, Pos2, Game.Player.Pos, Game.Player.Size/2) then
        begin
          Game.Player.Hit(Weapon);
          Enable := False;
        end;

      if (Pos.x < 0 - BulletSize) or (Pos.x > WorldSize + BulletSize) or
          (Pos.y < 0 - BulletSize) or  (Pos.y > Game.ScreenHeight + BulletSize) then
            Enable := False;
    end;
end;

procedure TWeaponEng.OnRender;
var
  i : Integer;
begin
  Render.BlendType := btAdd;
  Render2d.BatchBegin;
  for I := 1 to High(FBullet) do
  with FBullet[i], WeaponParam[Weapon] do
    if Enable then
    begin
      if BulletLine then
        Render2d.DrawSprite(FLaserTex.Frame, Pos.X- BulletSize/2 + Game.OffSet.x, Pos.Y - 4, BulletSize + Game.OffSet.y, 8, Color, -Dir.Angle(Vec2f(1,0)) * rad2deg )
      else
        Render2d.DrawSprite(FPlasmaTex.Frame, Pos.X- BulletSize/2 + Game.OffSet.x, Pos.Y - BulletSize/2+ Game.OffSet.y, BulletSize, BulletSize, Color, 0);
    end;
  Render2d.BatchEnd;
  Render.BlendType := btNormal;
end;

procedure TWeaponEng.Restart;
var
  i : Integer;
begin
  for I := 1 to High(FBullet) do
    FBullet[i].Enable := False;
end;

procedure TWeapon.SetWeapon(Weapon: TWeaponType);
begin
  FWeapon := Weapon;
  FAttackTime := Helpers.GetTime;
  FShootTime := Helpers.GetTime;
end;

procedure TWeapon.Shoot(const Pos, Dir1, Dir2: TVec2f);
begin
  if FWeapon = wtNone then
    Exit;

  if(Helpers.Time - FAttackTime >= WeaponParam[FWeapon].AttackDelay) then
  begin

    if(Helpers.Time - FShootTime >= WeaponParam[FWeapon].ShootDelay) then
    begin
      FFlag := not FFlag;
      case FWeapon of
        wtLaser1 : Game.WeaponEng.AddBullet(Vec2f(0,-1), Vec2f(Pos.x -10 + 20 * ord(FFlag), Pos.y-WeaponParam[FWeapon].BulletSize), FWeapon);
        wtLaser2 :
        begin
          Game.WeaponEng.AddBullet(Vec2f(0,-1), Vec2f(Pos.x-10, Pos.y-WeaponParam[FWeapon].BulletSize), FWeapon);
          Game.WeaponEng.AddBullet(Vec2f(0,-1), Vec2f(Pos.x+10, Pos.y-WeaponParam[FWeapon].BulletSize), FWeapon);
        end;
        wtLaser3 :
        begin
          Game.WeaponEng.AddBullet(Vec2f(0,-1), Vec2f(Pos.x-10, Pos.y-WeaponParam[FWeapon].BulletSize), FWeapon);
          Game.WeaponEng.AddBullet(Vec2f(0,-1), Vec2f(Pos.x+10, Pos.y-WeaponParam[FWeapon].BulletSize), FWeapon);

          Game.WeaponEng.AddBullet(Vec2f(-0.5,-0.5), Vec2f(Pos.x-20, Pos.y-WeaponParam[FWeapon].BulletSize), FWeapon);
          Game.WeaponEng.AddBullet(Vec2f(0.5,-0.5), Vec2f(Pos.x+20, Pos.y-WeaponParam[FWeapon].BulletSize), FWeapon);
        end;

        wtLaser4:
        begin
          Game.WeaponEng.AddBullet(Vec2f(0,-1), Vec2f(Pos.x-15, Pos.y-WeaponParam[FWeapon].BulletSize), FWeapon);
          Game.WeaponEng.AddBullet(Vec2f(0,-1), Vec2f(Pos.x-5, Pos.y-WeaponParam[FWeapon].BulletSize), FWeapon);
          Game.WeaponEng.AddBullet(Vec2f(0,-1), Vec2f(Pos.x+5, Pos.y-WeaponParam[FWeapon].BulletSize), FWeapon);
          Game.WeaponEng.AddBullet(Vec2f(0,-1), Vec2f(Pos.x+15, Pos.y-WeaponParam[FWeapon].BulletSize), FWeapon);
        end;
        wtEnemyLaser1 : Game.WeaponEng.AddBullet(Vec2f(0,1), Vec2f(Pos.x, Pos.y+WeaponParam[FWeapon].BulletSize), FWeapon);
        wtEnemyPlasma, wtEnemyLaserGun, wtEnemyLaserGun2: if Dir1.Dot(Dir2)>0 then  Game.WeaponEng.AddBullet(Dir1, Vec2f(Pos.x, Pos.y+WeaponParam[FWeapon].BulletSize), FWeapon);

        wtBossGun:
        begin
          Game.WeaponEng.AddBullet(Vec2f(0,1), Vec2f(Pos.x-10, Pos.y+WeaponParam[FWeapon].BulletSize+64), FWeapon);
          Game.WeaponEng.AddBullet(Vec2f(0,1), Vec2f(Pos.x+10, Pos.y+WeaponParam[FWeapon].BulletSize+64), FWeapon);

          Game.WeaponEng.AddBullet(Vec2f(-2,3).Normal, Vec2f(Pos.x-40, Pos.y+WeaponParam[FWeapon].BulletSize+48), FWeapon);
          Game.WeaponEng.AddBullet(Vec2f(2,3).Normal, Vec2f(Pos.x+40, Pos.y+WeaponParam[FWeapon].BulletSize+48), FWeapon);
            {
          Game.WeaponEng.AddBullet(Vec2f(0,-1), Vec2f(Pos.x+5, Pos.y-WeaponParam[FWeapon].BulletSize), FWeapon);
          Game.WeaponEng.AddBullet(Vec2f(0,-1), Vec2f(Pos.x+15, Pos.y-WeaponParam[FWeapon].BulletSize), FWeapon); }
        end;
      end;
     FShootTime := Helpers.Time;
    end;

    if (Helpers.Time - FAttackTime) >= WeaponParam[FWeapon].AttackDelay + WeaponParam[FWeapon].AttackTime then
      FAttackTime := Helpers.Time;

  end;
end;

procedure TWeapon.Upgrade;
begin
  Inc(FWeapon);
  if FWeapon = wtBFG then
  Dec(FWeapon);
end;



end.
