//-------------------------------------------------------------------
//
//  This code is copyright 2001 by G5 Software.
//  Any unauthorized usage, either in part or in whole of this code
//  is strictly prohibited. Violators WILL be prosecuted to the
//  maximum extent allowed by law.
//
//-------------------------------------------------------------------

class CGermanParatrooperMesh
{
  string MeshFile = "Models/Paratrooper.mesh";
  string SkinFile = "Models/Paratrooper.skin";
}

class CParatrooperCollisionDetector
{
  float CollisionRadius = 10.0f;
}

class CGermanParatrooperStateControl extends CUnitLifeControl
{
  void CGermanParatrooperStateControl()
  {
    CUnitLifeControl(30.0);
    m_DestroyPause = 0.0;
    m_ExplosionId  = "";
  }

  void OnCollisionOccured(
      float _fPower
    )
  {
    // Destroy object
    Core_PostEventTo(
        SOID_MissionController,
        "DestroyGameObject",
        Core_GetIdentificator()
      );

    // register paratrooper landing
    Core_PostEventTo(
        SOID_MissionController,
        "ParatrooperLanded",
        Core_GetIdentificator()
      );
  }

  void DestroyComponent()
  {
    // Destroy object
    Core_PostEventTo(
        SOID_MissionController,
        "DestroyGameObject",
        Core_GetIdentificator()
      );

    // register paratrooper death
    Core_PostEventTo(
        SOID_MissionController,
        "ParatrooperKilled",
        Core_GetIdentificator()
      );
  }
}

class CGermanParatrooperGun extends CBaseWeaponDescriptor
{
  int    AmmoQuantity      = -1;
  float  BulletSpeed       = 600.0;
  float  FireDeviation     = 0.02;
  string LinkJointName     = "";

  string WeaponName        = "Gun";
  float  FireWeaponDelay   = 0.1;
  bool   IsAutotargeting   = false;
  int    AttachSlotNumber  = 1;

  string BulletPatternId   = "BULLETID_GermanParatrooperBullet";
  string EffectOnFire      = "EFFECTID_GunTowerGunFireEffect";   //#TMP
  string SoundOnFire       = "SOUNDID_GunTowerGunFireSound";     //#TMP
}

class CGermanParatrooperBehavior extends
    CBaseBehavior, CGermanParatrooperFireParameters
{
  bool CanMove = false;

  void CGermanParatrooperBehavior()
  {
    CBaseBehavior();
  }
}

class CGermanParatrooperFireParameters
{
  bool CanFire = true;

  int  FirePeriod        = 100; // ms
  int  FirePeriodRandAdd = 0; // ms
  int  ShootGunNum       = 1;

  bool BurstFire         = true;
  int  BurstTime         = 200; // ms
  int  BurstTimeRandAdd  = 0; // ms

  int  BurstDelay        = 5000; // ms
  int  BurstDelayRandAdd = 5000; // ms

// radar

  bool  HasRadar = true;

  float MaxRadarDistance = 1500; // m
  float MinRadarDistance = 30;   // m

  int   UpdateRadarPeriod        = 3000; // ms
  int   UpdateRadarPeriodRandAdd = 1000; // ms

  bool  FireFlying = true;
  bool  FireGround = true;
};

class CParatrooperFreeFallControl extends CWorldPhysics
{
  void CParatrooperFreeFallControl()
  {
    SetFreeFallSpeed(vector(0.0, 0.0, -5.0));
    SetFreeFallAccel(vector(0.0, 0.0,  0.0));
    SetFreeFallAngle(0.0, Math_PI * 2.0);
    EnableFreeFall(true);
  }
}

class CGermanParatrooper extends
  CBuilding, CUnitWithStateControl, CUnitWithBehavior, CArmedUnit
{
  void CGermanParatrooper()
  {
    InitializeModelAsStatic("CGermanParatrooperMesh");
    CUnitWithStateControl("CGermanParatrooperStateControl");
    CreateStaticWeapon("Weapon", "CGermanParatrooperGun");
    InitializeVehicleBehavior("CGermanParatrooperBehavior");

    CreateComponent("FreeFall", "FreeFallControl", "CParatrooperFreeFallControl");
    SetComponentSlaveObject("FreeFall", "Mesh");

    CreateComponent("CollisionDetector", "PointCollisionDetector", "CParatrooperCollisionDetector");
    SetComponentPositionable("CollisionDetector", "Mesh");

    Core_AddClassificator("German");
    Core_AddClassificator("Paratrooper");        // for cockpit identification
  }
}


class CGermanParatrooperGenerator
{
  array m_ParatrooperGroupName   = array();
  array m_ParatrooperGroupSize   = array();
  array m_ParatrooperLandedQty   = array();
  array m_ParatrooperKilledQty   = array();
  array m_ParatrooperTargetPos   = array();
  array m_ParatrooperTargetClass = array();
  array m_ParatrooperTargetName  = array();
  array m_ParatrooperSuccessQty  = array();

  void GenerateParatroopersGroup(
      string _BaseId,
      int    _Quantity,
      vector _Position,
      float  _Radius,
      float  _Height,
      string _TargetId,
      string _TargetClass,
      int    _SuccessQty
    )
  {
    for (int Paratrooper = 0; Paratrooper < _Quantity; Paratrooper = Paratrooper + 1)
    {
      final float Alpha  = rand(Math_PI);
      final float Radius = rand(0.0, _Radius);

      matrix Position = matrix(
          1.0, 0.0, 0.0, Core_GetVectorX(_Position) + Radius * sin(Alpha),
          0.0, 1.0, 0.0, Core_GetVectorY(_Position) + Radius * cos(Alpha),
          0.0, 0.0, 1.0, Core_GetVectorZ(_Position) + float(Paratrooper) * _Height / float(_Quantity),
          0.0, 0.0, 0.0, 1.0
        );

      Core_CallFunction(
          SOID_MissionController,
          "CreateComponent",
          _BaseId + "_" + Paratrooper,
          "GameObject",
          "CGermanParatrooper"
        );

      Core_CallFunction(
          SOID_MissionController,
          "SetComponentPosition",
          _BaseId + "_" + Paratrooper,
          Position
        );
    }

    m_ParatrooperGroupName.addElement(_BaseId);
    m_ParatrooperGroupSize.addElement(_Quantity);
    m_ParatrooperLandedQty.addElement(0);
    m_ParatrooperKilledQty.addElement(0);
    m_ParatrooperTargetPos.addElement(_Position);
    m_ParatrooperTargetClass.addElement(_TargetClass);
    m_ParatrooperTargetName.addElement(_TargetId);
    m_ParatrooperSuccessQty.addElement(_SuccessQty);
  }

  void GenerateParatroopers(
      string _BaseId,        // Name of group w/o number
      int    _Quantity,      // Groups amount
      int    _GroupSize,     // Paratroopers in group
      vector _Position,      // point of landing
      float  _Radius,        // Radius
      float  _Height,        // Hight
      string _TargetId,      // Name of unit after landing
      string _TargetClass,   // Class of unit after landing
      int    _SuccessQty,    // Min troopers amount for unit creating
      float  _DistrTime      // Distribution time for paratroopers creation
    )
  {
    for (int Group = 0; Group < _Quantity; Group = Group + 1)
    {
      final float Alpha  = rand(Math_PI);
      final float Radius = rand(0.0, _Radius);

      vector Position = vector(
          Core_GetVectorX(_Position) + Radius * sin(Alpha),
          Core_GetVectorY(_Position) + Radius * cos(Alpha),
          Core_GetVectorZ(_Position) + rand(_Height)
        );

      Core_ScheduleTask(
          Core_GetIdentificator(),
          OT_SendEventTo,
          float(Group) * _DistrTime / float(_Quantity),
          "GenerateParatroopersGroup",
          _BaseId + "_" + Group,
          _GroupSize,
          Position,
          _Radius / float(_Quantity),
          _Height,
          _TargetId + "_" + Group,
          _TargetClass,
          _SuccessQty
        );
    }
  }

  void ParatrooperLanded(
      string ParatrooperId
    )
  {
    for (int Group = 0; Group < m_ParatrooperGroupName.size(); Group = Group + 1)
    {
      if (Core_IsStringStartsWith(ParatrooperId, m_ParatrooperGroupName[Group]))
      {
        m_ParatrooperLandedQty[Group] = m_ParatrooperLandedQty[Group] + 1;
        CheckParatroopersGroup(Group);
        return;
      }
    }
  }

  void ParatrooperKilled(
      string ParatrooperId
    )
  {
    for (int Group = 0; Group < m_ParatrooperGroupName.size(); Group = Group + 1)
    {
      if (Core_IsStringStartsWith(ParatrooperId, m_ParatrooperGroupName[Group]))
      {
        m_ParatrooperKilledQty[Group] = m_ParatrooperKilledQty[Group] + 1;
        CheckParatroopersGroup(Group);
        return;
      }
    }
  }

  void CheckParatroopersGroup(
      int _Group
    )
  {
    if ((m_ParatrooperLandedQty[_Group] + m_ParatrooperKilledQty[_Group]) != m_ParatrooperGroupSize[_Group])
      return;

    if (m_ParatrooperLandedQty[_Group] < m_ParatrooperSuccessQty[_Group])
    {
      Core_CallFunction(
          SOID_MissionController,
          "OnParatrooperGroupLanded",
          false,
          m_ParatrooperTargetName[_Group]
        );

      return;
    }

    Core_CallFunction(
        SOID_MissionController,
        "CreateComponent",
        m_ParatrooperTargetName[_Group],
        "GameObject",
        m_ParatrooperTargetClass[_Group]
      );

    Core_CallFunction(
        SOID_MissionController,
        "SetComponentPosition",
        m_ParatrooperTargetName[_Group],
        matrix(
            1.0, 0.0, 0.0, Core_GetVectorX(m_ParatrooperTargetPos[_Group]),
            0.0, 1.0, 0.0, Core_GetVectorY(m_ParatrooperTargetPos[_Group]),
            0.0, 0.0, 1.0, Core_GetVectorZ(m_ParatrooperTargetPos[_Group]),
            0.0, 0.0, 0.0, 1.0
          )
      );

    Core_CallFunction(
        SOID_MissionController,
        "OnParatrooperGroupLanded",
        true,
        m_ParatrooperTargetName[_Group]
      );
  }
}

