#TouhouDanmakufu[Player]
#ScriptVersion[3]	//スクリプトバージョン3が必須です
#ID["Kirishima"]
#Title["Kirishima Twins"]
#Text["Narumi & Mizuki Kirishima"]
#Image["./Select.png"]
#ReplayName["Kirishima"]

/*
Hitbox radius: 1

Damage:

Spread type
- Center DPS: 108
- Edge DPS: 36
- Shotgun DPS: 350
- Spell Damage: 1980

Straight type
- Full DPS: 270
- Edge DPS: 48
- Spell Far Damage: 306
- Spell Near Damage: 3060
*/

#include "./PlayerSys.dnh"

let ANIM_STRAIGHT = [AddAnimation(), AddAnimation()];
let ANIM_LEFT_TO = [AddAnimation(), AddAnimation()];
let ANIM_RIGHT_TO = [AddAnimation(), AddAnimation()];
let ANIM_LEFT_FROM = [AddAnimation(), AddAnimation()];
let ANIM_RIGHT_FROM = [AddAnimation(), AddAnimation()];
let ANIM_LEFT = [AddAnimation(), AddAnimation()];
let ANIM_RIGHT = [AddAnimation(), AddAnimation()];

let current = CSD;
let character = 0;
let upAngle = -90;

let sndGraze;
let sndShot;
let sndSpellShot;
let sndSpell;
let sndDeath;

SetShotData(CSD ~ "KirishimaShotData.dnh");
SetPlayerTexture(CSD ~ "Textures/Player.png");
SetHitboxRadius(0);
SetHitboxPosition(0, 5);
SetGrazeRadius(24);
SetTurnDuration(12);
SetSpellRestock(true);
SetSpellCount(3);
SetPlayerDownStateFrame(90);
SetPlayerRebirthFrame(10);

function Init()
{
	LoadTextures();
	LoadSounds();

	//Animation definitions
	ascent (ind in 0 .. 2)
	{
		AddFrame(ANIM_STRAIGHT[ind], 64 * 0, ind * 256, 64 * 1, ind * 256 + 64);
		AddFrame(ANIM_STRAIGHT[ind], 64 * 1, ind * 256, 64 * 2, ind * 256 + 64);
		AddFrame(ANIM_STRAIGHT[ind], 64 * 2, ind * 256, 64 * 3, ind * 256 + 64);
		AddFrame(ANIM_STRAIGHT[ind], 64 * 3, ind * 256, 64 * 4, ind * 256 + 64);
		AddFrame(ANIM_STRAIGHT[ind], 64 * 4, ind * 256, 64 * 5, ind * 256 + 64);
		AddFrame(ANIM_STRAIGHT[ind], 64 * 3, ind * 256, 64 * 4, ind * 256 + 64);
		AddFrame(ANIM_STRAIGHT[ind], 64 * 2, ind * 256, 64 * 3, ind * 256 + 64);
		AddFrame(ANIM_STRAIGHT[ind], 64 * 1, ind * 256, 64 * 2, ind * 256 + 64);

		AddFrame(ANIM_LEFT_TO[ind], 64 * 5, ind * 256, 64 * 6, ind * 256 + 64);
		AddFrame(ANIM_LEFT_TO[ind], 64 * 7, ind * 256, 64 * 8, ind * 256 + 64);
		AddFrame(ANIM_LEFT_TO[ind], 64 * 1, ind * 256 + 64 * 1, 64 * 2, ind * 256 + 64 * 2);

		AddFrame(ANIM_RIGHT_TO[ind], 64 * 6, ind * 256, 64 * 7, ind * 256 + 64);
		AddFrame(ANIM_RIGHT_TO[ind], 64 * 0, ind * 256 + 64 * 1, 64 * 1, ind * 256 + 64 * 2);
		AddFrame(ANIM_RIGHT_TO[ind], 64 * 0, ind * 256 + 64 * 2, 64 * 1, ind * 256 + 64 * 3);

		AddFrame(ANIM_LEFT_FROM[ind], 64 * 5, ind * 256, 64 * 6, ind * 256 + 64);
		AddFrame(ANIM_LEFT_FROM[ind], 64 * 7, ind * 256, 64 * 8, ind * 256 + 64);
		AddFrame(ANIM_LEFT_FROM[ind], 64 * 1, ind * 256 + 64 * 1, 64 * 2, ind * 256 + 64 * 2);

		AddFrame(ANIM_RIGHT_FROM[ind], 64 * 6, ind * 256, 64 * 7, ind * 256 + 64);
		AddFrame(ANIM_RIGHT_FROM[ind], 64 * 0, ind * 256 + 64 * 1, 64 * 1, ind * 256 + 64 * 2);
		AddFrame(ANIM_RIGHT_FROM[ind], 64 * 0, ind * 256 + 64 * 2, 64 * 1, ind * 256 + 64 * 3);

		AddFrame(ANIM_LEFT[ind], 64 * 2, ind * 256 + 64 * 1, 64 * 3, ind * 256 + 64 * 2);
		AddFrame(ANIM_LEFT[ind], 64 * 3, ind * 256 + 64 * 1, 64 * 4, ind * 256 + 64 * 2);
		AddFrame(ANIM_LEFT[ind], 64 * 4, ind * 256 + 64 * 1, 64 * 5, ind * 256 + 64 * 2);
		AddFrame(ANIM_LEFT[ind], 64 * 5, ind * 256 + 64 * 1, 64 * 6, ind * 256 + 64 * 2);
		AddFrame(ANIM_LEFT[ind], 64 * 4, ind * 256 + 64 * 1, 64 * 5, ind * 256 + 64 * 2);
		AddFrame(ANIM_LEFT[ind], 64 * 3, ind * 256 + 64 * 1, 64 * 4, ind * 256 + 64 * 2);
		AddFrame(ANIM_LEFT[ind], 64 * 2, ind * 256 + 64 * 1, 64 * 3, ind * 256 + 64 * 2);

		AddFrame(ANIM_RIGHT[ind], 64 * 1, ind * 256 + 64 * 2, 64 * 2, ind * 256 + 64 * 3);
		AddFrame(ANIM_RIGHT[ind], 64 * 2, ind * 256 + 64 * 2, 64 * 3, ind * 256 + 64 * 3);
		AddFrame(ANIM_RIGHT[ind], 64 * 3, ind * 256 + 64 * 2, 64 * 4, ind * 256 + 64 * 3);
		AddFrame(ANIM_RIGHT[ind], 64 * 4, ind * 256 + 64 * 2, 64 * 5, ind * 256 + 64 * 3);
		AddFrame(ANIM_RIGHT[ind], 64 * 3, ind * 256 + 64 * 2, 64 * 4, ind * 256 + 64 * 3);
		AddFrame(ANIM_RIGHT[ind], 64 * 2, ind * 256 + 64 * 2, 64 * 3, ind * 256 + 64 * 3);
		AddFrame(ANIM_RIGHT[ind], 64 * 1, ind * 256 + 64 * 2, 64 * 2, ind * 256 + 64 * 3);
	}

	SetPlayerAnimation(ANIM_STRAIGHT[character]);
	HandleAnimations();
	HandleSwitch();
	HandleShots();
	HandleHitbox();
	HandleBoundaries();
	AuraEffect();
	CircleEffect();
}

function LoadTextures()
{
	LoadTexture(CSD ~ "Textures/Player.png");
	LoadTexture(CSD ~ "Textures/Shot.png");
	LoadTexture(CSD ~ "Textures/Hitbox.png");
	LoadTexture(CSD ~ "Textures/ShotDelete.png");
	LoadTexture(CSD ~ "Textures/Graze.png");
}

function LoadSounds()
{
	sndGraze = CreateSound(CSD ~ "Sounds/Graze.wav", 80);
	sndShot = CreateSound(CSD ~ "Sounds/Shot.wav", 70);
	sndSpellShot = CreateSound(CSD ~ "Sounds/SpellShot.wav", 70);
	sndSpell = CreateSound(CSD ~ "Sounds/Spell.wav", 100);
	sndDeath = CreateSound(CSD ~ "Sounds/Death.wav", 100);
	GrazeEffect();
}

function OnEvent()
{
	alternative(GetEventType())
	case (EV_SHOT_DELETE)
	{
		let arg = GetEventArgument(0);
		//[x, y, speed, angle, id, xscale, yscale]
		DeleteEffect(arg[0], arg[1], arg[2], arg[3], arg[4], arg[5], arg[6])
	}
}

task Death()
{
	ObjSound_Play(sndDeath);

	let fade = CreateSprite(GetPlayerX(), GetPlayerY(), GetPlayerTexture(), 0, 255, 255, 255, 255, 1, 1, GetPlayerRenderPriorityI(), BLEND_ALPHA);

	SetAnimation(fade, GetPlayerAnimation());
	Animate(fade);

	let alpha = 255;

	loop (30)
	{
		alpha -= 255 / 30;
		SetObjectAlpha(fade, alpha);

		yield;
	}

	Obj_Delete(fade);
}

task Graze()
{
	ObjSound_Play(sndGraze);
	GrazeEffect();
}

task Spell()
{
	ObjSound_Play(sndSpell);

	let startChar = character;

	let fade = CreateObject();

	SetObjectSprite(fade, CSD ~ "Textures/SpellFade.png");
	ObjRender_SetPosition(fade, GetStgFrameWidth() / 2, GetStgFrameHeight() / 2, 0);
	SetObjectScaleY(fade, GetStgFrameHeight() / 64);
	SetObjectScale(fade, GetStgFrameWidth() / 60, GetStgFrameHeight() / 60);
	Obj_SetRenderPriorityI(fade, GetPlayerRenderPriorityI() - 5);
	
	let alpha = 0;

	FadeObject(fade, 0, 192, 10);

	let x0 = GetStgFrameWidth() / 2 + 64;
	let y0 = GetStgFrameHeight() / 1.75;
	let shade0 = 96;
	let rp0 = -4;
	if (startChar == 0)
	{
		shade0 = 255;
		rp0 = -3;
	}
	let cutin0 = CreateSprite(x0, y0, CSD ~ "Textures/Cutin0.png", 0, 0, shade0, shade0, shade0, 0.75, 0.75, GetPlayerRenderPriorityI() + rp0, BLEND_ALPHA);
	FadeObject(cutin0, 0, 255, 10);
	PauseFade(cutin0, 30);
	FadeObjectToDelete(cutin0, 255, 90);
	MoveObject(cutin0, x0 + 58, y0, 70);
	MoveObject(cutin0, x0 + 256, y0, 60);

	let x1 = GetStgFrameWidth() / 2 - 64;
	let y1 = GetStgFrameHeight() / 1.75;
	let shade1 = 96;
	let rp1 = -4;
	if (startChar == 1)
	{
		shade1 = 255;
		rp1 = -3;
	}
	let cutin1 = CreateSprite(x1, y1, CSD ~ "Textures/Cutin1.png", 0, 0, shade1, shade1, shade1, 0.75, 0.75, GetPlayerRenderPriorityI() + rp1, BLEND_ALPHA);
	FadeObject(cutin1, 0, 255, 10);
	PauseFade(cutin1, 30);
	FadeObjectToDelete(cutin1, 255, 90);
	MoveObject(cutin1, x1 - 58, y1, 70);
	MoveObject(cutin1, x1 - 256, y1, 60);

	DeleteShotInCircle(TYPE_SHOT, TYPE_ITEM, GetPlayerX(), GetPlayerY(), 128);

	wait(20);

	let x = GetPlayerX();
	let y = GetPlayerY();

	if (startChar == 0)
	{
		let circle = CreateSprite(x, GetStgFrameHeight() - 16, CSD ~ "Textures/SpellCircle.png", 0, 0, 255, 255, 255, 0.5, 0.5, GetPlayerRenderPriorityI() - 1, BLEND_ALPHA);

		FadeObject(circle, 0, 192, 20);
		ScaleObject(circle, 0.25, 40);
		RotateObject(circle, 360, 180);

		wait(5);

		loop (30)
		{
			ObjSound_Play(sndSpellShot);
			DeleteShotInCircle(TYPE_SHOT, TYPE_ITEM, GetPlayerX(), GetPlayerY(), 128);
			CreatePlayerShotCS(x, GetStgFrameHeight() - 32, 12, upAngle, 24.0, 1, 1, 255, 127, 127, 2, 2);
			CreatePlayerShotCS(x + 8, GetStgFrameHeight(), 12, upAngle, 21.0, 1, 1, 255, 127, 127, 2, 2);
			CreatePlayerShotCS(x - 8, GetStgFrameHeight(), 12, upAngle, 21.0, 1, 1, 255, 127, 127, 2, 2);
			wait(5);
		}

		FadeObjectToDelete(circle, 192, 20);
	}
	else
	{
		let circle = CreateSprite(x, y, CSD ~ "Textures/SpellCircle.png", 0, 0, 255, 255, 255, 0.3, 0.3, GetPlayerRenderPriorityI() - 1, BLEND_ALPHA);

		FadeObject(circle, 0, 192, 20);
		ScaleObject(circle, 0.2, 40);
		RotateObject(circle, 360, 180);

		let angle = upAngle - 60 + ((120 / 30) / 2);
		let delay = 50;

		loop (30)
		{
			ObjSound_Play(sndSpellShot);
			DeleteShotInCircle(TYPE_SHOT, TYPE_ITEM, GetPlayerX(), GetPlayerY(), 128);

			let obj;

			obj = CreatePlayerShotCS(x, y, 6, angle, 34, 1, 1, 255, 192, 192, 0.8, 2);
			ObjMove_AddPatternA2(obj, 1, NO_CHANGE, NO_CHANGE, -6 / 40, 0, 0);
			ObjMove_AddPatternA2(obj, delay, NO_CHANGE, NO_CHANGE, 6 / 40, 0, 12);

			obj = CreatePlayerShotCS(x, y, 4, angle, 34, 1, 1, 255, 192, 192, 0.8, 2);
			ObjMove_AddPatternA2(obj, 1, NO_CHANGE, NO_CHANGE, -4 / 40, 0, 0);
			ObjMove_AddPatternA2(obj, delay, NO_CHANGE, NO_CHANGE, 6 / 40, 0, 12);

			obj = CreatePlayerShotCS(x, y, 2, angle, 34, 1, 1, 255, 192, 192, 0.8, 2);
			ObjMove_AddPatternA2(obj, 1, NO_CHANGE, NO_CHANGE, -2 / 40, 0, 0);
			ObjMove_AddPatternA2(obj, delay, NO_CHANGE, NO_CHANGE, 6 / 40, 0, 12);

			angle += 120 / 30;
			delay--;

			wait(1);
		}
		
		wait(20);

		loop (20)
		{
			ObjSound_Play(sndSpellShot);
			wait(1);
		}

		loop (45)
		{
			DeleteShotInCircle(TYPE_SHOT, TYPE_ITEM, GetPlayerX(), GetPlayerY(), 128);
			wait(2);
		}

		FadeObjectToDelete(circle, 192, 20);
	}

	FadeObjectToDelete(fade, 192, 10);

	EndSpell();
}


task HandleAnimations()
{
	loop
	{
		alternative (GetAction())
		case (ACTION_STRAIGHT)
		{
			if (GetActionChanged())
			{
				SetPlayerAnimation(ANIM_STRAIGHT[character]);
			}
		}
		case (ACTION_LEFT)
		{
			if (GetActionChanged())
			{
				SetPlayerAnimation(ANIM_LEFT[character]);
			}
		}
		case (ACTION_RIGHT)
		{
			if (GetActionChanged())
			{
				SetPlayerAnimation(ANIM_RIGHT[character]);
			}
		}
		case (ACTION_LEFT_TO)
		{
			if (GetActionChanged())
			{
				SetPlayerAnimation(ANIM_LEFT_TO[character]);
			}
			SetPlayerFrame(GetTurnFrame());
		}
		case (ACTION_RIGHT_TO)
		{
			if (GetActionChanged())
			{
				SetPlayerAnimation(ANIM_RIGHT_TO[character]);
			}
			SetPlayerFrame(GetTurnFrame());
		}
		case (ACTION_LEFT_FROM)
		{
			if (GetActionChanged())
			{
				SetPlayerAnimation(ANIM_LEFT_FROM[character]);
			}
			SetPlayerFrame(GetTurnFrame());
		}
		case (ACTION_RIGHT_FROM)
		{
			if (GetActionChanged())
			{
				SetPlayerAnimation(ANIM_RIGHT_FROM[character]);
			}
			SetPlayerFrame(GetTurnFrame());
		}
		yield;
	}
}

task HandleSwitch()
{
	loop
	{
		/* USER1 switch
		if (GetVirtualKeyState(VK_USER1) == KEY_PUSH)
		{
			if (character == 0)
			{
				character = 1;
				SetPlayerAnimation(GetPlayerAnimation() + 1);
			}
			else
			{
				character = 0;
				SetPlayerAnimation(GetPlayerAnimation() - 1);
			}
		}
		*/

		//Focus switch
		if (GetVirtualKeyState(VK_SLOWMOVE) == KEY_PUSH)
		{
			if (character == 0)
			{
				character = 1;
				SetPlayerAnimation(GetPlayerAnimation() + 1);
			}
		}
		else if (GetVirtualKeyState(VK_SLOWMOVE) == KEY_PULL)
		{
			if (character == 1)
			{
				character = 0;
				SetPlayerAnimation(GetPlayerAnimation() - 1);
			}
		}

		yield;
	}
}

task HandleShots()
{
	loop
	{
		if (GetShooting() && GetAlive())
		{
			if (character == 0)
			{
				CreatePlayerShotCS(GetPlayerX(), GetPlayerY(), 12, upAngle, 9.0, 1, 1, 255, 160, 160, 0.8, 1.3);
				CreatePlayerShotCS(GetPlayerX(), GetPlayerY(), 12, upAngle - 20, 4.0, 1, 1, 255, 160, 160, 0.8, 1.3);
				CreatePlayerShotCS(GetPlayerX(), GetPlayerY(), 12, upAngle - 40, 3.0, 1, 1, 255, 160, 160, 0.8, 1.3);
				CreatePlayerShotCS(GetPlayerX(), GetPlayerY(), 12, upAngle - 60, 3.0, 1, 1, 255, 160, 160, 0.8, 1.3);
				CreatePlayerShotCS(GetPlayerX(), GetPlayerY(), 12, upAngle + 20, 4.0, 1, 1, 255, 160, 160, 0.8, 1.3);
				CreatePlayerShotCS(GetPlayerX(), GetPlayerY(), 12, upAngle + 40, 3.0, 1, 1, 255, 160, 160, 0.8, 1.3);
				CreatePlayerShotCS(GetPlayerX(), GetPlayerY(), 12, upAngle + 60, 3.0, 1, 1, 255, 160, 160, 0.8, 1.3);
				ObjSound_Play(sndShot);
			}
			else
			{
				CreatePlayerShotCS(GetPlayerX(), GetPlayerY() - 16, 12, upAngle, 5.5, 1, 1, 255, 160, 160, 0.8, 2);
				CreatePlayerShotCS(GetPlayerX() + 10, GetPlayerY() - 12, 12, upAngle, 4.5, 1, 1, 255, 160, 160, 0.8, 2);
				CreatePlayerShotCS(GetPlayerX() - 10, GetPlayerY() - 12, 12, upAngle, 4.5, 1, 1, 255, 160, 160, 0.8, 2);
				CreatePlayerShotCS(GetPlayerX() + 20, GetPlayerY() - 8, 12, upAngle, 4.0, 1, 1, 255, 160, 160, 0.8, 2);
				CreatePlayerShotCS(GetPlayerX() - 20, GetPlayerY() - 8, 12, upAngle, 4.0, 1, 1, 255, 160, 160, 0.8, 2);
				ObjSound_Play(sndShot);
			}
		}

		wait(4);

		yield;
	}
}

task HandleHitbox()
{
	let hitbox = CreateSprite(0, 0, CSD ~ "Textures/Hitbox.png", 0, 0, 255, 255, 255, 1, 1, GetShotRenderPriorityI() + 1, BLEND_ALPHA);
	AttachObject(hitbox, objPlayer, 0, 5);

	let alpha = 0;
	
	loop
	{
		if (GetFocusing() && GetAlive())
		{
			alpha = min(255, alpha + 255 / 10);
		}
		else
		{
			alpha = max(0, alpha - 255 / 10);
		}

		SetObjectAlpha(hitbox, alpha);
		yield;
	}
}

task HandleBoundaries()
{
	loop
	{
		if (GetPlayerX() < 12)
		{
			ObjMove_SetX(objPlayer, 12);
		}
		else if (GetPlayerX() > GetStgFrameWidth() - 12)
		{
			ObjMove_SetX(objPlayer, GetStgFrameWidth() - 12);
		}
		if (GetPlayerY() < 12)
		{
			ObjMove_SetY(objPlayer, 12);
		}
		else if (GetPlayerY() > GetStgFrameHeight() - 12)
		{
			ObjMove_SetY(objPlayer, GetStgFrameHeight() - 12);
		}

		yield;
	}
}

task AuraEffect()
{
	let obj = CreateSprite(0, 0, CSD ~ "Textures/Player.png", 0, 96, 255, 255, 255, 1, 1, GetPlayerRenderPriorityI() - 1, BLEND_ADD_ARGB);

	loop
	{
		let state = GetPlayerState();

		if (state != STATE_DOWN && state != STATE_END)
		{
			Obj_SetVisible(obj, true);

			if (character == 0)
			{
				ObjSprite2D_SetSourceRect(obj, 320, 128, 384, 128 + 68);
				ObjSprite2D_SetDestCenter(obj);
			}
			else
			{
				ObjSprite2D_SetSourceRect(obj, 320, 256 + 128, 384, 256 + 128 + 68);
				ObjSprite2D_SetDestCenter(obj);
			}
			ObjRender_SetPosition(obj, ObjRender_GetX(objPlayer), ObjRender_GetY(objPlayer) + 8, 0);
		}
		else
		{
			Obj_SetVisible(obj, false);
		}
		yield;
	}
}

task DeleteEffect(x, y, speed, angle, id, xscale, yscale)
{
	let ret = CreateSprite(x, y, CSD ~ "Textures/ShotDelete.png", 0, 255, 255, 255, 255, 0.7, 0.7, GetShotRenderPriorityI() + 1, BLEND_ADD_ARGB);
	let time = 20;
	let maxtime = 20;
	let scale = 0.7;

	while (time > 0)
	{
		ObjRender_SetPosition(ret, x, y, 0);
		ObjRender_SetScaleXYZ(ret, scale, scale, 0);
		SetObjectAlpha(ret, (time / maxtime) * 255);
		
		x += cos(angle) * speed / 2;
		y += sin(angle) * speed / 2;
		speed /= 1.05;
		scale += 0.025;

		time--;
		yield;
	}

	Obj_Delete(ret);
}

task CircleEffect()
{
	let obj = CreateSprite(0, 0, CSD ~ "Textures/Player.png", 0, 255, 255, 255, 255, 0.66, 0.66, GetPlayerRenderPriorityI() - 1, BLEND_ADD_ARGB);

	AttachObject(obj, objPlayer, 0, 6);
	ObjSprite2D_SetSourceRect(obj, 384, 320, 512, 448);
	ObjSprite2D_SetDestCenter(obj);

	let life = 0;

	loop
	{
		let state = GetPlayerState();

		if (state != STATE_DOWN && state != STATE_END)
		{
			Obj_SetVisible(obj, true);
			ObjRender_SetAngleZ(obj, ObjRender_GetAngleZ(obj) - 2);
			SetObjectAlpha(obj, 192 + 64 * sin(life * 3));
		}
		else
		{
			Obj_SetVisible(obj, false);
		}

		life++;
		yield;
	}
}

task GrazeEffect()
{
	let obj = CreateObject();

	SetObjectSprite(obj, CSD ~ "Textures/Graze.png");
	ObjRender_SetAngleZ(obj, rand(0, 360));
	Obj_SetRenderPriorityI(obj, GetPlayerRenderPriorityI() + 2);

	let alpha = 255;
	let scale = 0.5;

	loop (10)
	{
		SetObjectScale(obj, scale, scale);
		SetObjectAlpha(obj, alpha);

		scale += 0.33 / 10;
		alpha -= 255 / 10;

		ObjRender_SetPosition(obj, GetPlayerX(), GetPlayerY() + 5, 0);

		yield;
	}

	Obj_Delete(obj);
}