//==========================================================================================
//
//  uje_cathedral.gm
//
//  Who         When        What
//------------------------------------------------------------------------------------------
//  ^1[UJE]^3Niek   07 November 2020    Initial Script
//
//==========================================================================================
//

/****************************************************
Path mapping updated and script by Mateos
Correspondant WAY file size: -
Last update: 20th December 2020
****************************************************/

/*
 * TODO:
 * - Add DEFEND spots for Allies (aside Tank, that's already done);
 * - Axis plants the Side Door from the wrong side;
 * - Add cover spots;
 * - Manage cabinets;
 * - Write the spawn management functions;
 * - Test the waypoints!
 */

global Spawns =
{
    AXIS_SPAWN = 1,
    ALLIED_SPAWN = 2,
    CATHEDRAL = 3, // Default Allies, capturable until the Tank is through the Second Barrier
    ALLIED_CP = 4,
    AXIS_CP = 5,
    COURTYARD_SPAWN = 6, // Default Axis
};

global CPStatus =
{
    NEUTRAL = 0,
    AXIS = 1,
    ALLIES = 2,
};

global Map =
{
    Debug = 0, // Please set to zero before distributing your script

    // ************************************************************************

    cpStatus = CPStatus.NEUTRAL,

    // ************************************************************************

    Allied_Command_Post_Built = function( trigger )
    {
        Map.cpStatus = CPStatus.ALLIES;

        Util.MapDebugPrint( "Allied_Command_Post_Built", true );
    },

    Axis_Command_Post_Built = function( trigger )
    {
        Map.cpStatus = CPStatus.AXIS;

        Util.MapDebugPrint( "Axis_Command_Post_Built", true );
    },

    Allied_Command_Post_Destroyed = function( trigger )
    {
        Map.cpStatus = CPStatus.NEUTRAL;

        Util.MapDebugPrint( "Allied_Command_Post_Destroyed", true );
    },

    Axis_Command_Post_Destroyed = function( trigger )
    {
        Map.cpStatus = CPStatus.NEUTRAL;

        Util.MapDebugPrint( "Axis_Command_Post_Destroyed", true );
    },

    oldcityflag_Axis_Captured = function( trigger )
    {
        Util.MapDebugPrint( "oldcityflag_Axis_Captured", true );
    },

    oldcityflag_Allies_Captured = function( trigger )
    {
        Util.MapDebugPrint( "oldcityflag_Allies_Captured", true );
    },

    // ************************************************************************

    Tank_Past_First_Barrier = function( trigger )
    {
        TankDefenceManagement.SetArea( TankDefenceManagement.AreaList.SECOND_AREA );

        Util.MapDebugPrint( "Tank_Past_First_Barrier", true );
    },

    Tank_Past_Second_Barrier = function( trigger )
    {
        TankDefenceManagement.SetArea( TankDefenceManagement.AreaList.THIRD_AREA );

        SetAvailableMapGoals( TEAM.AXIS, false, "PLANT_side_door" );
        SetAvailableMapGoals( TEAM.AXIS, true, "PLANT_Last_Barrier" );

        SetAvailableMapGoals( TEAM.ALLIES, false, {
            ".*_Command_Post",
            "BUILD_side_door",
        });

        Util.MapDebugPrint( "Tank_Past_Second_Barrier", true );
    },

    Tank_Past_Third_Barrier = function( trigger )
    {
        TankDefenceManagement.SetArea( TankDefenceManagement.AreaList.FOURTH_AREA );

        Util.MapDebugPrint( "Tank_Past_Third_Barrier", true );
    },

    vehicle_at_location = function( trigger )
    {
        switch( Map.VehicleLocation )
        {
            case 1:
            {
                Map.Tank_Past_Second_Barrier();
            }

            case 2:
            {
                Map.Tank_Past_Third_Barrier();
            }
        }
    },
};

global OnMapLoad = function()
{
    // *** TRIGGERS ***

    // For spawn management
    OnTrigger( "^8Allied Command Post constructed. Charge speed increased!", Map.Allied_Command_Post_Built );
    OnTrigger( "^8Axis Command Post constructed. Charge speed increased!", Map.Axis_Command_Post_Built );
    OnTrigger( "^8Axis team has destroyed the Allied Command Post!", Map.Allied_Command_Post_Destroyed );
    OnTrigger( "^8Allied team has destroyed the Axis Command Post!", Map.Axis_Command_Post_Destroyed );
    OnTrigger( "^8Axis reclaim the Cathedral!", Map.oldcityflag_Axis_Captured );
    OnTrigger( "^8Allies capture the Cathedral!", Map.oldcityflag_Allies_Captured );

    // For Tank progress
    OnTrigger( "^8The Tank is past the first tank barrier!", Map.Tank_Past_First_Barrier );
    OnTrigger( "tank at location", Map.vehicle_at_location );
    OnTriggerRegion( AABB( 655.125, -1008.875, 17.125, 927.875, -751.125, 91.125 ), RegionTrigger.VehicleTrigger );
    OnTriggerRegion( AABB( -344.868, 168.161, 17.125, -275.399, 401.943, 91.125 ), RegionTrigger.VehicleTrigger );

    // ************************************************************************

    // *** GOALS ***
    Util.DisableGoal( ".*", true ); // All but routes

    Util.EnableGoal( ".*_Command_Post" );
    Util.EnableGoal( "CHECKPOINT_oldcityflag" );

    SetGoalPriority( "PLANT_Last_Barrier", 0.92 );
    SetGoalPriority( "PLANT_Tank_Barrier_1", 0.92 );
    SetGoalPriority( "BUILD_Tank", 0.91 ); // TODO: Axis bots still go for BUILD_Command_Post which is 0.90...
    Util.SetGoalPosition( -150, 385, 40, "PLANT_Last_Barrier" );

    SetAvailableMapGoals( TEAM.AXIS, true, {
        "BUILD_Tank",
        "ESCORT_tank",
        "PLANT_Second_Tank_Barrier",
        "PLANT_side_door",
        "PLANT_Tank_Barrier_1",
    });

    SetAvailableMapGoals( TEAM.ALLIES, true, {
        "BUILD_side_door",
        "BUILD_Tank_Barrier_1",
    });

    // DEFEND goals for Allies all along the Tank journey
    TankDefenceManagement.Start();

    // ************************************************************************

    Util.MapDebugPrint( "Omni-bot map script for " + GetMapName() + " executed." );
};

global OnBotJoin = function( bot )
{
    // TODO: Spawn management
};

global InitializeRoutes = function()
{
    MapRoutes =
    {
        CHECKPOINT_oldcityflag =
        {
        },
        BUILD_Command_Post =
        {
        },
        PLANT_Command_Post =
        {
        },
        PLANT_Second_Tank_Barrier =
        {
        },
    };
    Util.Routes(MapRoutes);
};

/** Make the Allied bots defend the Tank all along its journey to the Cathedral exit */
global TankDefenceManagement =
{
    /** Entity target name, to track its position */
    ENTITY_TARGET_NAME,

    /** Entity to track the position of */
    ENTITY,

    /** Radius around the entity to enable the goals from */
    RADIUS,

    /** List of the goals to manage */
    GOAL_LIST,

    /** Check interval */
    CHECK_INTERVAL,

    /** Team for which handle the goals availability */
    TEAM,

    /** Enity last position, to detect if it's either moving or not */
    entityPreviousPosition,

    // ************************************************************************

    AreaList =
    {
        FIRST_AREA = 1,
        SECOND_AREA = 2,
        THIRD_AREA = 3,
        FOURTH_AREA = 4,
    },

    entityCurrentArea,

    // ************************************************************************

    Start = function()
    {
        TankDefenceManagement.Init();
        thread( TankDefenceManagement.TrackMovement );
    },

    Init = function()
    {
        TankDefenceManagement.ENTITY_TARGET_NAME = "tank";
        TankDefenceManagement.ENTITY = GetEntityByName( TankDefenceManagement.ENTITY_TARGET_NAME );
        TankDefenceManagement.entityPreviousPosition = GetEntPosition( TankDefenceManagement.ENTITY );

        TankDefenceManagement.RADIUS = 768;

        TankDefenceManagement.GOAL_LIST = {};
        TankDefenceManagement.GOAL_LIST[ TankDefenceManagement.AreaList.FIRST_AREA  ] = Util.GoalTable( "CAMP_TankFirstArea.*"  );
        TankDefenceManagement.GOAL_LIST[ TankDefenceManagement.AreaList.SECOND_AREA ] = Util.GoalTable( "CAMP_TankSecondArea.*" );
        TankDefenceManagement.GOAL_LIST[ TankDefenceManagement.AreaList.THIRD_AREA  ] = Util.GoalTable( "CAMP_TankThirdArea.*"  );
        TankDefenceManagement.GOAL_LIST[ TankDefenceManagement.AreaList.FOURTH_AREA ] = Util.GoalTable( "CAMP_TankFourthArea.*" );

        TankDefenceManagement.CHECK_INTERVAL = 1.0;

        TankDefenceManagement.TEAM = TEAM.ALLIES;

        TankDefenceManagement.entityCurrentArea = TankDefenceManagement.AreaList.FIRST_AREA;
    },

    TrackMovement = function()
    {
        Util.MapDebugPrint( "Starting Tank defence management thread...", true );

        while ( true )
        {
            entityCurrentPosition = GetEntPosition( TankDefenceManagement.ENTITY );
            if ( entityCurrentPosition != TankDefenceManagement.entityPreviousPosition )
            {
                TankDefenceManagement.entityPreviousPosition = entityCurrentPosition;
                TankDefenceManagement.ManageGoals();
            }
            else
            {
                // For debug purposes
                foreach ( goal in TankDefenceManagement.GOAL_LIST[ TankDefenceManagement.entityCurrentArea ] )
                {
                    TankDefenceManagement.DrawDebugGoal( goal );
                }
            }

            // For debug purposes
            DrawRadius( entityCurrentPosition, TankDefenceManagement.RADIUS, COLOR.BLUE, TankDefenceManagement.CHECK_INTERVAL );

            sleep( TankDefenceManagement.CHECK_INTERVAL );
        }
    },

    ManageGoals = function()
    {
        foreach ( goal in TankDefenceManagement.GOAL_LIST[ TankDefenceManagement.entityCurrentArea ] )
        {
            shouldGoalBeEnabled = DistanceBetween( goal, TankDefenceManagement.ENTITY ) <= TankDefenceManagement.RADIUS;
            goal.SetAvailable( TankDefenceManagement.TEAM, shouldGoalBeEnabled );

            // For debug purposes
            TankDefenceManagement.DrawDebugGoal( goal );
        }
    },

    DrawDebugGoal = function( goal )
    {
        goalPosition = goal.GetPosition();
        goalEyePosition = Vector3( goalPosition.x, goalPosition.y, goalPosition.z + 64 );

        color;
        if ( goal.IsAvailable( TankDefenceManagement.TEAM ) )
        {
            color = COLOR.CYAN;
        }
        else
        {
            color = COLOR.ORANGE;
        }

        DrawDebugLine( goalPosition, goalEyePosition, color, TankDefenceManagement.CHECK_INTERVAL );
    },

    SetArea = function( area )
    {
        // Update the goal list pointer
        TankDefenceManagement.entityCurrentArea = area;

        // Disable all the goals from the area we've just left
        foreach ( goal in TankDefenceManagement.GOAL_LIST[ area - 1 ] )
        {
            goal.SetAvailable( TankDefenceManagement.TEAM, false );
        }
    },
};
