
#include "scripts/common.txt"
#include "scripts/map/outpost/river.txt"
#include "scripts/map/outpost/gauntlet.txt"
#include "scripts/map/outpost/outpost.txt"
#include "scripts/map/outpost/riverside.txt"
#include "scripts/map/outpost/island.txt"

enum eTIDs
{
	TID_Startup,
	TID_LevelTick,

	TID_LevelWarp = 5,
	TID_SaveStation,

	TID_Forest_Birds = 9,
	TID_Forest_Button1_Event = 10,
	TID_Forest_Button1,
	TID_Forest_Emblem1_Button1,
	TID_Forest_Emblem1_Button2,
	TID_Forest_Emblem1_Button3,
	TID_Forest_Emblem1_Cave,
	TID_Forest_Ambush1,            // bridge between pillar button and button 1
	TID_Forest_Button2_Event = 20,
	TID_Forest_Button2,
	TID_Forest_Emblem2_Button1,
	TID_Forest_Emblem2_Button2,
	TID_Forest_Emblem2_Button3,
	TID_Forest_Emblem2_Cave,
	TID_Forest_Ambush2,            // bridge between button 1 and 2
	TID_Forest_Button3_Event = 30,
	TID_Forest_Button3,
	TID_Forest_Emblem3_Button1,
	TID_Forest_Emblem3_Button2,
	TID_Forest_Emblem3_Button3,
	TID_Forest_Emblem3_Cave,
	TID_Forest_Ambush3,            // bridge between button 2 and 3
	TID_Forest_Pillars_Event = 40,
	TID_Forest_Pillar_Actors,      // button, normal pillars
	TID_Forest_Pillar_Stupid,      // pillar with wrong initial sector
	TID_Forest_StupidPillarFixer,  // level script to fix stupid pillar sector height when reloading level
	TID_Forest_Ambush4 = 46,       // bridge between pillar button and button 3
	TID_Forest_SpiritBridge,

	TID_Cave_Land_Entrance = 50,
	TID_Cave_Land_Shortcut_Button,
	TID_Cave_Land_Shortcut_Gate,
	TID_Cave_Water_Shortcut1_Event = 60,
	TID_Cave_Water_Shortcut1_Button,
	TID_Cave_Water_Shortcut1_Post1,
	TID_Cave_Water_Shortcut1_Post2,
	TID_Cave_Water_Shortcut1_Post3,
	TID_Cave_Water_Shortcut2_Button,
	TID_Cave_Water_Shortcut2_Gate,
	TID_Cave_Gauntlet_Entrance_Button = 70,
	TID_Cave_Gauntlet_Entrance_Gates,

	TID_Cave_Gauntlet_Trap,
	TID_Cave_Gauntlet_Door1,
	TID_Cave_Gauntlet_Door2,
	TID_Cave_Gauntlet_Lava0 = 80,
	TID_Cave_Gauntlet_Lava1,
	TID_Cave_Gauntlet_Lava2,
	TID_Cave_Gauntlet_Lava3,
	TID_Cave_Gauntlet_Lava4,
	TID_Cave_Gauntlet_Lava5,
	TID_Cave_Gauntlet_Lava_Turn1 = TID_Cave_Gauntlet_Lava5,
	TID_Cave_Gauntlet_Lava6,
	TID_Cave_Gauntlet_Lava7,
	TID_Cave_Gauntlet_Lava8,
	TID_Cave_Gauntlet_Lava9,
	TID_Cave_Gauntlet_Lava_Turn2 = TID_Cave_Gauntlet_Lava9,
	TID_Cave_Gauntlet_Lava10,
	TID_Cave_Gauntlet_Lava11,
	TID_Cave_Gauntlet_Lava_End,
	TID_Cave_Gauntlet_Enemy1 = 100,
	TID_Cave_Gauntlet_Enemy2,
	TID_Cave_Gauntlet_Enemy3,
	TID_Cave_Gauntlet_Enemy4,
	TID_Cave_Gauntlet_Enemy5,
	TID_Cave_Gauntlet_Enemy_End,

	TID_Cave_Encampment_RadioChatter = 110,

	TID_Outpost_Commander = 150,
	TID_Outpost_Berzerker,
	TID_Outpost_Packrat,
	TID_Outpost_Sentinel,
	TID_Outpost_Guard,  // guy around the corner from back door, triggered along with sentinel
	TID_Outpost_Taxidermy,
	TID_Outpost_Lockdown_Begin = 175,
	TID_Outpost_Lockdown_Beginning,
	TID_Outpost_Button_Event,
	TID_Outpost_Button,
	TID_Outpost_Doors_Begin,
	TID_Outpost_Door_Back = TID_Outpost_Doors_Begin,
	TID_Outpost_Door_Barracks1,
	TID_Outpost_Door_Barracks2,
	TID_Outpost_Door_MessHall1,
	TID_Outpost_Door_MessHall2,
	TID_Outpost_Door_Overwatch,
	TID_Outpost_Door_Front_Inner,
	TID_Outpost_Door_Front_Outer,
	TID_Outpost_Doors_End,
	TID_Outpost_Elevator_Event_Lower_Near = 200,
	TID_Outpost_Elevator_Event_Lower_Far,
	TID_Outpost_Elevator_Event_Upper_Near,
	TID_Outpost_Elevator_Event_Upper_Far,
	TID_Outpost_Elevator_Event_Shaft,
	TID_Outpost_Elevator_Door_Lower = 210,
	TID_Outpost_Elevator_Door_Upper,
	TID_Outpost_Elevator_Actor,
	TID_Outpost_ComputerChatter = 220,

	TID_Overwatch_Sniper1 = 250,
	TID_Overwatch_Sniper_End = TID_Overwatch_Sniper1 + 5,
	TID_Overwatch_SniperFodder_Event = TID_Overwatch_Sniper_End,
	TID_Overwatch_SniperFodder1,
	TID_Overwatch_SniperFodder_End = TID_Overwatch_SniperFodder1 + 6,
	TID_Overwatch_Button1 = 270,
	TID_Overwatch_Gate1,
	TID_Overwatch_Button2,
	TID_Overwatch_Gate2,
	TID_Overwatch_Button3,
	TID_Overwatch_Gate3,
	TID_Overwatch_Button4,
	TID_Overwatch_Gate4,
	TID_Overwatch_Button5,
	TID_Overwatch_Gate5,

	TID_River_GuardPost_Gate_Button = 300,
	TID_River_GuardPost_Gate_Actors, // gate, guards
	TID_River_Trap1,
	TID_River_Trap2,

	TID_River_ForceField_Activate,
	TID_River_ForceField_Active,
	// 306 - 311
	TID_River_ForceField1,
	TID_River_ForceField_End = TID_River_ForceField1 + 6,

	// 312 - 316: first wave
	TID_River_Fight1_PurLin = TID_River_ForceField_End,
	TID_River_Fight1_Polearm1,
	TID_River_Fight1_Polearm2,
	TID_River_Fight1_Rifleman,
	TID_River_Fight1_Pistolero,

	// 317 - 321: triggered by fight1_purlin
	TID_River_Fight2_Commander,
	TID_River_Fight2_Polearm1,
	TID_River_Fight2_Polearm2,
	TID_River_Fight2_Polearm3,
	TID_River_Fight2_Polearm4,
	// 322 - 323: triggered by fight1_polearm1
	TID_River_Fight2_Knife1,
	TID_River_Fight2_Bludgeon1,
	// 324 - 325: triggered by fight1_polearm2
	TID_River_Fight2_Knife2,
	TID_River_Fight2_Axeman,
	// 326 - 327: triggered by fight1_rifleman
	TID_River_Fight2_Rifleman1,
	TID_River_Fight2_Rifleman2,
	// 328 - 329: triggered by fight1_pistolero
	TID_River_Fight2_Shotgunner1,
	TID_River_Fight2_Shotgunner2,

	// 330 - 343: triggered by fight2_commander
	TID_River_Fight3_Start,
	TID_River_Fight3_End = TID_River_Fight3_Start + 14,

	// 344 -349
	// TODO: remove these, and just use functions, since actor target TID can't trigger these
	TID_River_Fight1_PurLin_Death = TID_River_Fight3_End,
	TID_River_Fight1_Polearm1_Death,
	TID_River_Fight1_Polearm2_Death,
	TID_River_Fight1_Rifleman_Death,
	TID_River_Fight1_Pistolero_Death,
	TID_River_Fight2_Commander_Death,

	TID_RiverProbe_Slope_Begin = 350,
	TID_RiverProbe_Slope_End = TID_RiverProbe_Slope_Begin + 5,
	TID_RiverProbe_Waterfall_Begin = TID_RiverProbe_Slope_End,
	TID_RiverProbe_Waterfall_End = TID_RiverProbe_Waterfall_Begin + 3,

	TID_Island_Event = 400,
	TID_Island_Button,
	TID_Island_Plaque,
	TID_Island_Plaque_Event,
	TID_Island_Gate,
	TID_Island_Portal,
	TID_Island_Portal_Unhide,
	TID_Island_Portal_Teleport,
	// 410 - 426: outer edge of first level
	TID_Island_Cliff1_Start = 410,
	TID_Island_Cliff1_End = TID_Island_Cliff1_Start + 17,
	// 427 - 434: inner floor of first level
	TID_Island_Floor1_Start = 427,
	// 435 - 438: stairs
	TID_Island_Stairs = TID_Island_Floor1_Start + 8,
	TID_Island_Stair_Top1,
	TID_Island_Stair_Top2,
	TID_Island_Stair_Top3,
	TID_Island_Floor1_End,
	// 439 - 449: outer edge of second level
	TID_Island_Cliff2_Start = TID_Island_Floor1_End,
	TID_Island_Cliff2_End = TID_Island_Cliff2_Start + 11,
	// 450 - 451: inner floor of second level
	TID_Island_Floor2_Start = TID_Island_Cliff2_End,
	TID_Island_Floor2_End = TID_Island_Floor2_Start + 2,
	// dummy actors used to find sector indices
	TID_Island_Stair_Probe = 500, // top of the stairs
	TID_Island_Plaque_Probe,      // plaque event
	TID_Island_Gate_Probe1,       // top of left side of gate
	TID_Island_Gate_Probe2,       // top of right side of gate
	TID_Island_Rock_Peak_Start = 520,
	TID_Island_Rock_Peak_End = TID_Island_Rock_Peak_Start + 14,
	TID_Island_Rock_Body_Start = 540,
	TID_Island_Rock_Body_End = TID_Island_Rock_Body_Start + 5,

	TID_SecretMarker_Start = 1000,
	TID_SecretMarker_Forest = TID_SecretMarker_Start,
	TID_SecretMarker_SaveStation,
	TID_SecretMarker_Gauntlet,
	TID_SecretMarker_GuardPost,
	TID_SecretMarker_Toilet,
	TID_SecretMarker_Overwatch,
	TID_SecretMarker_End,

	TID_SecretEvent_GuardPost = 1100,
	TID_SecretItem_GuardPost_Start,
	TID_SecretItem_GuardPost_End = TID_SecretItem_GuardPost_Start + 6,
}

void PlayMusic( int track )
{
	kStr filename = "music/";
	if ( GetCvarB("g_altsoundtrack") )
		filename += "pc/";
	filename += "track";
	if ( track < 10 )
		filename += "0";
	Game.PlayMusic( filename+track+".ogg", true );
}

bool InCave()
{
	return World.GetAreaFlags( Player.Actor().AreaID() ) & AAF_DRAWSUN == 0;
}

bool InInnerCave()
{
	return World.GetAreaFlags( Player.Actor().AreaID() ) & AAF_DRAWSKY == 0;
}

bool InOuterCave()
{
	return World.GetAreaFlags( Player.Actor().AreaID() ) & (AAF_DRAWSUN | AAF_DRAWSKY) == AAF_DRAWSKY;
}

//==============================================================================
//
//    Level Startup
//
//==============================================================================

$script 0
{
	if ( GetGameVarB("g_newgame") )
	{
		GameVariables.SetValue( "chronoPieceFlags", "0" );
		GameVariables.SetValue( "hubPanelPieces1", "0" );
		GameVariables.SetValue( "hubPanelPieces2", "0" );
		GameVariables.SetValue( "hubPanelPieces3", "0" );
		GameVariables.SetValue( "hubPanelPieces4", "0" );
		GameVariables.SetValue( "hubPanelPieces5", "0" );
		GameVariables.SetValue( "hubPanelPieces6", "0" );
		GameVariables.SetValue( "hubPanelPieces7", "0" );
	}

	ActorFactory.Spawn( "TurokPlusSetup", 0,0,0, 0 );
	ActorFactory.Spawn( "TurokPlusTerminal", 1958.4f, 614.4f, -1331.2f, Math::Deg2Rad(90) );

	@Bug = Spawn( "DummyActor", Player.Actor().Origin() );//, 0, 3654 );
	@BugNoise = Spawn( "DummyActor", Player.Actor().Origin() );

	InitForestActors();
	InitRiver();
	InitWaterCave();
	InitGauntlet();
	InitOutpost();
//	InitEncampment();
	ToggleForceField( false );
	InitIsland();

	Game.CallDelayedMapScript( TID_LevelTick, instigator, 0 );
}

//==============================================================================
//
//    Level Tick
//
//==============================================================================

kPuppet@ P;
int area;
float height;
float slopePct;

$script 1
{
	@P = Player.Actor();
	area = P.AreaID();

	RiverTick();
	OutdoorParticles();
	UpdateBugs();

	WaterCaveTick();
	GauntletTick();
	OutpostTick();

	IslandTick();

	$restart;
}

void OutdoorParticles()
{
	if ( InInnerCave() )
		return;

	// Chimney Smoke
	if ( P.Origin().y > 1382 && P.Origin().y < 7186 && PlayLoop.Ticks() % 30 == 0 )
		Game.SpawnFx( "fx/ChimneySmoke.kfx", kVec3(222.72f,1589.76f,51.2f), -1 );

	// Waterfall Mist
	// not too far from the river (outpost-side)
	if ( P.Origin().x > 240 )
	{
		// close to the lower waterfall
		if ( P.Origin().y > 3840 )
			WaterfallMist( kVec3( 2846-400, 5512, -6387 ), kVec3( 4072+400, 5512, -6387 ), "fx/WaterfallMistHuge.kfx" );
		else
			WaterfallMist( WaterfallUpperLeft-kVec3(100,0,0), WaterfallUpperRight+kVec3(100,0,0), "fx/WaterfallMistBig.kfx", true );
	}
}

void WaterfallMist( kVec3&in v1, kVec3&in v2, const kStr&in particle, bool bRandom = false )
{
	if ( PlayLoop.Ticks() % 30 != 0 )
		return;
	float f;
	switch ( (PlayLoop.Ticks() / 30) % 4 )
	{
		case 0: f = 0;  break;
		case 1: f = bRandom? 0.5f  : 2.0f/3.0f;  break;
		case 2: f = bRandom? 0.25f : 1.0f/3.0f;  break;
		case 3: f = bRandom? 0.75f : 1;
	}

	if ( bRandom )
		f += Math::RandFloat() / 4;

	kVec3 v = v1;
	v.Lerp( v2, f );
	Game.SpawnFx( particle, v, -1 );
}

float BugZLimit = -205;
kActor@ Bug, BugNoise;
float BugPhaseDist, BugPhaseHeight, BugAngle;
float BugPause, BugScram = 2;
int8 BugDir = 1;

void UpdateBugs()
{
	if ( Bug is null || BugNoise is null )
		return;
	if ( Bug.IsStale() )
	{
		Sys.Warning( "bug is stale" );
		@Bug = null;
		return;
	}
	if ( BugNoise.IsStale() )
	{
		Sys.Warning( "bug noise is stale" );
		@BugNoise = null;
		return;
	}

		// no fly in the caves
	if ( InCave()
		// no fly in overwatch
		|| P.Origin().z > BugZLimit
		// no fly in the starting room (now handled by no sun flag)
//		|| (P.Origin().y > 8238 && P.Origin().x < -2798 && P.Origin().z < -1485)
		// no fly in forest secret area
		|| (P.Origin().y > 9585 && P.Origin().x >  -133)
		|| (P.Origin().x >  855 && P.Origin().y >  8392)
		|| (P.Origin().y > 6750 && P.Origin().z < -1741) )
	{
		if ( BugScram < 2 )
		{
			BugScram += GAME_DELTA_TIME;
			if ( BugScram >= 2 )
			{
				BugNoise.StopSound();
				return;
			}
		}
		else
			return;
	}
	else if ( BugScram > 0 )
		BugScram = Math::OLDMax( BugScram - GAME_DELTA_TIME, 0 );

	if ( BugPause > 0 )
	{
		BugPause -= GAME_DELTA_TIME;
		return;
	}

	bool bPause = (BugPhaseDist % (2*Math::pi)) < Math::pi/2;
	BugPhaseDist   += GAME_DELTA_TIME * (8 * Math::RandFloat());
	// just reached max distance
	if ( bPause && (BugPhaseDist % (2*Math::pi)) >= Math::pi/2 )
	{
		// pause for longer the further behind the player we are
//		BugPause = Math::RandFloat() * Math::Fabs( kAngle( BugAngle ) );
		BugPause = Math::RandFloat() + Math::Fabs( kAngle( BugAngle ) / Math::pi );
		BugNoise.StopSound();
		return;
	}
	BugPhaseHeight += GAME_DELTA_TIME * (8 * Math::RandFloat());
	BugAngle       += GAME_DELTA_TIME * (2 * Math::RandFloat()) * Math::pi * BugDir;
	if ( Math::Rand() < 500 )
		BugDir = -BugDir;

	float bugDist   = 300 + 200 * Math::Lerp( Math::Sin( BugPhaseDist ), 1, BugScram );
	float bugHeight = P.ViewHeight() * ( 1 + Math::Sin( BugPhaseHeight ) );
//	kVec3 v = P.Origin() + kVec3(0,bugDist,0)*kQuat(BugAngle,0,0,1) + kVec3(0,0,bugHeight);
	kVec3 v = P.Origin() + kVec3(0,bugDist,0)*kQuat(BugAngle+P.Yaw(),0,0,1) + kVec3(0,0,bugHeight);
	if ( P.GetWaterLevel() > WLT_INVALID && v.z < P.GetWaterHeight() )
		v.z = P.GetWaterHeight();
	Bug.Origin() = ClampToBounds( v );

	Bug.SpawnFx( "fx/Bug.kfx", Math::vecZero );

//	if ( bugDist < 150 && Math::Fabs( P.GetTurnYaw(Bug.Origin()) ) < Math::Deg2Rad(70) )
//	float angle = Math::Fabs( P.GetTurnYaw(Bug.Origin()) );
 	v = P.Origin();
 	v.z += P.ViewHeight();
 	kVec3 view = kVec3(0,1,0) * P.Rotation();
 	kVec3 toBug = Bug.Origin() - v;
// 	float angle = Math::Fabs( Math::ACos( Math::FClamp( view.Dot(toBug) / toBug.Unit(), -1, 1 ) ) );
	toBug.Normalize();
	float angle = 1 - toBug.Dot(view);
	v.Lerp( Bug.Origin(), 2 + angle*8 );
	BugNoise.Origin() = ClampToBounds( v );
	BugNoise.PlaySound( "sounds/shaders/BugBuzz.ksnd" );
}

//==============================================================================
//
//    Forest Events
//
//==============================================================================

void InitForestActors()
{
	// dim emblems that haven't been activated
	for ( int buttonTID = TID_Forest_Button1; buttonTID <= TID_Forest_Button3; buttonTID += TID_Forest_Button2 - TID_Forest_Button1 )
	{
		// check if this button has been activated, and dim all emblems if not
		kActor@ button = World.GetActorByTID( buttonTID );
		if ( button is null || !button.IsPersistentMarked() )
		{
			for ( int i=0; i<4; ++i )
			{
				kActor@ emblem = World.GetActorByTID( buttonTID + TID_Forest_Emblem1_Button1 - TID_Forest_Button1 + i );
				if ( emblem !is null )
					emblem.RenderModel().SetTexture( 0, 7 );
			}
		}
	}

	// fix one of the forest pillars thinking it's in an underground sector
	@StupidPillar = World.GetActorByTID( TID_Forest_Pillar_Stupid );
	if ( StupidPillar !is null )
	{
		// this is better at updating sector ID, so it sets it to the correct upper sector
		StupidPillar.SetPosition( StupidPillar.Origin() + kVec3(0,0,1000) );
		// this isn't as good about updating sector, so this moves it back into place while keeping the upper sector ID
		StupidPillar.Origin().z -= 1000;
		if ( StupidPillar.IsPersistentMarked() )
		{
			StupidPillarDelta = StupidPillar.FloorHeight() - StupidPillar.Origin().z;
			Game.CallDelayedMapScript( 43, Player.Actor().CastToActor(), GAME_DELTA_TIME );
		}
	}
}

kActor @StupidPillar;
float StupidPillarDelta;

// stupid pillar fixer
// pillar has already been raised; wait for it to move, then fix floor height
// since TurokFloorMover::OnRestore() initializes its initial floor height before we fix its sector
$script 43
{
	if ( StupidPillar is null || StupidPillar.IsStale() )
		return;

	if ( StupidPillar.Flags() & AF_DORMANT != 0 )
	{
		$restart;
		return;
	}

	World.ChangeSectorHeight( StupidPillar.SectorIndex(), StupidPillar.Origin().z + StupidPillarDelta );
}

void PressForestButton( int buttonTID )
{
	// make sure player is on the ground (not in the air above the button)
	// don't check AF_ENTEREDAREAEVENT, in case player is in the air when entering sector
	if ( !Player.Actor().OnGround() )
		return;

	// skip if this button is already pressed (prevents playing final sound repeatedly)
	kActor@ button = World.GetActorByTID( buttonTID );
	if ( button !is null && button.IsPersistentMarked() )
		return;

	// trigger the button
	World.TriggerActorsByTID( Player.Actor().CastToActor(), buttonTID );
	// give some time for the button to animate and play click sound
	delay( 0.2f );

	// light the emblems
	for ( int i=0; i<4; ++i )
	{
		kActor@ emblem = World.GetActorByTID( buttonTID + TID_Forest_Emblem1_Button1 - TID_Forest_Button1 + i );
		if ( emblem !is null )
			emblem.RenderModel().SetTexture( 0, 0 );
	}

	// open the gate if all 3 buttons are now pressed
	for ( int TID = TID_Forest_Button1; TID <= TID_Forest_Button3; TID += TID_Forest_Button2 - TID_Forest_Button1 )
	{
		kActor@ b = World.GetActorByTID( TID );
		if ( b is null || !b.IsPersistentMarked() )
			return;
	}

	button.PlaySoundWithLookupID( 206 ); // key plaque shwoom
	World.TriggerActorsByTID( Player.Actor().CastToActor(), TID_Cave_Land_Entrance );
}

// Button 1
$script 10
{
	PressForestButton( TID_Forest_Button1 );
}
// Button 2
$script 20
{
	PressForestButton( TID_Forest_Button2 );
}
// Button 3
$script 30
{
	PressForestButton( TID_Forest_Button3 );
}

// Forest Pillars
$script 40
{
	if ( !instigator.OnGround() )
		return;
	World.TriggerActorsByTID( instigator, TID_Forest_Pillar_Actors );
	World.TriggerActorsByTID( instigator, TID_Forest_Pillar_Stupid );
}

//==============================================================================
//
//    Cave Events
//
//==============================================================================

array<kActor@> WaterShortcutPosts(3);

void InitWaterCave()
{
	for ( int i=0; i<3; ++i )
		@WaterShortcutPosts[i] = World.GetActorByTID( TID_Cave_Water_Shortcut1_Post1 + i );
}

// first shortcut gates appear to block cave below when opened, because I left no vertical clearance
// so hide them when the player is down there
void WaterCaveTick()
{
	if ( P.Origin().z + P.ViewHeight() < -1946 && (P.Origin().y < 307 || P.Origin().y > 768 || P.Origin().x > 1003) )
	{
		for ( int i=0; i<3; ++i )
			if ( WaterShortcutPosts[i] !is null )
				WaterShortcutPosts[i].Flags() |= AF_HIDDEN;
	}
	else
	{
		for ( int i=0; i<3; ++i )
			if ( WaterShortcutPosts[i] !is null )
				WaterShortcutPosts[i].Flags() &= ~AF_HIDDEN;
	}
}

// Water Shortcut 1
$script 60
{
	if ( instigator.OnGround() )
		for ( int i=TID_Cave_Water_Shortcut1_Button; i<=TID_Cave_Water_Shortcut1_Post3; ++i )
			World.TriggerActorsByTID( instigator, i );
}

/*
void InitEncampment()
{
	for ( int i=TID_Cave_Encampment_Meat1; i<=TID_Cave_Encampment_Meat2; ++i )
	{
		kActor@ actor = World.GetActorByTID( i );
		if ( actor !is null && !actor.IsStale() )
			actor.RenderModel().SetModel( "models/misc_gibs01.bin", "" ); // 01: breast, 06: abdomen
	}
}
*/

//==============================================================================
//
//    Secrets
//
//==============================================================================

// forest spirit bridge
$script 47
{
	float xMin = 1036.799927f + 15;
	float xMax = 1344 - 15; // 1333.760010f - 15;
	float yMin = 7183.359863f + 15;
	float yMax = 8698.879883f - 15;
/*
	float y1 = instigator.Origin().y - 300;//200
	float y2 = instigator.Origin().y + 300;//400;

	if ( y1 < yMin )
	{
		y1 = yMin;
		y2 = y1 + 600;
	}
	else if ( y2 > yMax )
	{
		y2 = yMax;
		y1 = y2 - 600;
	}
*/
	for ( int i=0; i<24; ++i )
	{
		float r = Math::RandFloat() * 300;
		float a = Math::RandFloat() * Math::pi*2;
		kVec3 v = instigator.Origin() + kVec3(0,r,0) * kQuat( a, 0,0,1 );
		if ( v.y < yMin || v.y > yMax ) continue;
		if ( v.x < xMin || v.x > xMax ) continue;
		v.z = -2375.679932f;

//		kVec3 v(
//			Math::Lerp( 1036.799927f + 15, 1333.760010f - 15, Math::RandFloat() ),
//			Math::Lerp( y1, y2, Math::RandFloat() ),
//			-2375.679932f );

		// don't waste particles inside cliff
		if ( v.x < 1141 && v.y < 8381 ) continue;
		if ( v.x < 1172 && v.y < 8164 && v.y > 7624 ) continue;

		Game.SpawnFx( "fx/SpiritBridgeFar.kfx", v, -1 );
	}
}
