//
// Copyright(C) 2014-2015 Samuel Villarreal
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// DESCRIPTION:
//      Level Script For Level48.map
//

#include "scripts/common.txt"

kActor @g_pHummer1 = null;
kActor @g_pHummer2 = null;
kActor @g_pHunter = null;

kVec3 g_vHunterTauntLocation;

/*
==============================================================
CheckPosition
==============================================================
*/

bool CheckPosition(const float dist, const float angle, kVec3 &out position)
{
    kActor @actor = Player.Actor().CastToActor();
    float ang = actor.Yaw() + angle;
    
    position.x = actor.Origin().x + Math::Sin(ang) * dist;
    position.y = actor.Origin().y + Math::Cos(ang) * dist;
    position.z = actor.Origin().z;
    
    return actor.CheckPosition(position);
}

/*
==============================================================
SpawnHummer
==============================================================
*/

void SpawnHummer(kActor @actor)
{
    actor.Flags() &= ~(AF_HIDDEN|AF_DISABLED);
    actor.ClipFlags() |= CF_DROPOFF;
    actor.ClipFlags() &= ~(CF_NOENTERWATER|CF_NOEXITWATER);
    
    actor.AnimState().Set(anim_aiTeleportIn, 4.0f, ANF_ROOTMOTION);
}

/*
==============================================================
OpenDam
==============================================================
*/

void OpenDam(kActor @instigator)
{
    kActor @pForceField;
    kActor @pKey;
    
    for(int i = 0; i < 4; ++i)
    {
        kActor @waterGate = World.GetActorByTID(611 + i);
        kActor @waterFall = World.GetActorByTID(11 + i);
        
        waterFall.Flags() &= ~AF_HIDDEN;
        waterGate.AnimState().Set(anim_trapActivate, 96.0f, 0);
    }
    
    World.TriggerActorsByTID(instigator, 50);
    World.TriggerActorsByTID(instigator, 51);
    
    World.FloodFillAreaFlags(kVec3(-17.5f*GAME_SCALE, 0, 0), AAF_BLOCK, false);
    @pForceField = World.GetActorByTID(150);
    
    @pKey = World.GetActorByTID(1);
    pKey.Origin().x = -(0.6f*GAME_SCALE);
    pKey.Origin().y = 0;
    
    if(!(pForceField is null))
    {
        pForceField.Remove();
    }
}

/*
==============================================================
Script 0
==============================================================
*/

$script 0
{
    int state, state2, state3;
    
    GameVariables.GetInt("longHunterState", state);
    GameVariables.GetInt("hummer1State", state2);
    GameVariables.GetInt("hummer2State", state3);
    
    if(state == LHGS_NEW)
    {
        Game.CallDelayedMapScript(1, instigator, 0.0f); //Update Check to start battle
    }
    
    @g_pHummer1 = World.GetActorByTID(1140);
    @g_pHummer2 = World.GetActorByTID(1141);
    
    @g_pHunter = World.GetActorByTID(400);
    
	
    if (state2 == HGS_ENTERED_ARENA)
    {
		Game.CallDelayedMapScript(2, instigator, 0.0f); //Update Hummer 1 Health Check
    }
    if (state3 == HGS_ENTERED_ARENA)
    {
		Game.CallDelayedMapScript(7, instigator, 0.0f); //Update Hummer 2 Health Check
    }
    
    if(state == LHGS_INCOMBAT)
    {
        Game.CallDelayedMapScript(8, instigator, 0); //Update Hunter Health Check
    }
    
    if(state != LHGS_DEAD)
    {
        for(int i = 0; i < 4; ++i)
        {
            kActor @waterFall = World.GetActorByTID(11 + i);
            waterFall.Flags() |= AF_HIDDEN;
        }
    }
    else
    {
        kActor @pKey;
        
        OpenDam(instigator);
        
        g_pHunter.ImpactType() = IT_FLESH_HUMAN;
        
        @pKey = World.GetActorByTID(1);
        pKey.Origin().z = -(GAME_SCALE*6.06f);
    }
}

/*
==============================================================
Update Check to start battle
==============================================================
*/

$script 1
{
    kActor @actor = Player.Actor().CastToActor();
    kVec3 position;
    
    if(actor.OnGround())
    {
        float x = actor.Origin().x;
        float y = actor.Origin().y;
        float dist = (30*GAME_SCALE);
        
        if(x * x + y * y < (dist*dist))
        {
            if( CheckPosition(15*GAME_SCALE, Math::Deg2Rad(180.0f), position) ||
                CheckPosition(15*GAME_SCALE, Math::Deg2Rad( 90.0f), position) ||
                CheckPosition(15*GAME_SCALE, Math::Deg2Rad(-90.0f), position))
            {
                g_vHunterTauntLocation = position;
                
                Game.CallDelayedMapScript(3, instigator, 0.0f); //Start Battle Cinematic
                
                Camera.origin = actor.Origin();
                Camera.origin.z += (4*GAME_SCALE);
                
                Camera.SetEyeView(Camera.origin);
                
                Camera.yaw = (g_vHunterTauntLocation - actor.Origin()).ToYaw();
                Camera.pitch = 0;
                Camera.roll = 0;
                
                Camera.StartCinematic();
                Camera.fov = 74.0f;
                return;
            }
        }
    }
    
    delay(0.1f);
    $restart;
}

/*
==============================================================
Update Hummer 1 Health Check
==============================================================
*/

$script 2
{
    if(g_pHummer1.Health() <= 0)
    {
		if(g_pHummer2.Health() <= 0)
		{
			PlayLoop.TagActorForBossBar(g_pHunter);
			g_pHunter.ImpactType() = IT_FLESH_HUMAN;
			Game.CallDelayedMapScript(8, instigator, 0); //Update Hunter Health Check
		} else {
			PlayLoop.TagActorForBossBar(g_pHummer2);
		}
        return;
    }
    
    delay(0.1f);
    $restart;
}

/*
==============================================================
Start Battle Cinematic
==============================================================
*/

$script 3
{
    if(Camera.CinematicState() == 2)
    {
        g_pHunter.SetPosition(kVec3(g_vHunterTauntLocation.x, g_vHunterTauntLocation.y, 0));
        g_pHunter.Origin().z = g_pHunter.FloorHeight();
        g_pHunter.Yaw() = (Player.Actor().Origin() - g_pHunter.Origin()).ToYaw();
        
        g_pHunter.AnimState().Set(anim_longHunterTaunt, 4.0f, ANF_ROOTMOTION);
        
        Game.CallDelayedMapScript(4, instigator, 3.6f); //Look at Hummer Cinematic
        
        delay(1.35f);
        g_pHunter.PlaySound("sounds/shaders/longhunter_taunt_1.ksnd");
        return;
    }
    
    $restart;
}

/*
==============================================================
Look at Hummer Cinematic
==============================================================
*/

$script 4
{
    Camera.SetLookAtActor(g_pHummer1);
    
    SpawnHummer(g_pHummer1);
	SpawnHummer(g_pHummer2);
    //PlayLoop.TagActorForBossBar(g_pHummer2);
	Game.CallDelayedMapScript(2, instigator, 0.0f); //Update Hummer 1 Health Check
	Game.CallDelayedMapScript(7, instigator, 0.0f); //Update Hummer 2 Health Check
		
    //Game.CallDelayedMapScript(2, instigator, 0.0f);
    
    Camera.origin = g_vHunterTauntLocation;
    Camera.origin.z += (6*GAME_SCALE);
    
    Camera.SetEyeView(Camera.origin);
    
    Game.CallDelayedMapScript(6, instigator, 2.5f); //stop cinematic/tag hummer1
}

/*
==============================================================
Not used
==============================================================
*/

$script 5
{
	PlayLoop.RemoveBossActor();
    PlayLoop.TagActorForBossBar(instigator);
}

/*
==============================================================
stop cinematic/tag hummer1
==============================================================
*/

$script 6
{
    Camera.StopCinematic();
    PlayLoop.TagActorForBossBar(g_pHummer1);
}

/*
==============================================================
Update Hummer 2 Health Check
==============================================================
*/

$script 7
{
    if(g_pHummer2.Health() <= 0)
    {
		if(g_pHummer1.Health() <= 0)
		{
			PlayLoop.TagActorForBossBar(g_pHunter);
			g_pHunter.ImpactType() = IT_FLESH_HUMAN;
			Game.CallDelayedMapScript(8, instigator, 0); //Update Hunter Health Check
		} else {
			PlayLoop.TagActorForBossBar(g_pHummer1);
		}
        return;
    }
    
    delay(0.1f);
    $restart;
}

/*
==============================================================
Update Hunter Health Check
==============================================================
*/

$script 8
{
    if(g_pHunter.Health() <= 0)
    {
        kActor @pItem;
        
        Game.CallDelayedMapScript(9, instigator, 0); //Rotate around dead hunter
        Game.CallDelayedMapScript(10, instigator, 7.0f); //End Battle
        
        delay(0.35f);
        g_pHunter.AnimState().Set(anim_aiDeathStand, 4.0f, ANF_ROOTMOTION);
        g_pHunter.ModelVariation() = 1;
        
        @pItem = ActorFactory.Spawn("Wpn_PulseRifle",
            g_pHunter.Origin().x, g_pHunter.Origin().y, g_pHunter.Origin().z,
            0, g_pHunter.SectorIndex());
            
        pItem.Scale() = kVec3(0.35f, 0.35f, 0.35f);
        
        delay(11.25f);
        Player.Victory();
        return;
    }
    
    $restart;
}

/*
==============================================================
Rotate around dead hunter
==============================================================
*/

$script 9
{
    Camera.StartCinematic(CMF_LOCK_PLAYER|CMF_UNLOCK_PLAYER_ON_FINISH|CMF_SHOW_HIDDEN_OBJECTS);
    PlayLoop.RemoveBossActor();
    
    Camera.SetLookAtActor(g_pHunter);
    Camera.fov = 74.0f;
    
    Camera.SetFinalView(0);
    Camera.SetRotationTrack(0,
                            Math::Deg2Rad(0.0f),    // start angle
                            Math::Deg2Rad(160.0f),  // dest angle
                            7*GAME_SCALE,           // start distance
                            8*GAME_SCALE,           // dest distance
                            8*GAME_SCALE,           // start height
                            2*GAME_SCALE,           // dest height
                            5*GAME_SCALE,           // start look at height
                            3*GAME_SCALE);          // dest look at height
                                       
    Camera.AutoPlayRotationTrack(0, 3.33f, CMLT_COSINE);
}

/*
==============================================================
End Battle 
==============================================================
*/

$script 10
{
    kActor @pKey;
    
    Game.HaltMapScript(9);
    
    Camera.ClearLookAtActor();
    Camera.ClearViewTracks();
    Camera.SetFinalView(0);
    
    Camera.SetEyeView(kVec3(50*GAME_SCALE, 50*GAME_SCALE, 10*GAME_SCALE));
    Camera.SetFocusView(kVec3(0, 0, 0));
    
    OpenDam(instigator);
    
    @pKey = World.GetActorByTID(1);
    delay(4.6f);
    
    pKey.Origin().z += GAME_SCALE;
}
