//
// 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:
//      Object Class For Iggy
//

// Smoke39: this file is unlikely to be altered by general purpose mods like Turok+ or weapon packs
// which makes it a good place to include code outside the level module (got this idea from BehemothProgrammer)

#include "scripts/common.txt"

//==============================================================================
//    Outskirts
//==============================================================================

float AmbientSoundRangeLimit = 2048*2048;
float AmbientSoundPrecision = GAME_SCALE*GAME_SCALE;

class AmbientSound : ScriptObject
{
	kActor@ self;
	kVec3 origin;

	AmbientSound( kActor@ a )
	{
		@self = a;
		origin = self.Origin();
	}
	void OnSpawn(){}

	// TODO: this could theoretically still fall asleep far from origin if player teleports away while out of audible range, but not so far that actor has moved back to origin
	// TODO: cap Origin() to keep in-bounds
	void OnTick()
	{
		// scale distance from player
		float hScale = self.Radius()-1;
		float vScale = self.Height() > 0 ? self.Height()-1 : hScale;
		kVec3 view = Camera.Active() ? Camera.origin : Player.Actor().Origin();
		kVec3 far = origin + (origin - view) * kVec3( hScale, hScale, vScale );
		// if we're outside audible range, move as close to origin as possible while staying out of
		// audible range, to prevent going to sleep so far away that we won't wake back up when
		// player gets back into range of origin
		if ( ( far - view ).UnitSq() > AmbientSoundRangeLimit )
		{
			kVec3 near = origin, mid;
			int i=0; // infinite loop guard, just in case I missed some edge case...
			do
			{
				mid = (far + near) / 2;
				if ( ( mid - view ).UnitSq() > AmbientSoundRangeLimit )
					far = mid;
				else
					near = mid;
			}
			while ( ( far - near ).UnitSq() > AmbientSoundPrecision && ++i < 100 );
		}
		self.Origin() = far;
	}
}

class UnBlocker : ScriptObject
{
	kActor@ self;
	UnBlocker( kActor@ a )
	{
		@self = a;
	}
	void OnSpawn() {}
	void OnRestore()
	{
		OnActivate();
	}
	void OnTick() {}

	void OnActivate()
	{
		if ( self.SectorIndex() < 0 ) return;
		World.FloodMatchingAreaFlags( self.SectorIndex(), AAF_BLOCK, false );
		self.MarkPersistentBit( false );
		self.Remove();
	}
}


/*
==============================================================
TurokIggy
==============================================================
*/

class TurokIggy : ScriptObject
{
    kActor @self;

    TurokIggy(kActor @actor)
    {
        @self = actor;
    }

    /*
    ==============================================================
    IntroCinematicEvent
    ==============================================================
    */

    void IntroCinematicEvent(kActor @instigator, const float w, const float x, const float y, const float z)
    {
        if(Game.GetCurrentMapID() != 46)
        {
            return;
        }

        PlayLoop.ChangeMap("levels/level43.map");
    }

    /*
    ==============================================================
    OnTick
    ==============================================================
    */

    void OnTick(void)
    {
    }

    /*
    ==============================================================
    OnBeginLevel
    ==============================================================
    */

    void OnBeginLevel(void)
    {
        self.AnimState().Set(anim_activate, 8.0f, 0);
    }

    /*
    ==============================================================
    OnSpawn
    ==============================================================
    */

    void OnSpawn(void)
    {
    }
};
