#TouhouDanmakufu[Player]
#ScriptVersion[3]
#ID["DCS_BORDERTEAM"]
#Title["E`["]
#Text["E`["]
#ReplayName["BorderTeam"]

// Player global and required
let playerID = GetPlayerObjectID;
let playerObj = ObjPrim_Create(OBJ_SPRITE_2D);
let teamanm = 0;
let teamanm2 = 0;
let count = -1;
let baseLaserScale = 6;
let scanScreen = [];						// array to store all enemyID.
let isFocus = false;
let isSpell = false;
let isSpellReimu = 0;
let isSpellYukari = 1;
let breakOut = false; 
let objRan = ObjPrim_Create(OBJ_SPRITE_2D);
let objDummy = ObjShot_Create(OBJ_SHOT);
let ranDir = 0; 

// Border shotsheet
let shotBorder = "script/player/dcs_player/shot_border.txt";

let hitboxObj = ObjPrim_Create(OBJ_SPRITE_2D);

// Libraries
#include "script/thdcs/functions/function_loaddata.txt"
#include "script/player/dcs_player/functions/player_global.txt"
#include "script/thdcs/functions/const_sound.txt"

@Initialize {
	LoadPlayerShotData(shotBorder); 
	plyHitbox(GetPlayerX,GetPlayerY);	
	SetPlayerSpeed(4,2); 
	ObjPlayer_AddIntersectionCircleA1(playerID,0,0,2,32);
	SetPlayerClip(0+6,0+24,384-6,448-16);
	SetPlayerRebirthFrame(30);
	SetPlayerDownStateFrame(60);
	SetPlayerAutoItemCollectLine(120);

	// Render the player & ran
	renderPlayer;		
	shikigamiRan;
}

@Event {
	alternative(GetEventType)
	
	case(EV_REQUEST_SPELL) {
		let bombStock = GetPlayerSpell;
		if(GetPlayerSpell > 0) { 
			if(isFocus) { 
				SetScriptResult(true); 
				SetPlayerSpell(bombStock - 1);
				spellCard(isSpellYukari); 
	
			} 
			else { 
				SetScriptResult(true); 
				SetPlayerSpell(bombStock - 1);
				spellCard(isSpellReimu); 		
			}
		} 
		else { 
			SetScriptResult(false); 
		}
	}	
	case(EV_GRAZE){
		PlaySFX(SFX_GRAZE);
	}
	case(EV_HIT){
		PlaySFX(SFX_PLDEAD00);
		playerPichuunEffect;	
	}
	case(EV_PLAYER_SHOOTDOWN) {
		pichuunHandler;
		PlaySFX(SFX_PLDEAD01);
		DeleteShotAllEX(TYPE_SHOT,TYPE_IMMEDIATE,GetPlayerX,GetPlayerY);	
	}
	case(EV_PLAYER_REBIRTH) {
		SetPlayerSpell(2);
		SetPlayerInvincibilityFrame(240);
		invincEffect(240);
		SetForbidPlayerShot(false);
		SetForbidPlayerSpell(false);
	}
}

@MainLoop {
	// scanScreen updater
	scanScreen = GetAllEnemyID;

	if(!isSpell && IsPermitPlayerShot) {
		// counter for shot
		if((GetVirtualKeyState(VK_SHOT) == KEY_PUSH || GetVirtualKeyState(VK_SHOT) == KEY_HOLD) && count == -1) {
				count = 0;
		}
		// Yukari
		if(GetVirtualKeyState(VK_SLOWMOVE) == KEY_PUSH || GetVirtualKeyState(VK_SLOWMOVE) == KEY_HOLD) {
	
			// Needle shot
			if(count%5 == 0) {
				CreatePlayerShotA1(GetPlayerX-20, GetPlayerY, 15, 270, 0.35, 1, 3);
				CreatePlayerShotA1(GetPlayerX-10, GetPlayerY, 15, 273, 0.55, 1, 3);
				CreatePlayerShotA1(GetPlayerX+10, GetPlayerY, 15, 267, 0.55, 1, 3);
				CreatePlayerShotA1(GetPlayerX+20, GetPlayerY, 15, 270, 0.35, 1, 3);
				
				CreatePlayerShotA1(ObjRender_GetX(objRan), ObjRender_GetY(objRan), 15, ranDir-2 ,0.15, 1, 4);
				CreatePlayerShotA1(ObjRender_GetX(objRan), ObjRender_GetY(objRan), 15, ranDir, 0.20, 1, 4);
				CreatePlayerShotA1(ObjRender_GetX(objRan), ObjRender_GetY(objRan), 15, ranDir+2, 0.15, 1, 4);
				
				PlaySFX(SFX_PSHOT);
			}
		} 
		// Reimu
		else {
			// Amulet shot
			if(count%5 == 0) {
				CreatePlayerShotA1(GetPlayerX-6, GetPlayerY, 15, 270, 0.65, 1, 1);
				CreatePlayerShotA1(GetPlayerX+6, GetPlayerY, 15, 270, 0.65, 1, 1);
				
				homingAmulet(GetPlayerX, GetPlayerY, 260, 0.15);
				homingAmulet(GetPlayerX, GetPlayerY, 280, 0.15);

				PlaySFX(SFX_PSHOT);
			}
			// Homing amulets 
			if(count%10 == 0) {
				homingAmulet(GetPlayerX, GetPlayerY, 250, 0.25);
				homingAmulet(GetPlayerX, GetPlayerY, 290, 0.25);
			}
		}      
		if(count >= 0) {
			count++;
		}
		if(count >= 10 && (GetVirtualKeyState(VK_SLOWMOVE) == KEY_PUSH || GetVirtualKeyState(VK_SLOWMOVE) == KEY_HOLD)) {
			count=-1;
		}
		if(count >= 20) {
			count=-1;
		}
	}
	yield;
} 

//----------------------------------------------------------------------------------------------------------------------------------------
// Render the player
task renderPlayer {

	ObjRender_SetPosition(playerObj,GetPlayerX,GetPlayerY,0);
	ObjPrim_SetTexture(playerObj,teamtex2); 
	Obj_SetRenderPriorityI(playerObj,31);
	ObjRender_SetBlendType(playerObj,BLEND_ALPHA);
	ObjRender_SetAngleXYZ(playerObj,0,0,0);
	ObjRender_SetScaleXYZ(playerObj,1,1,0);
	ObjRender_SetAlpha(playerObj,255);
	ObjSprite2D_SetSourceRect(playerObj,0,0,32,48);
	ObjSprite2D_SetDestCenter(playerObj);	
	
	while(!Obj_IsDeleted(playerObj)) {
		ObjRender_SetPosition(playerObj,GetPlayerX,GetPlayerY,0);
		
		if(GetVirtualKeyState(VK_SLOWMOVE) == KEY_PUSH || GetVirtualKeyState(VK_SLOWMOVE) == KEY_HOLD) { 
			if(!isSpell) { isFocus = true; } 
			 
		} 
		if(GetVirtualKeyState(VK_SLOWMOVE) == KEY_PULL ) { 
			if(!isSpell) { isFocus = false;  } 
		} 
		
		if(GetVirtualKeyState(VK_LEFT) == KEY_HOLD) { ObjRender_SetAngleY(playerObj,0); }
		if(GetVirtualKeyState(VK_RIGHT) == KEY_HOLD) { ObjRender_SetAngleY(playerObj,180); }
		if(!isFocus) {  ObjRender_SetAngleY(playerObj,0); }
		
		// Regular mode (main)
		if(!isFocus) {
			// Left side animation
			if(GetVirtualKeyState(VK_LEFT) == KEY_PUSH || GetVirtualKeyState(VK_LEFT) == KEY_HOLD) { 
				ObjRender_SetAngleY(playerObj,0);
				ObjSprite2D_SetSourceRect(playerObj,0,48,32,96);
			}
			// Right side animation
			else if(GetVirtualKeyState(VK_RIGHT) == KEY_PUSH || GetVirtualKeyState(VK_RIGHT) == KEY_HOLD) {
				ObjRender_SetAngleY(playerObj,180);
				ObjSprite2D_SetSourceRect(playerObj,0,48,32,96);
			} 
			// Idle animation
			else { 
				ObjSprite2D_SetSourceRect(playerObj,0,0,32,48); 
			}
			ObjRender_SetAlpha(hitboxObj,0);
		}
		
		// Focus mode (partner switch)
		if(isFocus) { 
			// Left side animation
			if(GetVirtualKeyState(VK_LEFT) == KEY_PUSH || GetVirtualKeyState(VK_LEFT) == KEY_HOLD) { 
				ObjSprite2D_SetSourceRect(playerObj,128,48,160,96);
			}
			// Right side animation
			else if(GetVirtualKeyState(VK_RIGHT) == KEY_PUSH || GetVirtualKeyState(VK_RIGHT) == KEY_HOLD) {
				ObjSprite2D_SetSourceRect(playerObj,128,48,160,96); 
			}
			// Idle animation
			else { 
				ObjSprite2D_SetSourceRect(playerObj,128,0,160,48);
			}
			ObjRender_SetAlpha(hitboxObj,255);
		}
		//teamanm+=3;
        //teamanm2+=3;
		//if(teamanm == 60) { teamanm = 0; }
		yield;
	}
} 

task shikigamiRan {

	// anim
	let guru = 0;
	let alphret = 255;

	// essential
	let ranScan = 0;
	let ranLock = -1;
	let ranVicinityCone = 0;
	let ranHome = true;
	let x = GetPlayerX;
	let y = GetPlayerY - 96;
	let v = 0;

	// obj
	ObjPrim_SetTexture(objRan,teamtex2);
	ObjRender_SetBlendType(objRan,BLEND_ALPHA);
	ObjRender_SetAlpha(objRan,alphret);
	Obj_SetRenderPriorityI(objRan,40);
	ObjRender_SetPosition(objRan,x,y,0);
	ObjRender_SetScaleXYZ(objRan,1,1,0);
	ObjSprite2D_SetSourceRect(objRan,192,144,256,240);
	ObjSprite2D_SetDestCenter(objRan);

	while(!Obj_IsDeleted(objRan)) {

		// If Ran is out
		if(isFocus) {
			alphret = 255;

			let rx = ObjRender_GetX(objRan);
			let ry = ObjRender_GetY(objRan);

			// default target is player
			let tx = GetPlayerX;
			let ty = GetPlayerY - 96; // above player

			// Ran behaviour when shooting
			if(GetVirtualKeyState(VK_SHOT) == KEY_HOLD || GetVirtualKeyState(VK_SHOT) == KEY_PUSH) {
				
				// If there is no target and some are available
				if(length(scanScreen) > 0 && ranLock == -1) {

					let ranLockDist = 999999;

					// loop through the entire enemy object array
					ascent (i in 0..length(scanScreen)) {

						ranScan = scanScreen[i];

						// create a cone and circle to check for enemies within and store in var
						ranVicinityCone = GetPointToPointAngle(ObjMove_GetX(ranScan),ObjMove_GetY(ranScan),ObjRender_GetX(objRan),ObjRender_GetY(objRan));
						
						// Check whether the enemy is 10 degree from 270 degree (-90) or within 64 pixel radius from Ran
						if(((ranVicinityCone < -70 && ranVicinityCone > -110) || (GetObjectDistance(objRan,ranScan) < 64)) && (ranLock == -1 || !Obj_IsDeleted(ranLock))) {

							// Get value from SetValue and check whether it is a familiar or not (bool)
							if(!Obj_GetValue(ranScan,"isFamiliar")) {
								// If there is a better target (nearer to Ran) replace nominee
								let ranScanDist = GetObjectDistance(objRan,ranScan);
								if(ranScanDist < ranLockDist) {
									ranLock = ranScan;
									ranLockDist = ranScanDist;
									ranDir = GetPointToPointAngle(ObjMove_GetX(ranLock),ObjMove_GetY(ranLock),ObjRender_GetX(objRan),ObjRender_GetY(objRan));
								}
							}

						}
					}
				}

				// If there is a target and it isn't dead
				if(ranLock != -1 && !Obj_IsDeleted(ranLock)) {
					ranHome = false; // Off of home position

					// Set target position
					tx = ObjMove_GetX(ranLock);
					ty = ObjMove_GetY(ranLock);
				} else {
					// dead, pick another target
					ranLock = -1;
				}
			} else {
				// If you stop shooting, let you pick another target
				ranLock = -1;
			}

			if(!ranHome) {
				let dx = (tx - rx);
				let dy = (ty - ry);
				let dist = (dy^2 + dx^2)^0.5;

				// If Ran is within 16 pixels of target, just set her position to the target
				if( dist < 16 ) {
					x = tx;
					y = ty;
					if(ranLock == -1) { 		// dist < 16 at Yukari
						ranHome = true; 	// lock at home position
					}
				} else {
					// Otherwise increase velocity
					if(v < 8) { v += 2; }
					// Change xy position so that Ran moves towards target at given velocity
					x += dx * (v / dist);
					y += dy * (v / dist);
				}

				// anim
				guru+=15;
				ObjSprite2D_SetSourceRect(objRan,128,144,192,240);
				
			} else {
				x = GetPlayerX;
				y = GetPlayerY - 96;
				guru = 0;
				ranDir = 270;
				v = 0;
				ObjSprite2D_SetSourceRect(objRan,192,144,256,240);			
			}

		}
		// If player isn't focussing, reset everything to default.
		else if(!isFocus) {
			guru = 0;
			ranDir = 270;
			v = 0;
			x = GetPlayerX;
			y = GetPlayerY-64;
			alphret = 0;
			ranLock = -1;
		}

		// Update Ran animation
		ObjRender_SetAngleZ(objRan,guru);
		ObjRender_SetAlpha(objRan,alphret);

		// Move Ran
		ObjRender_SetPosition(objRan,x,y,0);

		yield;
	}
}

// Naut's code for homing bullets from RandomPlayer script.
task homingAmulet(x, y, angle, dmg){
	loop(rand_int(0, 1)){yield;}
	let ar = GetAllEnemyID;
	let obj = ObjShot_Create(OBJ_SHOT);
	let speed = 10;
	let enem = [x + 500*cos(angle), y + 500*sin(angle), 1000];
	let counter = 0;	
	
	ObjShot_Regist(obj);
	ObjMove_SetPosition(obj,x,y);
	ObjShot_SetGraphic(obj,2);
	ObjShot_SetDamage(obj,dmg);
	ObjShot_SetPenetration(obj,1);

	while(!Obj_IsDeleted(obj)) {
		counter++;
	
		if(counter%2==0) {
			ar = GetAllEnemyID;
			ascent(i in 0..(length(ar))){
				let dis = ((x - ObjMove_GetX(ar[0]))^2 + (y - ObjMove_GetY(ar[0]))^2)^0.5;
				if(dis<enem[2]){
					enem[2] = dis;
					enem[0] = ObjMove_GetX(ar[0]);
					enem[1] = ObjMove_GetY(ar[0]);
				}
			}
			enem[2] = 1000;
		}
		let dir = atan2(enem[1] - y, enem[0] - x);
		let diff = dir - angle;
		while(diff >= 180) { diff -= 360; }
		while(diff < -180) { diff += 360; }
		let diffAbs = (|diff|);
		if(diffAbs <= 4) {
			angle = dir;
		} else {
			if(length(ar) > 0) { angle += 14 * diff / diffAbs; }
		}
		ObjMove_SetAngle(obj, angle);
		speed+=0.1;
		x+=speed*cos(angle);
		y+=speed*sin(angle);
		ObjMove_SetSpeed(obj, speed);
		yield;
	}
}

// Task to summon the spell card + deal damage. Type determines which char uses.
task spellCard(type) { 
	let card = ObjSpell_Create();
	let colSet = [[255, 16, 16],[16,255,16],[16,16,255],[16,255,255],[255,16,255],[255,255,16],[255,128,16]]; // red, green, blue, cyan, purple, yellow, orange
	let colKies = 0;
	let dir = 0;	
	
	ObjSpell_Regist(card);
	ObjSpell_SetEraseShot(card,true);
	SetForbidPlayerShot(true);
	SetForbidPlayerSpell(true);	
	PlaySFX(SFX_CAT00);

	playerFunkyCircle;
	playerFunkyCircle2;
	
	if(type == isSpellReimu) { 
		magicCircleBorder(GetPlayerX,GetPlayerY);
		SetPlayerInvincibilityFrame(300);	
		SetPlayerSpeed(10,10);	
		
		// sfx randomizer
		let randomsfx = rand_int(0,2);
		if(randomsfx == 0) { }
		if(randomsfx == 1) { }	
		setReimuGlow;
		PlaySFX(SFX_BALLHUM);
		ascent(i in 0..8) { 
			reimuDiscoBall(card,GetPlayerX,GetPlayerY,dir,i); 
			dir+=360/8; 
		}
		isSpell = true;
		wait(240);
		PlaySFX(SFX_DISCONEP00);
		playerBreakEffect;		
		breakOut = true;	
		wait(1);
		isSpell = false;
		SetCommonData("BGMVolume",100);		
		SetPlayerSpeed(4,2);
	} 
	if(type == isSpellYukari) { 
		magicCircleBorder(GetPlayerX,GetPlayerY);
		SetPlayerInvincibilityFrame(300);	
		SetPlayerSpeed(1,1);

		// sfx randomizer
		let randomsfx = rand_int(0,2);
		if(randomsfx == 0) { }
		if(randomsfx == 1) { }			
		sukimaGenerator; 

		isSpell = true;
		wait(240);
		PlaySFX(SFX_DISCONEP00);
		playerBreakEffect;		
		breakOut = true;	
		wait(1);
		isSpell = false;
		SetCommonData("BGMVolume",100);	
		SetPlayerSpeed(4,2);
		if(GetVirtualKeyState(VK_SLOWMOVE) != KEY_HOLD) { isFocus = false; }  	
	}
	Obj_Delete(GetSpellManageObject);
	SetForbidPlayerShot(false);
	SetForbidPlayerSpell(false);
	breakOut = false;	
}


