//-------------------------------------------------------------------
//
//  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.
//
//-------------------------------------------------------------------

///////////////////////////////////
//
// Mission 9 -- Tank battle
//
//

class CM9_AIController extends CBaseAIController, CTankBattleMission_Strings, CMissionMessageColors
{
  boolean m_Activated_A = false;
  boolean m_Activated_B = false;
  boolean m_Activated_C = false;
  boolean m_Activated_D = false;
  boolean m_Activated_E = false;
  boolean m_Activated_F = false;
  boolean m_Activated_G = false;

  void OnObjectEnterArea( int _NavPointIndex, string _NavPointName, string _ObjectID)
  {
    Core_LogMessage("GameObject <" + _ObjectID + "> entered activate area [" + _NavPointName + "]");

    if ( !m_Activated_A
      && _NavPointName == "NavPoint_Village_A"
      && ( _ObjectID == "Helicopter"
        || ( Core_IsStringStartsWith( _ObjectID, "Soviet")
          && !Core_IsStringStartsWith( _ObjectID, "SovietTank_A"))))
    {
      Core_LogMessage(" !!! Activate A");
      Core_BroadcastEvent( "OnStartAttack_A");
      m_Activated_A = true;

      Core_BroadcastEvent(
        "OnDisplayMessage",
        m_strAttackStarted, // "Attack started"
        m_BadNewsColor);
    }

    if ( !m_Activated_B
      && _NavPointName == "NavPoint_Village_B"
      && ( _ObjectID == "Helicopter"
        || ( Core_IsStringStartsWith( _ObjectID, "Soviet")
          && !Core_IsStringStartsWith( _ObjectID, "SovietTank_B"))))
    {
      Core_LogMessage(" !!! Activate B");
      Core_BroadcastEvent( "OnStartAttack_B");
      m_Activated_B = true;
    }

    if ( !m_Activated_C
      && _NavPointName == "NavPoint_Village_C"
      && ( _ObjectID == "Helicopter"
        || ( Core_IsStringStartsWith( _ObjectID, "Soviet")
          && !Core_IsStringStartsWith( _ObjectID, "SovietTank_C"))))
    {
      Core_LogMessage(" !!! Activate C");
      Core_BroadcastEvent( "OnStartAttack_C");
      m_Activated_C = true;
    }

    if ( !m_Activated_D
      && _NavPointName == "NavPoint_Village_D"
      && ( _ObjectID == "Helicopter"
        || ( Core_IsStringStartsWith( _ObjectID, "Soviet")
          && !Core_IsStringStartsWith( _ObjectID, "SovietTank_D"))))
    {
      Core_LogMessage(" !!! Activate D");
      Core_BroadcastEvent( "OnStartAttack_D");
      m_Activated_D = true;
    }

    if ( !m_Activated_E
      && _NavPointName == "NavPoint_Village_E"
      && ( (_ObjectID == "Helicopter")
        || ( Core_IsStringStartsWith( _ObjectID, "Soviet")
          && !Core_IsStringStartsWith( _ObjectID, "SovietTank_E"))))
    {
      Core_LogMessage(" !!! Activate E");
      Core_BroadcastEvent( "OnStartAttack_E");
      m_Activated_E = true;
    }

    if ( !m_Activated_F
      && _NavPointName == "NavPoint_F"
      && ( (_ObjectID == "Helicopter")
        || ( Core_IsStringStartsWith( _ObjectID, "Soviet")
          && !Core_IsStringStartsWith( _ObjectID, "SovietTank_F"))))
    {
      Core_LogMessage(" !!! Activate F");
      Core_BroadcastEvent( "OnStartAttack_F");
      m_Activated_F = true;
    }

    if ( !m_Activated_G
      && _NavPointName == "NavPoint_G"
      && ( (_ObjectID == "Helicopter")
        || ( Core_IsStringStartsWith( _ObjectID, "Soviet")
          && !Core_IsStringStartsWith( _ObjectID, "SovietTank_G"))))
    {
      Core_LogMessage(" !!! Activate G");
      Core_BroadcastEvent( "OnStartAttack_G");
      m_Activated_G = true;
    }
  }

  boolean m_TimerOn = false;
  int m_StartTime = 0;
  int m_LastMessageTime = 0;
  int m_MinutesSpent = 0;

  void Init( int _GameTime)
  {
    m_TimerOn = true;
    m_StartTime       = _GameTime;
    m_LastMessageTime = _GameTime - 60000;
  }

  void Update( int _GameTime)
  {
    if ( m_TimerOn && (_GameTime - m_LastMessageTime >= 60000))
    {
      m_MinutesSpent = m_MinutesSpent + 1;
      m_LastMessageTime = m_LastMessageTime + 60000;

      int MinutesLeft = 11 - m_MinutesSpent;

      if ( MinutesLeft == 0)
      {
        Core_BroadcastEvent( "OnStartAttack_A");
        m_TimerOn = false;

        Core_BroadcastEvent(
          "OnDisplayMessage",
          m_strAttackStarted,
          m_BadNewsColor);
      }
      else
      {
        Core_BroadcastEvent(
          "OnDisplayMessage",
          m_strMinutesLeft_start + MinutesLeft + m_strMinutesLeft_end,
          m_ReminderColor);
      }
    }
  }

  void OnStartAttack_A()
  {
    m_TimerOn     = false;
    m_Activated_A = true;
  }
}

class CM9_Attack extends CBaseAITask_BaseTask, CNavPointUser
{
  int      m_StartTime = 0;

  boolean  m_Wait              = true;  // initial state - wait before attack
  boolean  m_MoveToDislocation = false; // move to dislocation point
  boolean  m_Attack_A          = false; // final attack

  // delayed order
  boolean  m_Delayed_MoveToDislocation = false;
  boolean  m_Delayed_Attack_A          = false;
  int      m_GiveOrderTime             = 0;

  void Init()
  {
    m_StartTime = GetGameTime() + int(rand(0, 10000));
    SetFireStyle_NoFire();
  }

  void OnUpdate()
  {
    if ( m_Wait && (GetGameTime() >= m_StartTime + GetActivateDelay()))
    {
      // activate by timer
      //DoAttack();
    }

    if ( m_Delayed_MoveToDislocation && (GetGameTime() >= m_GiveOrderTime))
    {
      GiveOrder_MoveToDislocation();
    }

    if ( m_Delayed_Attack_A && (GetGameTime() >= m_GiveOrderTime))
    {
      GiveOrder_Attack_A();
    }
  }

  void ClearState()
  {
    m_Wait              = false;
    m_MoveToDislocation = false;
    m_Attack_A          = false;

    m_Delayed_MoveToDislocation = false;
    m_Delayed_Attack_A          = false;
    m_GiveOrderTime             = 0;
  }

  void DelayedGiveOrder_MoveToDislocation()
  {
    if ( !m_Delayed_MoveToDislocation)
    {
      m_Delayed_MoveToDislocation = true;
      m_Delayed_Attack_A          = false;

      m_GiveOrderTime = GetGameTime() + int(rand(0, 10000));
    }
  }

  void DelayedGiveOrder_Attack_A()
  {
    if ( !m_Delayed_Attack_A)
    {
      m_Delayed_MoveToDislocation = false;
      m_Delayed_Attack_A          = true;

      m_GiveOrderTime = GetGameTime() + int(rand(0, 10000));
    }
  }

  void GiveOrder_MoveToDislocation()
  {
    if ( !m_MoveToDislocation)
    {
      ClearState();
      m_MoveToDislocation = true;

      DoAction();
    }
  }

  void GiveOrder_Attack_A()
  {
    if ( !m_Attack_A)
    {
      ClearState();
      m_Attack_A = true;

      DoAction();
    }
  }

  string OnGetDebugInfo()
  {
    if ( m_Wait)
      return "= wait";
    if ( m_MoveToDislocation)
      return " = dislocating";
    if ( m_Attack_A)
      return " = Attack_A";
    
    return "";
  }

  void DoAction()
  {
    string NearestEnemy = GetTargetedEnemy();

    if ( NearestEnemy == "")
    {
      NearestEnemy = GetNearestEnemyUnit_Ranged(1000.0);
    };

    if ( NearestEnemy == "")
    {
      if ( m_MoveToDislocation)
      {
        vector DestinationPoint = GetMeetingPlace() + vector(rand(-150, 150), rand(-150, 150), 0);
        //Core_LogMessage("destination = " + DestinationPoint);
        SetStartDelay( 0, 5000);
        SetOrder_MoveTo( DestinationPoint, 30);
        SetFireStyle_Nearest();
      }
      else
      {
        vector DestinationPoint = GetBattleAPlace() + vector(rand(-150, 150), rand(-150, 150), 0);
        SetStartDelay( 0, 5000);
        SetOrder_MoveTo( DestinationPoint, 30);
        SetFireStyle_Nearest();
      }
    }
    else
    {
      SetAttackStyle_DirectMove( true);
      SetStartDelay( 0, 5000);
      SetOrder_Attack( NearestEnemy, 30.0, 120.0, 30.0);
      SetFireStyle_Enemy( NearestEnemy);
    };
  }

  void OnOrderedEnemyKilled()
  {
    SetFireStyle_Nearest();
    DoAction();
  }

  void OnEnemyTargeted()
  {
    if ( m_MoveToDislocation || m_Attack_A)
    {
      DoAction();
    }
  }

  void OnToDamage(
    float   _DamageRate,
    string  _TargetId,
    string  _SourceType,
    matrix  _SourcePlace)
  {
    if ( m_Wait)
    {
      Core_BroadcastEvent( "OnStartAttack_" + GetLocalBattleName());
    }
  }
}

class CM9_Attack_Soviet extends CM9_Attack
{
  vector GetBattleAPlace() { return GetNavPoint( "NavPoint_Village_A"); }

  void OnStartAttack_A()
  {
    DelayedGiveOrder_Attack_A();
  }
}

class CM9_Attack_Nazi extends CM9_Attack
{
  vector GetBattleAPlace() { return GetNavPoint( "NavPoint_Village_A"); }
  vector GetMeetingPlace() { return GetNavPoint( "NavPoint_Village_A"); }

  void OnStartAttack_A()
  {
    DelayedGiveOrder_Attack_A();
  }

  void DoAction()
  {
    string NearestEnemy = GetTargetedEnemy();

    if ( NearestEnemy == "")
    {
      if ( m_MoveToDislocation)
      {
        vector DestinationPoint = GetMeetingPlace() + vector(rand(-150, 150), rand(-150, 150), 0);
        //Core_LogMessage("destination = " + DestinationPoint);
        SetStartDelay( 0, 5000);
        SetOrder_MoveTo( DestinationPoint, 30);
        SetFireStyle_Nearest();
      }
      else
      {
        vector DestinationPoint = GetBattleAPlace() + vector(rand(-150, 150), rand(-150, 150), 0);
        SetStartDelay( 0, 5000);
        SetOrder_MoveTo( DestinationPoint, 30);
        SetFireStyle_Nearest();
      }
    }
    else
    {
      SetAttackStyle_DirectMove( true);
      SetStartDelay( 0, 5000);
      SetOrder_Attack( NearestEnemy, 30.0, 120.0, 30.0);
      SetFireStyle_Enemy( NearestEnemy);
    };
  }
}

class CM9_Soviet_A extends CM9_Attack_Soviet
{
  int GetActivateDelay() { return 50000; }
  vector GetMeetingPlace() { return GetNavPoint( "NavPoint_Village_A"); }
  string GetLocalBattleName() { return "A"; }
}

class CM9_Soviet_B extends CM9_Attack_Soviet
{
  int GetActivateDelay() { return 40000; }
  vector GetMeetingPlace() { return GetNavPoint( "NavPoint_Meeting_3"); }
  vector GetLocalBattleName() { return "B"; }

  void OnStartAttack_B()
  {
    DelayedGiveOrder_MoveToDislocation();
  }
}

class CM9_Soviet_C extends CM9_Attack_Soviet
{
  int GetActivateDelay() { return 30000; }
  vector GetMeetingPlace() { return GetNavPoint( "NavPoint_Meeting_2"); }
  vector GetLocalBattleName() { return "C"; }

  void OnStartAttack_C()
  {
    DelayedGiveOrder_MoveToDislocation();
  }
}

class CM9_Soviet_D extends CM9_Attack_Soviet
{
  int GetActivateDelay() { return 20000; }
  vector GetMeetingPlace() { return GetNavPoint( "NavPoint_Meeting_1"); }
  vector GetLocalBattleName() { return "D"; }

  void OnStartAttack_D()
  {
    DelayedGiveOrder_MoveToDislocation();
  }
}

class CM9_Soviet_E extends CM9_Attack_Soviet
{
  int GetActivateDelay() { return 10000; }
  vector GetMeetingPlace() { return GetNavPoint( "NavPoint_Meeting_1"); }
  vector GetLocalBattleName() { return "E"; }

  void OnStartAttack_E()
  {
    DelayedGiveOrder_MoveToDislocation();
  }
}

class CM9_Soviet_F extends CM9_Attack_Soviet
{
  int GetActivateDelay() { return 10000; }
  vector GetMeetingPlace() { return GetNavPoint( "NavPoint_Meeting_1"); }
  vector GetLocalBattleName() { return "F"; }

  void OnStartAttack_F()
  {
    DelayedGiveOrder_MoveToDislocation();
  }
}

class CM9_Soviet_G extends CM9_Attack_Soviet
{
  int GetActivateDelay() { return 10000; }
  vector GetMeetingPlace() { return GetNavPoint( "NavPoint_Meeting_2"); }
  vector GetLocalBattleName() { return "G"; }

  void OnStartAttack_G()
  {
    DelayedGiveOrder_MoveToDislocation();
  }
}


class CM9_Nazi_A extends CM9_Attack_Nazi
{
  int GetActivateDelay() { return 200000; }
  vector GetLocalBattleName() { return "A"; }

  void DoAction()
  {
    string NearestEnemy = GetTargetedEnemy();

    if ( NearestEnemy == "")
    {
      NearestEnemy = GetNearestEnemyUnit_Ranged(500.0);
    };

    if ( NearestEnemy == "")
    {
      // do nothing
    }
    else
    {
      SetAttackStyle_DirectMove( true);
      SetStartDelay( 0, 5000);
      SetOrder_Attack( NearestEnemy, 30.0, 120.0, 30.0);
      SetFireStyle_Enemy( NearestEnemy);
    };
  }
}

class CM9_Nazi_B extends CM9_Attack_Nazi
{
  int GetActivateDelay() { return 5*60000; }
  vector GetLocalBattleName() { return "B"; }

  void OnStartAttack_B()
  {
    DelayedGiveOrder_MoveToDislocation();
  }
}

class CM9_Nazi_C extends CM9_Attack_Nazi
{
  int GetActivateDelay() { return 5*60000; }
  vector GetLocalBattleName() { return "C"; }

  void OnStartAttack_C()
  {
    DelayedGiveOrder_MoveToDislocation();
  }
}

class CM9_Nazi_D extends CM9_Attack_Nazi
{
  int GetActivateDelay() { return 2*60000; }
  vector GetLocalBattleName() { return "D"; }

  void OnStartAttack_D()
  {
    DelayedGiveOrder_MoveToDislocation();
  }
}

class CM9_Nazi_E extends CM9_Attack_Nazi
{
  int GetActivateDelay() { return 30000; }
  vector GetLocalBattleName() { return "E"; }

  void OnStartAttack_E()
  {
    DelayedGiveOrder_MoveToDislocation();
  }
}

class CM9_Nazi_F extends CM9_Attack_Nazi
{
  int GetActivateDelay() { return 30000; }
  vector GetLocalBattleName() { return "F"; }

  void OnStartAttack_F()
  {
    DelayedGiveOrder_MoveToDislocation();
  }
}

class CM9_Nazi_G extends CM9_Attack_Nazi
{
  int GetActivateDelay() { return 30000; }
  vector GetLocalBattleName() { return "G"; }

  void OnStartAttack_G()
  {
    DelayedGiveOrder_MoveToDislocation();
  }
}

