#TouhouDanmakufu[Package]
#Title["󉉕 ` Treasured Dance Performance"]
#Text["v1.50"]

//****************************************************************************************************
// Library:
// 		mainTask						- Main task flow
// 		mainLoadThread					- Loading thread for preloading data.
// 		drawLoadingScreen				- Drawing code to draw the loading screen
// 		titleScreenHandler				- Summoned from menu_title.txt to handle the title selection
//
//****************************************************************************************************

// Global
let isLoaded = false;
let rootDir = GetModuleDirectory;

// Loading progress text
let loadingText = ObjText_Create;
ObjRender_SetPosition(loadingText,16,458,0);	
ObjText_SetFontType(loadingText,"MeiryoKe_PGothic");
ObjText_SetFontBorderType(loadingText,BORDER_SHADOW);
ObjText_SetFontBorderWidth(loadingText,1);
ObjText_SetFontBorderColor(loadingText,0,0,0);	
ObjText_SetFontSize(loadingText,14);
ObjText_SetText(loadingText,"...");
	
#include "script/thdcs/functions/function_loaddata.txt"
#include "script/thdcs/functions/function_hud.txt"
#include "script/thdcs/menu/menu_title.txt"

@Initialize {
	// System config data (save checked) 
	LoadCommonDataAreaA1("system");
	if(!IsCommonDataAreaExists("system")) { 
		CreateCommonDataArea("system");							
		LoadCommonDataAreaA1("system");
		SetAreaCommonData("system","bgmvol",100);			// Music volume
		SetAreaCommonData("system","sfxvol",100);			// Sound volume		
		SetAreaCommonData("system","gameLang",0); 			// Language, 0 = JP, 1 = EN	
		SetAreaCommonData("system","FXLevel",2);			// Level of detail. 0 = No FX, 1 = Medium FX,  2 = Full FX
		SaveCommonDataAreaA1("system");
	}

	// Core data (save checked)
	LoadCommonDataAreaA1("core");
	if(!IsCommonDataAreaExists("core")) { 
		CreateCommonDataArea("core");							
		LoadCommonDataAreaA1("core");


		SetAreaCommonData("core","unlockExtra",false);
		SetAreaCommonData("core","practiseStg1",false);		
		SetAreaCommonData("core","practiseStg2",false);		
		SetAreaCommonData("core","practiseStg2",false);			

		// Last words unlock trackers
		SetAreaCommonData("core","unlockLast1",false);      // Reimu
		SetAreaCommonData("core","unlockLast2",false);      // Yukari
		SetAreaCommonData("core","unlockLast3",false);      // Marisa
		SetAreaCommonData("core","unlockLast4",false);      // Alice
		SetAreaCommonData("core","unlockLast5",false);      // Fifi
		SetAreaCommonData("core","unlockLast6",false);      // Pierre
		SetAreaCommonData("core","unlockLast7",false);      // Hina
		SetAreaCommonData("core","unlockLast8",false);      // Ufo
		SetAreaCommonData("core","unlockLast9",false);      // Nue
		SetAreaCommonData("core","unlockLast10",false);     // Kogasa
		SetAreaCommonData("core","unlockLast11",false);     // Tenji
		SetAreaCommonData("core","unlockLast12",false);     // Iku
		SetAreaCommonData("core","unlockLast13",false);     // Akira
		SetAreaCommonData("core","unlockLast14",false);     // Tewi
		SetAreaCommonData("core","unlockLast15",false);		// Border
		SetAreaCommonData("core","unlockLast16",false);		// Magic
		SetAreaCommonData("core","unlockLast17",false);		// Nue & Kogasa
		SetAreaCommonData("core","unlockLast18",false);		// Piere & Hina
		SetAreaCommonData("core","unlockLast19",false);		// Tenji & Iku
		SetAreaCommonData("core","unlockLast20",false);		// Dj & Tewi

		// Endings
		SetAreaCommonData("core","goodEndBorder",false);
		SetAreaCommonData("core","goodEndMagic",false);
		SetAreaCommonData("core","normalEndBorder",false);
		SetAreaCommonData("core","normalEndMagic",false);
		SetAreaCommonData("core","badEnd01",false);
		SetAreaCommonData("core","badEnd02",false);
		SetAreaCommonData("core","badEnd03",false);
		SetAreaCommonData("core","badEnd04",false);
		SetAreaCommonData("core","badEnd05",false);
		SetAreaCommonData("core","badEnd06",false);

		// Spell practise core. Array for the spell cards to track value
		//		Structure [ state, captureStage, historyStage, capturePrac, historyPrac, scoreBorder, scoreMagic, scoreReimu, scoreYukari, scoreMarisa, scoreAlice ]
		//		State 0 = unseen/disabled. 1 = Seen. 2 = Captured.
		//		Number of captures and tries is as they are.
		
		// 01 spell cards
		SetAreaCommonData("core","fifi01norm",[0,0,0,0,0,0,0,0,0,0,0]);
		SetAreaCommonData("core","pierre01norm",[0,0,0,0,0,0,0,0,0,0,0]);
		SetAreaCommonData("core","pierre02norm",[0,0,0,0,0,0,0,0,0,0,0]);
		SetAreaCommonData("core","pierre03norm",[0,0,0,0,0,0,0,0,0,0,0]);
		SetAreaCommonData("core","pierre04norm",[0,0,0,0,0,0,0,0,0,0,0]);
		
		SetAreaCommonData("core","fifi01hard",[0,0,0,0,0,0,0,0,0,0,0]);
		SetAreaCommonData("core","pierre01hard",[0,0,0,0,0,0,0,0,0,0,0]);
		SetAreaCommonData("core","pierre02hard",[0,0,0,0,0,0,0,0,0,0,0]);
		SetAreaCommonData("core","pierre03hard",[0,0,0,0,0,0,0,0,0,0,0]);
		SetAreaCommonData("core","pierre04hard",[0,0,0,0,0,0,0,0,0,0,0]);
		
		SetAreaCommonData("core","fifi01runa",[0,0,0,0,0,0,0,0,0,0,0]);
		SetAreaCommonData("core","pierre01runa",[0,0,0,0,0,0,0,0,0,0,0]);
		SetAreaCommonData("core","pierre02runa",[0,0,0,0,0,0,0,0,0,0,0]);
		SetAreaCommonData("core","pierre03runa",[0,0,0,0,0,0,0,0,0,0,0]);
		SetAreaCommonData("core","pierre04runa",[0,0,0,0,0,0,0,0,0,0,0]);
		
		// 02 spell cards
		SetAreaCommonData("core","nue01norm",[0,0,0,0,0,0,0,0,0,0,0]);
		SetAreaCommonData("core","tenji01norm",[0,0,0,0,0,0,0,0,0,0,0]);
		SetAreaCommonData("core","tenji02norm",[0,0,0,0,0,0,0,0,0,0,0]);
		SetAreaCommonData("core","tenji03norm",[0,0,0,0,0,0,0,0,0,0,0]);
		SetAreaCommonData("core","tenji04norm",[0,0,0,0,0,0,0,0,0,0,0]);
		SetAreaCommonData("core","tenji05norm",[0,0,0,0,0,0,0,0,0,0,0]);
		SetAreaCommonData("core","tenji06norm",[0,0,0,0,0,0,0,0,0,0,0]);
		SetAreaCommonData("core","tenji07norm",[0,0,0,0,0,0,0,0,0,0,0]);
		
		SetAreaCommonData("core","nue01hard",[0,0,0,0,0,0,0,0,0,0,0]);
		SetAreaCommonData("core","tenji01hard",[0,0,0,0,0,0,0,0,0,0,0]);
		SetAreaCommonData("core","tenji02hard",[0,0,0,0,0,0,0,0,0,0,0]);
		SetAreaCommonData("core","tenji03hard",[0,0,0,0,0,0,0,0,0,0,0]);
		SetAreaCommonData("core","tenji04hard",[0,0,0,0,0,0,0,0,0,0,0]);
		SetAreaCommonData("core","tenji05hard",[0,0,0,0,0,0,0,0,0,0,0]);
		SetAreaCommonData("core","tenji06hard",[0,0,0,0,0,0,0,0,0,0,0]);
		SetAreaCommonData("core","tenji07hard",[0,0,0,0,0,0,0,0,0,0,0]);
		
		SetAreaCommonData("core","nue01runa",[0,0,0,0,0,0,0,0,0,0,0]);
		SetAreaCommonData("core","tenji01runa",[0,0,0,0,0,0,0,0,0,0,0]);
		SetAreaCommonData("core","tenji02runa",[0,0,0,0,0,0,0,0,0,0,0]);
		SetAreaCommonData("core","tenji03runa",[0,0,0,0,0,0,0,0,0,0,0]);
		SetAreaCommonData("core","tenji04runa",[0,0,0,0,0,0,0,0,0,0,0]);
		SetAreaCommonData("core","tenji05runa",[0,0,0,0,0,0,0,0,0,0,0]);
		SetAreaCommonData("core","tenji06runa",[0,0,0,0,0,0,0,0,0,0,0]);
		SetAreaCommonData("core","tenji07runa",[0,0,0,0,0,0,0,0,0,0,0]);
		
		// 03 spell cards
		SetAreaCommonData("core","border01norm",[0,0,0,0,0,0,0,0,0,0,0]);
		SetAreaCommonData("core","magic01norm",[0,0,0,0,0,0,0,0,0,0,0]);
		SetAreaCommonData("core","dj01norm",[0,0,0,0,0,0,0,0,0,0,0]);
		SetAreaCommonData("core","dj02norm",[0,0,0,0,0,0,0,0,0,0,0]);
		SetAreaCommonData("core","dj03norm",[0,0,0,0,0,0,0,0,0,0,0]);
		SetAreaCommonData("core","dj04norm",[0,0,0,0,0,0,0,0,0,0,0]);
		SetAreaCommonData("core","dj05norm",[0,0,0,0,0,0,0,0,0,0,0]);
		SetAreaCommonData("core","dj06norm",[0,0,0,0,0,0,0,0,0,0,0]);
		SetAreaCommonData("core","dj07norm",[0,0,0,0,0,0,0,0,0,0,0]);
		
		SetAreaCommonData("core","border01hard",[0,0,0,0,0,0,0,0,0,0,0]);
		SetAreaCommonData("core","magic01hard",[0,0,0,0,0,0,0,0,0,0,0]);
		SetAreaCommonData("core","dj01hard",[0,0,0,0,0,0,0,0,0,0,0]);
		SetAreaCommonData("core","dj02hard",[0,0,0,0,0,0,0,0,0,0,0]);
		SetAreaCommonData("core","dj03hard",[0,0,0,0,0,0,0,0,0,0,0]);
		SetAreaCommonData("core","dj04hard",[0,0,0,0,0,0,0,0,0,0,0]);
		SetAreaCommonData("core","dj05hard",[0,0,0,0,0,0,0,0,0,0,0]);
		SetAreaCommonData("core","dj06hard",[0,0,0,0,0,0,0,0,0,0,0]);
		SetAreaCommonData("core","dj07hard",[0,0,0,0,0,0,0,0,0,0,0]);
		
		SetAreaCommonData("core","border01runa",[0,0,0,0,0,0,0,0,0,0,0]);
		SetAreaCommonData("core","magic01runa",[0,0,0,0,0,0,0,0,0,0,0]);
		SetAreaCommonData("core","dj01runa",[0,0,0,0,0,0,0,0,0,0,0]);
		SetAreaCommonData("core","dj02runa",[0,0,0,0,0,0,0,0,0,0,0]);
		SetAreaCommonData("core","dj03runa",[0,0,0,0,0,0,0,0,0,0,0]);
		SetAreaCommonData("core","dj04runa",[0,0,0,0,0,0,0,0,0,0,0]);
		SetAreaCommonData("core","dj05runa",[0,0,0,0,0,0,0,0,0,0,0]);
		SetAreaCommonData("core","dj06runa",[0,0,0,0,0,0,0,0,0,0,0]);
		SetAreaCommonData("core","dj07runa",[0,0,0,0,0,0,0,0,0,0,0]);
		
		// Last words
		SetAreaCommonData("core","last1",[0,0,0,0,0,0,0,0,0,0,0]);          // Reimu
		SetAreaCommonData("core","last2",[0,0,0,0,0,0,0,0,0,0,0]);          // Yukari
		SetAreaCommonData("core","last3",[0,0,0,0,0,0,0,0,0,0,0]);          // Marisa
		SetAreaCommonData("core","last4",[0,0,0,0,0,0,0,0,0,0,0]);          // Alice
		SetAreaCommonData("core","last5",[0,0,0,0,0,0,0,0,0,0,0]);          // Fifi
		SetAreaCommonData("core","last6",[0,0,0,0,0,0,0,0,0,0,0]);          // Pierre
		SetAreaCommonData("core","last7",[0,0,0,0,0,0,0,0,0,0,0]);          // Hina
		SetAreaCommonData("core","last8",[0,0,0,0,0,0,0,0,0,0,0]);          // Ufo
		SetAreaCommonData("core","last9",[0,0,0,0,0,0,0,0,0,0,0]);          // Kogasa
		SetAreaCommonData("core","last10",[0,0,0,0,0,0,0,0,0,0,0]);         // Nue
		SetAreaCommonData("core","last11",[0,0,0,0,0,0,0,0,0,0,0]);         // Tenji
		SetAreaCommonData("core","last12",[0,0,0,0,0,0,0,0,0,0,0]);         // Iku
		SetAreaCommonData("core","last13",[0,0,0,0,0,0,0,0,0,0,0]);         // Dj
		SetAreaCommonData("core","last14",[0,0,0,0,0,0,0,0,0,0,0]);         // Tewi
		SetAreaCommonData("core","last15",[0,0,0,0,0,0,0,0,0,0,0]);         // Border
		SetAreaCommonData("core","last16",[0,0,0,0,0,0,0,0,0,0,0]);         // Magic
		SetAreaCommonData("core","last17",[0,0,0,0,0,0,0,0,0,0,0]);         // Kogasa & Nue
		SetAreaCommonData("core","last18",[0,0,0,0,0,0,0,0,0,0,0]);         // Pierre + Hina
		SetAreaCommonData("core","last19",[0,0,0,0,0,0,0,0,0,0,0]);         // Tenji + Iku
		SetAreaCommonData("core","last20",[0,0,0,0,0,0,0,0,0,0,0]);         // Dj + Tewi
		
        // Scores for stages
        //      Structure: border, magic, reimu, yukari, marisa, alice
		SetAreaCommonData("core", "hiScoreStg1Norm", [0,0,0,0,0,0]);		// High Score stg1
		SetAreaCommonData("core", "hiScoreStg1Hard", [0,0,0,0,0,0]);
		SetAreaCommonData("core", "hiScoreStg1Luna", [0,0,0,0,0,0]);
		SetAreaCommonData("core", "hiScoreStg2Norm", [0,0,0,0,0,0]);	    // High Score stg2
		SetAreaCommonData("core", "hiScoreStg2Hard", [0,0,0,0,0,0]);
		SetAreaCommonData("core", "hiScoreStg2Luna", [0,0,0,0,0,0]);
		SetAreaCommonData("core", "hiScoreStg3Norm", [0,0,0,0,0,0]);		// High Score stg3
		SetAreaCommonData("core", "hiScoreStg3Hard", [0,0,0,0,0,0]);
		SetAreaCommonData("core", "hiScoreStg3Luna", [0,0,0,0,0,0]);

        SetAreaCommonData("core", "hiScorePracStg1Norm", [0,0,0,0,0,0]);	// High Score stg1
        SetAreaCommonData("core", "hiScorePracStg1Hard", [0,0,0,0,0,0]);
        SetAreaCommonData("core", "hiScorePracStg1Luna", [0,0,0,0,0,0]);
		SetAreaCommonData("core", "hiScorePracStg2Norm", [0,0,0,0,0,0]);	// High Score stg2
		SetAreaCommonData("core", "hiScorePracStg2Hard", [0,0,0,0,0,0]);
		SetAreaCommonData("core", "hiScorePracStg2Luna", [0,0,0,0,0,0]);
		SetAreaCommonData("core", "hiScorePracStg3Norm", [0,0,0,0,0,0]);	// High Score stg3
		SetAreaCommonData("core", "hiScorePracStg3Hard", [0,0,0,0,0,0]);
		SetAreaCommonData("core", "hiScorePracStg3Luna", [0,0,0,0,0,0]);

		SetAreaCommonData("core", "hiScoreStgTotal", [0,0,0,0,0,0]);		// High Score story mode
		SetAreaCommonData("core", "hiScorePracTotal", [0,0,0,0,0,0]);	    // High Score practice mode

		SaveCommonDataAreaA1("core");
	}

	// Game data
	CreateCommonDataArea("game");	
	LoadCommonDataAreaA1("game");
	SetAreaCommonData("game","menuFlow",0);					// Tracker for Menu flows.
	SetAreaCommonData("game","stageNum",1);					// Tracker for Stage number.
	SetAreaCommonData("game","difficulty",0);				// 0 = Normal, 1 = Hard, 2 = Lunatic.
	SetAreaCommonData("game","team",0);						// 0 = Border, 1 = Magic.
	SetAreaCommonData("game","isDialogue",false);			// Tracker for dialogues (dialogue).
	SetAreaCommonData("game","fightHina",false);			// Will meet Hina, because player has met conditions.
	SetAreaCommonData("game","fightIku",false);				// Will meet Iku, because player has met conditions.
	SetAreaCommonData("game","fightTewi",false);			// Will meet Tewi, because player has met conditions.
	SetAreaCommonData("game","piv",0);						// PIV value
	SetAreaCommonData("game","feverpoint",0);				// Fever points value
	SetAreaCommonData("game","spellcardname",0);			// Name of the spell card
	SetAreaCommonData("game","cannotUnlock",0);				// Unlocktracker

	SetAreaCommonData("game","treasure1",false);			// treasure gotten from stage 1
	SetAreaCommonData("game","treasure2",false);			// treasure gotten from stage 2
	SetAreaCommonData("game","treasure3",false);			// treasure gotten from stage 3	
	SaveCommonDataAreaA1("game");	

	// Sound data
	CreateCommonDataArea("sound");	
	LoadCommonDataAreaA1("sound");
	SetAreaCommonData("sound","song",0);					// Song number. 0 = title, 1/2/3 = STG1/2/3, 4/5/6 = Boss 1/2/3, 7 = Ending
	SetAreaCommonData("sound","genvol",100);				// General volume
	SetAreaCommonData("sound","playervol",100);				// Player music volume (currently for Alice spell only)
	SetAreaCommonData("sound","isMute",false);				// Tracker whether music is muted
	SetAreaCommonData("sound","isStop",false);				// Tracker whether music is stopped
	SetAreaCommonData("sound","isStart",false);				// Tracker whether music is started
	SetAreaCommonData("sound","isChange",false);			// Tracker whether music is changed
	SaveCommonDataAreaA1("sound");	
	
	// boot to mainTask to start the engine processing for loading.
	mainTask;
}

@MainLoop { yield; }
@Finalize { }

// Main task flow
task mainTask {
	SetSkipModeKey(KEY_INVALID);

    let disclaimerSrc = drawDisclaimerScreen();
    screenFadeOutEffect(disclaimerSrc);
    waitTitle(240);
    Obj_Delete(disclaimerSrc);

	ObjText_SetText(loadingText,"Starting scripts...");
	
	// Prepare all sounds, bgm and voice acting.
	let rootDir = GetModuleDirectory;
	let path = rootDir ~ "script/thdcs/functions/function_sound.txt";
	let id = LoadScript(path);
	StartScript(id);	
	ObjText_SetText(loadingText,"Loading data...");
	
	// Loading screen as placeholder
	let loadScr = drawLoadingScreen();
	screenFadeInEffect(loadScr);
	hudBallGlitterA;	
	waitTitle(30);
	mainLoadThread;
	ObjText_SetText(loadingText,"Loaded! Ready to fever?");
	waitTitle(180);
	while(!isLoaded) { yield; }
	
	Obj_Delete(loadScr); Obj_Delete(loadingText);
	
	// finished loading > call titleScreenHandler to start the title screen
	PlayMusic(BGM_TITLE);	
	titleScreenHandler;	
}

// Loading function
function mainLoadThread {
	// for each part use ascent to loop through length of the array and load in thread.
	ObjText_SetText(loadingText,"Loading title data...");
	ascent(i in 0..length(loadArrayTitle)) {
		LoadTextureInLoadThread(loadArrayTitle[i]);
	}
	yield;
	ObjText_SetText(loadingText,"Loading dialogue data...");
	// Dialogue faces load
	ascent(i in 0..length(loadArrayDiag)) {
		LoadTextureInLoadThread(loadArrayDiag[i]);
	}	
	yield;
	ObjText_SetText(loadingText,"Loading stage data...");
	// Gen world tex load
	ascent(i in 0..length(loadArrayStgGen)) {
		LoadTextureInLoadThread(loadArrayStgGen[i]);
	}	
	// Stg1 world tex load
	ascent(i in 0..length(loadArrayStg1)) {
		LoadTextureInLoadThread(loadArrayStg1[i]);
	}
	// Stg 2 world tex load
	ascent(i in 0..length(loadArrayStg2)) {
		LoadTextureInLoadThread(loadArrayStg2[i]);
	}	
	// Stg 3 world tex load
	ascent(i in 0..length(loadArrayStg3)) {
		LoadTextureInLoadThread(loadArrayStg3[i]);
	}
	yield;
	ObjText_SetText(loadingText,"Loading enemy data...");
	// Enemy tex load
	ascent(i in 0..length(loadArrayEnemy)) {
		LoadTextureInLoadThread(loadArrayEnemy[i]);
	}	
	yield;
	ObjText_SetText(loadingText,"Loading player data...");
	// Player tex load
	ascent(i in 0..length(loadArrayPly)) {
		LoadTextureInLoadThread(loadArrayPly[i]);
	}			
	yield;
	ObjText_SetText(loadingText,"Loading effects data...");
	// Effect tex load
	ascent(i in 0..length(loadArrayEffect)) {
		LoadTextureInLoadThread(loadArrayEffect[i]);
	}	
	isLoaded = true;
}

function drawDisclaimerScreen {
	let obj = ObjPrim_Create(OBJ_SPRITE_2D);

	ObjPrim_SetTexture(obj,imgDisclaimerScr);
	ObjRender_SetBlendType(obj,BLEND_ALPHA);
	ObjRender_SetAlpha(obj,255);
	Obj_SetRenderPriorityI(obj,20);
	ObjSprite2D_SetSourceRect(obj,0,0,640,480);
	ObjSprite2D_SetDestRect(obj,0,0,640,480);

	return obj;
}

function drawLoadingScreen {
	let obj = ObjPrim_Create(OBJ_SPRITE_2D);

	ObjPrim_SetTexture(obj,imgLoadScr);
	ObjRender_SetBlendType(obj,BLEND_ALPHA);
	ObjRender_SetAlpha(obj,0);
	Obj_SetRenderPriorityI(obj,20);
	ObjSprite2D_SetSourceRect(obj,0,0,640,480);
	ObjSprite2D_SetDestRect(obj,0,0,640,480);
	
	return obj;	
}

task screenFadeInEffect(obj) {
    let increaseAlphaValue = 0;

    loop(15) {
        ObjRender_SetAlpha(obj,increaseAlphaValue);
        increaseAlphaValue += 254/15;
        yield;
    }
}

task screenFadeOutEffect(obj) {
    let increaseAlphaValue = 250;

    loop(180) { yield; }
    loop(60) {
        ObjRender_SetAlpha(obj,increaseAlphaValue);
        increaseAlphaValue -= 250/60;
        yield;
    }
}

// Glitter during loading
task hudBallGlitterA {
	// red, green, blue, cyan, purple, yellow, orange
	let colSet = [[255, 16, 16],[16,255,16],[16,16,255],[16,255,255],[255,16,255],[255,255,16],[255,128,16]]; 
	let colKies = 0;	
	let dir = 0;
	
	loop(64) { 
		colKies = rand_int(0,7);
		hudGlitterA(480+72*cos(dir),256+72*sin(dir),rand(0.5,3.0),rand_int(0,360),rand(0.2,3.5),255,colSet[colKies][0],colSet[colKies][1],colSet[colKies][2]);
		yield;
		hudGlitterA(480+72*cos(dir+180),256+72*sin(dir+180),rand(0.5,3.0),rand_int(0,360),rand(0.2,3.5),255,colSet[colKies][0],colSet[colKies][1],colSet[colKies][2]);
		dir+=360/36;
		yield;
	}
}