unit uPlayer;

interface

uses uGlobal, Math, Windows, uMap, VectorGeometry, VectorTypes, uWeapon, uObjects;

type
  TModelType = (mtBiped);
  TMoveDirection = (mdNone, mdForward, mdBackward, mdLeft, mdRight);
  TPlayer = class
  private
    LastMovement: set of TMoveDirection;
    procedure Move(Step: Double; Direction: TMoveDirection);
  public
    LegsModel, BodyModel: integer;
    Effects: array of integer;
    Sounds: array of integer;
    Position: array[0..2] of double;
    Rotation, WeaponRotationX, WeaponRotationY: double;
    Speed: Double;
    Health: Double;
    Weapons: array of TWeapon;
    ID: integer;
    Radius: Double;
    Movement: set of TMoveDirection;

    constructor Create(ModelType: TModelType);
    
    procedure Draw(Step: Double);
    procedure Shot(Step: Double; const Weapon: integer = -1);
  end;

var
  SStep, SSMGFire, WoodBullet: integer;

implementation

uses uGame;

var
  Sand, Smoke: integer;
  PrimaryID: integer = 0;

constructor TPlayer.Create(ModelType: TModelType);
var
  x: Integer;
begin
  ID:=PrimaryID; inc(PrimaryID);
  case ModelType of
    mtBiped:
      begin
        LegsModel:=call('model_legs_biped',[]);
        BodyModel:=call('model_body',[]);
      end;
  end;

  Speed:=60;
  Health:=100;
  Radius:=10;

  SetLength(Weapons, 2);
  for x := 0 to length(Weapons) - 1 do
    Weapons[x]:=TWeapon.Create(Self, wtMachineGun);

  Weapons[0].Position[2]:=6;
  Weapons[1].Position[2]:=-6;

  Weapons[0].Position[1]:=5;
  Weapons[1].Position[1]:=5;
  //Weapons[2].Position[1]:=-1;

  SetLength(Effects, 4);
  Effects[0]:=call('poaObjectID',[LegsModel,4]);
  Effects[1]:=call('poaObjectID',[LegsModel,8]);
  call('pfxAssign',['sand', Effects[0]]);
  call('pfxAssign',['sand', Effects[1]]);
  call('pfxInterval', [Effects[0],0.12]);
  call('pfxInterval', [Effects[1],0.12]);

  SetLength(Sounds, 2);
  Sounds[0]:=call('alObjectSound', [call('poaObjectID',[LegsModel,0]), SStep, 0]);
  Sounds[1]:=call('alObjectSound', [call('poaObjectID',[LegsModel,0]), SStep, 1]);

  LastMovement:=[];
  Move(0.1,mdForward);
  call('poaframestart', [LegsModel, 0]);
  call('poaframeend', [LegsModel, 0]);
  call('poaReset', [LegsModel]);

  call('poaframestart', [BodyModel, 0]);
  call('poaframeend', [BodyModel, 0]);
  call('poaReset', [BodyModel]);
        
  call('pfxEnabled', [Effects[0], false]);
  call('pfxEnabled', [Effects[1], false]);
end;

procedure TPlayer.Move(Step: Double; Direction: TMoveDirection);
var
  V, v2: TVector3F;
  I: Integer;
begin
  case Direction of
    mdNone:
      if LastMovement<>[] then
      begin
        call('poaframestart', [LegsModel, 0]);
        call('poaframeend', [LegsModel, 0]);
        call('poaReset', [LegsModel]);

        call('poaframestart', [BodyModel, 0]);
        call('poaframeend', [BodyModel, 0]);
        call('poaReset', [BodyModel]);
        
        call('pfxEnabled', [Effects[0], false]);
        call('pfxEnabled', [Effects[1], false]);
      end;
    mdForward:
      begin
        Position[0]:=Position[0]-cos(DegToRad(Rotation))*Step*Speed;
        Position[2]:=Position[2]+sin(DegToRad(Rotation))*Step*Speed;
      {  if (call('poaTime', [LegsModel])>1.9)AND(call('poaTime', [LegsModel])<2.1) then call('alPlay', [call('poaObjectID',[LegsModel,0]), true, Sounds[0]]);
        if (call('poaTime', [LegsModel])>0.0)AND(call('poaTime', [LegsModel])<0.15) then call('alPlay', [call('poaObjectID',[LegsModel,0]), true, Sounds[1]]);
       }
        if not(mdForward in LastMovement) then
        begin
          call('poaframestart', [LegsModel, 1]);
          call('poaframeend', [LegsModel, 4]);

          call('poaframestart', [BodyModel, 1]);
          call('poaframeend', [BodyModel, 4]);

          call('pfxEnabled', [Effects[0], true]);
          call('pfxEnabled', [Effects[1], true]);

       end;
      end;
    mdBackward:
      begin
        Position[0]:=Position[0]+cos(DegToRad(Rotation))*Step*Speed;
        Position[2]:=Position[2]-sin(DegToRad(Rotation))*Step*Speed;
       { if (call('poaTime', [LegsModel])>1.9)AND(call('poaTime', [LegsModel])<2.1) then call('alPlay', [call('poaObjectID',[LegsModel,0]), true, Sounds[0]]);
        if (call('poaTime', [LegsModel])>0.0)AND(call('poaTime', [LegsModel])<0.15) then call('alPlay', [call('poaObjectID',[LegsModel,0]), true, Sounds[1]]);
       }
        if not(mdBackward in LastMovement) then
        begin
          call('poaframestart', [LegsModel, 5]);
          call('poaframeend', [LegsModel, 8]);

          call('poaframestart', [BodyModel, 5]);
          call('poaframeend', [BodyModel, 8]);

          call('pfxEnabled', [Effects[0], true]);
          call('pfxEnabled', [Effects[1], true]);
        end;
      end;
    mdLeft:
      begin
        Rotation:=Rotation+Step*Speed*4;
       { if (call('poaTime', [LegsModel])>1.9)AND(call('poaTime', [LegsModel])<2.1) then call('alPlay', [call('poaObjectID',[LegsModel,0]), true, Sounds[0]]);
        if (call('poaTime', [LegsModel])>0.0)AND(call('poaTime', [LegsModel])<0.15) then call('alPlay', [call('poaObjectID',[LegsModel,0]), true, Sounds[1]]);
         }
        if not(mdLeft in LastMovement) then
        begin
          call('poaframestart', [LegsModel, 1]);
          call('poaframeend', [LegsModel, 4]);

          call('poaframestart', [BodyModel, 1]);
          call('poaframeend', [BodyModel, 4]);

          call('pfxEnabled', [Effects[0], true]);
          call('pfxEnabled', [Effects[1], true]);
        end;
      end;
    mdRight:
      begin
        Rotation:=Rotation-Step*Speed*4;
       { if (call('poaTime', [LegsModel])>1.9)AND(call('poaTime', [LegsModel])<2.1) then call('alPlay', [call('poaObjectID',[LegsModel,0]), true, Sounds[0]]);
        if (call('poaTime', [LegsModel])>0.0)AND(call('poaTime', [LegsModel])<0.15) then call('alPlay', [call('poaObjectID',[LegsModel,0]), true, Sounds[1]]);
         }
        if not(mdRight in LastMovement) then
        begin
          call('poaframestart', [LegsModel, 5]);
          call('poaframeend', [LegsModel, 8]);

          call('poaframestart', [BodyModel, 5]);
          call('poaframeend', [BodyModel, 8]);

          call('pfxEnabled', [Effects[0], true]);
          call('pfxEnabled', [Effects[1], true]);
        end;
      end;
  end;

  if LastMovement=[] then exit;

  Position[1]:=MapZ(Position[0], Position[2]);
  // Go back to map, bitch!
  if VectorLength(Position[0], 0, Position[2])>MapRadius then
  begin
    V:=Vector3fMake(Position[0], 0, Position[2]);
    NormalizeVector(V);
    ScaleVector(V,MapRadius);
    Position[0]:=V[0];
    Position[2]:=V[2];
  end;

  //Don't touch other players, bitch!
  for I := 0 to length(Players) - 1 do
  if Players[i].ID<>ID then
  begin
    V:=Vector3fMake(Position[0], 0, Position[2]);
    V2:=Vector3fMake(Players[i].Position[0], 0, Players[i].Position[2]);
    SubtractVector(v, v2);
    if VectorLength(v)<=Players[i].Radius then
    begin
      V:=Vector3fMake(Position[0], 0, Position[2]);
      V2:=V;
      SubtractVector(V2, Vector3fMake(Players[i].Position[0], 0, Players[i].Position[2]));
      NormalizeVector(V2);
      ScaleVector(V2,Step*Speed);
      AddVector(V, V2);
      Position[0]:=V[0];
      Position[2]:=V[2];
    end;
  end;

  //Don't touch map objects, bitch!
  for I := 0 to length(Objects) - 1 do
  begin
    V:=Vector3fMake(Position[0], 0, Position[2]);
    V2:=Vector3fMake(Objects[i].Position[0], 0, Objects[i].Position[2]);
    SubtractVector(v, v2);
    if VectorLength(v)<=Objects[i].Radius then
    begin
      if Objects[i].Reflect then
      begin
        V:=Vector3fMake(Position[0], 0, Position[2]);
        V2:=V;
        SubtractVector(V2, Vector3fMake(Objects[i].Position[0], 0, Objects[i].Position[2]));
        NormalizeVector(V2);
        ScaleVector(V2,Step*Speed);
        AddVector(V, V2);
        Position[0]:=V[0];
        Position[2]:=V[2];
      end;
      Objects[i].Collusion(i, ID);
    end
    else Objects[i].UnCollusion(i, ID);
  end;
end;

procedure TPlayer.Draw(Step: Double);
var
  x: Integer;
begin
  call('poaanimate', [LegsModel, Step*5]);
  call('poaanimate', [BodyModel, Step*5]);

  call('poaposition', [LegsModel, Position[0], Position[1], Position[2]]);
  call('poaRotation', [LegsModel, 0, Rotation, 0]);

  call('poaRotation', [BodyModel, 0, WeaponRotationX, 0]);
  call('poaposition', [BodyModel, Position[0], Position[1], Position[2]]);

  for x := 0 to length(Weapons) - 1 do
  begin
    call('glRotation', [call('poaObjectID',[Weapons[x].Model,0]), -WeaponRotationY+20, 0, 0]);
    call('glPosition', [call('poaObjectID', [Weapons[x].Model, 0]), Weapons[x].Position[0],Weapons[x].Position[1],Weapons[x].Position[2]]);
  end;

  if Movement=[] then Move(Step, mdNone) else
  begin
    if mdForward in Movement then Move(Step, mdForward);
    if mdBackward in Movement then Move(Step, mdBackward);
    if mdLeft in Movement then Move(Step, mdLeft);
    if mdRight in Movement then Move(Step, mdRight);
  end;
  LastMovement:=Movement;
end;

procedure TPlayer.Shot(Step: Double; const Weapon: integer = -1);
var
  I: Integer;
begin
  if Weapon=-1 then
  begin
    for I := 0 to length(weapons) - 1 do Weapons[i].Shot(Step);
  end
  else
    Weapons[Weapon].Shot(Step);

  call('pfxAcceleration', [Smoke, random(10)-5,random(30),random(10)-5]);
end;

end.
