//各種機能取り込み
#include_function ".\System\ResultSystem.txt"
#include_function ".\System\TitleSystem.txt"
#include_function ".\System\HiScoreSystem.txt"
#include_function ".\System\SpellSystem.txt"
#include_function ".\System\PlayDataSystem.txt"
#include_function ".\System\BackGroundSystem.txt"
#include_function ".\System\UserScoreSystem.txt"
#include_function ".\System\DrawSystem.txt"
#include_function ".\System\ConfigSystem.txt"

/**
 * ゲーム開始処理
 */
task StartGame(){
	//残機設定等
	ExpertEx( false, 9, 3 );
	
	//念のため1F待つ
	yield;
	
	//リプレイかどうか判断
	if( IsReplay() ){
		isReplayData = true;
	}else{
		isReplayData = false;
	}
	
	//共通データ作成
	CreateOFTCommonData();
	
	//セーブデータを読み込む設定になっている場合のみ読み込む
	if( IsLoadFile ){
		//セーブデータを読み込む
		if( !isReplayData ){
			//セーブファイルから読み込む
			LoadCommonDataEx( "OFT_Save", SaveFilePath );
		}else{
			//リプレイファイルから読み込む
			//TODO:リプレイからの読み込み対応
			LoadCommonDataEx( "OFT_Save", SaveFilePath );
			//LoadCommonDataFromReplayFileEx( "OFT_Save" );
			//LoadCommonDataFromReplayFile();
		}
		
		//コンフィグデータを読み込む
		LoadCommonDataEx( "OFT_Config", ConfigFilePath );
	}
	
	//素材の読み込み
	LoadMaterial();
	
	//レートシステム無効化
	SetRateScoreSystemEnable( false );
	//デフォルトステータス無効化
	SetDefaultStatusVisible( false );
	
	//スコアエクステンドタスク起動
	ScoreExtend();
	
	//オーバーエクステンドタスク起動
	OverExtend();
	
	//スコア値管理タスク起動
	ScorePointControlTask();
	
	//独自スコアシステム起動
	UserScoreTask();
	
	//フレーム内の要素描画タスク起動
	FrameDrawTask();
	
	//グレイズチャージ
	GrazeTask();
	
	//アイテム作成タスク開始
	ItemTask();
	
	//ゲージ描画タスク開始
	DrawGauge();
	
	//背景制御タスク開始
	BackGroundControl();
	
	//プレイ時間管理タスク起動
	PlayTimeTask();
	
	//タイトル開始
	Title();
}

/**
 * ゲーム終了処理
 */
task EndGame(){
	//ハイスコアの記録
	if( State != State_Title ){
		let player = GetCommonDataDefaultEx( "OFT", "Player", "" );
		let difficult = GetCommonDataDefaultEx( "OFT", "Difficult", "" );
		SetHiScore( player, difficult, score1, score2, score3 );
	}
	
	//プレイ時間の記録
	if( IsLoadFile ){
		SavePlayTime();
	}
	
	//共通データのセーブ
	SaveOFTCommonData();
	
	//共通データの削除
	DeleteOFTCommonData();
	
	//素材の削除
	UnLoadMaterial();
	
	//リプレイ用にスコアの億の数値を増やす
	AddScore( score1 * ( scoreexp / 10 ) + truncate( score2 / 10 ) );
}

/**
 * 描画処理
 */
function GameDrawLoop(){
	alternative( State )
		case( State_Title ){
			//タイトル画面
			TitleDraw();
		}
}

/**
 * 共通データ空間を作成する
 */
function CreateOFTCommonData(){
	//通常エリア
	CreateCommonDataArea( "OFT" );
	//一時使用エリア
	CreateCommonDataArea( "OFT_tmp" );
	//セーブ用エリア
	CreateCommonDataArea( "OFT_Save" );
	//コンフィグ用エリア
	CreateCommonDataArea( "OFT_Config" );
	
	//リプレイかどうか
	SetCommonDataEx( "OFT", "IsReplay", isReplayData );
	//プレイヤー
	SetCommonDataEx( "OFT", "Player", "" );
	//難易度
	SetCommonDataEx( "OFT", "Difficult", "" );
	//ミス回数
	SetCommonDataEx( "OFT", "MissNum", 0 );
	//ボム回数
	SetCommonDataEx( "OFT", "BombNum", 0 );
	//スペル取得枚数
	SetCommonDataEx( "OFT", "GetSpellNum", 0 );
	//シールドゲージ
	SetCommonDataEx( "OFT", "ShieldGauge", ShieldGauge_Max );
	//チャージゲージ
	SetCommonDataEx( "OFT", "ChargeGauge", 0 );
	//現在チャージ数
	SetCommonDataEx( "OFT", "NowChargeCount", 0 );
	//最大チャージ数
	SetCommonDataEx( "OFT", "MaxChargeCount", 0 );
	//ボムエクステンド値
	SetCommonDataEx( "OFT", "BombExtendPoint", 0 );
	//ボムエクステンドノルマ値
	SetCommonDataEx( "OFT", "BombExtendNormaPoint", 0 );
	//ボムエクステンドシグナル
	SetCommonDataEx( "OFT", "BombExtendSignal", false );
	//スコア値
	SetCommonDataEx( "OFT", "ScorePoint", 1 );
	//アイテム回収フラグ
	SetCommonDataEx( "OFT", "CollectUserItem", false );
	//アイテム作成用配列
	SetCommonDataEx( "OFT", "Item", [] );
	
	//セーブデータを読み込まない設定になっている場合のみデータ作成
	if( !IsLoadFile ){
		//ハイスコアデータ作成
		CreateHiScoreDataArea();
		
		//スペルデータ作成
		CreateSpellDataArea();
		
		//プレイデータ作成
		CreatePlayDataArea();
		
		//コンフィグデータ作成
		CreateConfigDataArea();
	}
}

/**
 * 共通データ空間を削除する
 */
function DeleteOFTCommonData(){
	//通常エリア
	ClearCommonDataEx( "OFT" );
	
	//セーブ用エリア
	ClearCommonDataEx( "OFT_Save" );
	
	//コンフィグ用エリア
	ClearCommonDataEx( "OFT_Config" );
	
	//一時使用エリア
	ClearCommonDataEx( "OFT_tmp" );
}

/**
 * 共通データ空間をセーブする
 */
function SaveOFTCommonData(){
	if( !isReplayData ){
		//セーブファイルに保存する
		SaveCommonDataEx( "OFT_Save", SaveFilePath );
		//リプレイファイルに保存する
		//SaveCommonDataInReplayFileEx( "OFT_Save" );
		//SaveCommonDataInReplayFile();
		
		//コンフィグを保存する
		SaveCommonDataEx( "OFT_Config", ConfigFilePath );
	}else{
		//リプレイ再生中は何もしない
	}
}


/**
 * BGMの停止・再生を行う
 * 
 * @param {String} prevBGM 停止するBGMのファイルパス
 * @param {String} nextBGM 再生するBGMのファイルパス
 */
task ChangeBGM( prevBGM, nextBGM ){
	FadeOutMusic( prevBGM, 20 );
	FWait( 90 );
	PlayMusic( nextBGM );
	DeleteMusic( prevBGM );
}

/**
 * ステージを開始する
 * ステージ間の制御などもここで行う
 * 
 * @param { Integer } difficult 難易度
 * @param { Integer } player    プレイヤー
 * @param { Integer } stage     開始ステージ
 */
task StageStart( difficult, player, stage ){
	let playerName = "";
	let difficultName = "";
	
	//タイトルBGM停止
	ChangeBGM( bgmTitle, "" );
	//ステート変更
	State = State_Load;
	
	//プレイヤー設定
	alternative( player )
		case( 1 ){
			//サニー
			playerName = "Sunny";
		}
		case( 2 ){
			//ルナチャ
			playerName = "Luna";
		}
		case( 3 ){
			//スター
			playerName = "Star";
		}
	SetCommonDataEx( "OFT", "Player", playerName );
	
	//難易度設定
	alternative( difficult )
		case( 1 ){
			//Easy
			difficultName = "Easy";
			ExtendScore = EasyExtendScore;
			SetBombExtendNormaPoint( EasyBombExtendScore );
		}
		case( 2 ){
			//Normal
			difficultName = "Normal";
			ExtendScore = NormalExtendScore;
			SetBombExtendNormaPoint( NormalBombExtendScore );
		}
		case( 3 ){
			//Panic
			difficultName = "Panic";
			ExtendScore = PanicExtendScore;
			SetBombExtendNormaPoint( PanicBombExtendScore );
		}
	SetCommonDataEx( "OFT", "Difficult", difficultName );
	
	//2秒ぐらい待ってみる
	FWait( 120 );
	
	//ステージ設定
	if( stage == 0 ){
		//本編
		
		//ステージ1
		AddStagePlayNum( playerName, difficultName, "1" );
		Stage1();
		FWait( 240 );
/*		
		//ステージ2
		AddStagePlayNum( playerName, difficultName, "2" );
		Stage2();
		FWait( 240 );
		
		//ステージ3
		AddStagePlayNum( playerName, difficultName, "3" );
		Stage3();
		FWait( 240 );
		
		//ステージEX
		let isContinue  = Continued();
		let MissNum     = GetMissCount();
		let BombNum     = GetBombCount();
		let GetSpellNum = GetCommonDataDefaultEx( "OFT", "GetSpellNum", 0 );
		//ステージEX突入条件
		//  ノーコンティニュー
		//  ミス回数+ボム回数 <= 6
		//  スペル取得枚数 >= 10
		if( !isContinue && (MissNum + BombNum) <= 6 && GetSpellNum >= 10 ){
			AddStagePlayNum( playerName, difficultName, "4" );
			StageEX();
			FWait( 240 );
		}
*/		
		//クリア回数プラス
		AddClearNum( playerName, difficultName, !Continued() );
		
		//ステージ終了
		ClearStage();
	}else{
		//プラクティス
		alternative( stage )
			case( 1 ){
				//1
				AddStagePlayNum( playerName, difficultName, "1" );
				Stage1();
			}
			case( 2 ){
				//2
				AddStagePlayNum( playerName, difficultName, "2" );
				Stage2();
			}
			case( 3 ){
				//3
				AddStagePlayNum( playerName, difficultName, "3" );
				Stage3();
			}
			case( 4 ){
				//Ex
				AddStagePlayNum( playerName, difficultName, "4" );
				StageEX();
			}
		
		//1秒待つ
		FWait(60);
		
		//ステージ終了
		ClearStage();
	}
}

/**
 * セーブ＆コンフィグデータの削除を行う
 */
task ClearSaveData(){
	if( isReplayData ){
		//リプレイ再生中で消えるのはまずい
		ClearStage();
	}else{
		//初期化設定
		IsLoadFile = false;
		//初期値設定
		CreateOFTCommonData();
		//初期値でセーブ
		SaveOFTCommonData();
		//暫定処置
		ClearStage();
	}
}

/**
 * スコアエクステンドの処理を行う
 */
task ScoreExtend(){
	//基準値が設定されるまで待機
	while( ExtendScore == 0 ){
		yield;
	}
	
	let extendscore = ExtendScore;
	let ccount = GetAllowedContinueCount();
	let contnum = 0;
	let handredmillionscore = 0;
	
	loop{
		while( ccount == GetAllowedContinueCount() ){
			handredmillionscore = score1 * ( scoreexp / 10 ) + truncate(score2 / 10);
			if( handredmillionscore > extendscore ){
				CreateUserItem( GetPlayerX(), GetPlayerY(), UI_LIFE );
				extendscore += ExtendScore;
			}
			
			yield;
		}
		
		//コンティニュー時処理
		ccount = GetAllowedContinueCount();
		//エクステンド値初期化
		extendscore = ExtendScore;
		contnum += 1;
		//スコア初期化
		score1 = 0;
		score2 = 0;
		score3 = contnum;
		//スコア値初期化
		SubScorePoint( GetScorePoint() - 1 );
	}
}

/**
 * 撃ちこみ点用のグレイズ管理タスク
 */
task GrazeTask(){
	let graze = 0;
	
	loop{
		graze = truncate( GetScorePoint() / 10 ) * 40;
		AddGraze( graze - GetGraze() );
		
		yield;
	}
}

/**
 * オーバーエクステンド処理タスク
 */
task OverExtend(){
	let playernum = 0;
	let bombnum = 0;
	let playermaxnum = 10;
	let bombmaxnum = 10;
	
	loop{
		playernum = GetPlayerLife();
		bombnum = GetPlayerBomb();
		//残機オーバーエクステンド
		if( playernum > playermaxnum ){
			playernum -= playermaxnum;
			AddScore( OverPlayerExtendBonus * playernum );
			ExtendPlayer( -playernum );
		}
		//ボムオーバーエクステンド
		if( bombnum > bombmaxnum ){
			bombnum -= bombmaxnum;
			AddScore( OverBombExtendBonus * bombnum );
			AddBomb( -bombnum );
		}
		
		yield;
	}
}

/**
 * スコア値管理タスク
 */
task ScorePointControlTask(){
	let misscount = 0;
	let bombcount = 0;
	let scorepoint = 0;
	let subscorepoint = 0;
	
	loop{
		//デスペナルティ
		if( misscount != GetMissCount() ){
			scorepoint = GetScorePoint();
			subscorepoint = truncate( scorepoint * 0.15 );
			SubScorePoint( subscorepoint );
			
			misscount = GetMissCount();
		}
		//ボムペナルティ
		if( bombcount != GetBombCount() ){
			scorepoint = GetScorePoint();
			subscorepoint = truncate( scorepoint * 0.03 );
			SubScorePoint( subscorepoint );
			
			bombcount = GetBombCount();
		}
		
		yield;
	}
}