372 lines
8.9 KiB
Plaintext
372 lines
8.9 KiB
Plaintext
#TouhouDanmakufu[Single]
|
|
#ScriptVersion[3]
|
|
#Title["Remilia Spell 3 (Sakuya Card)"]
|
|
#Text["yassification"]
|
|
#System["script/KevinSystem/Kevin_System.txt"]
|
|
|
|
int difficultySelect = 0;
|
|
|
|
let objScene = GetEnemyBossSceneObjectID();
|
|
let csd = GetCurrentScriptDirectory();
|
|
|
|
let bossObj;
|
|
|
|
float bossX = 0;
|
|
float bossY = 0;
|
|
float playerY = 0;
|
|
float playerX = 0;
|
|
|
|
let aniframe = 0;
|
|
let aniframe2 = 0;
|
|
|
|
let spellsnd = ObjSound_Create();
|
|
let bossdiesnd = ObjSound_Create();
|
|
|
|
/*
|
|
Parameters:
|
|
|
|
- Movement speed (in frames)
|
|
- Ring density
|
|
- Ring speed
|
|
|
|
- Density of one knife line
|
|
- Speed of knives
|
|
|
|
- Number of knife rings
|
|
- Density of each knife ring
|
|
- Speed of each knife ring
|
|
*/
|
|
|
|
int[] frameMove = [9*27, 9*25, 9*23]; // Divisible by 9
|
|
int[] denseRing = [15, 18, 21];
|
|
int[] speedRing = [4, 5, 6];
|
|
|
|
int[] denseKnifeLine = [5, 6, 7];
|
|
float[] speedKnife = [8, 9, 10];
|
|
float[] spaceKnifeFan = [5, 7, 9];
|
|
|
|
int[] ringcountKnife = [3, 5, 7];
|
|
int[] ringdenseKnife = [10, 12, 14];
|
|
float[] ringspeedKnife = [8, 9, 10];
|
|
|
|
// Includes ahoy
|
|
|
|
#include "script/KevinSystem/Universal_Lib.txt" // The library to include all libraries :sans: :nail_care:
|
|
|
|
@Initialize {
|
|
|
|
//SetIntersectionVisualization(true);
|
|
|
|
SetAutoDeleteObject(true);
|
|
|
|
_InitDifficulty(difficultySelect);
|
|
|
|
difficultySelect = 0; // debug
|
|
|
|
SetShotAutoDeleteClip(64, 64, 64, 64);
|
|
|
|
if(!IsCommonDataAreaExists("PIV")){
|
|
CreateCommonDataArea("PIV");
|
|
SetAreaCommonData("PIV", "currentvalue", 10000);
|
|
}
|
|
else{}
|
|
|
|
// Create the boss object itself
|
|
bossObj = ObjEnemy_Create(OBJ_ENEMY_BOSS);
|
|
ObjEnemy_Regist(bossObj);
|
|
|
|
ObjMove_SetPosition(bossObj, GetCommonData("Boss Position X", STG_WIDTH/2), GetCommonData("Boss Position Y", STG_HEIGHT/2));
|
|
ObjEnemy_SetMaximumDamage(bossObj, 999);
|
|
|
|
// PLACEHOLDER!
|
|
let imgExRumia = GetModuleDirectory() ~ "script/ExRumia/ExRumia.png";
|
|
ObjPrim_SetTexture(bossObj, imgExRumia);
|
|
ObjSprite2D_SetSourceRect(bossObj, 64, 1, 127, 64);
|
|
ObjSprite2D_SetDestCenter(bossObj);
|
|
ObjRender_SetScaleXYZ(bossObj, 2, 2, 1);
|
|
ObjRender_SetColor(bossObj, 0xB93C3C);
|
|
ObjMove_SetDestAtFrame(bossObj, STG_WIDTH/2, 550, 1);
|
|
// PLACEHOLDER!
|
|
|
|
/*_SoloCutin(
|
|
"script/invalid.png",
|
|
0, 0, 1, 1,
|
|
bossObj, objScene, "\"Euphoric Blooming of a New Market\"",
|
|
40, 4, 0x2868B9, 0x1D115D,
|
|
10, STG_HEIGHT*1/10-30, 41
|
|
);*/
|
|
|
|
//WriteLog(spellPIV);
|
|
WriteLog(ObjEnemyBossScene_GetInfo(objScene, INFO_SPELL_SCORE));
|
|
|
|
mainTask();
|
|
_FadeInvincibility(bossObj, 150, 150, 1);
|
|
endingnew();
|
|
}
|
|
|
|
@Event {
|
|
|
|
alternative(GetEventType())
|
|
|
|
case(EV_REQUEST_LIFE) {
|
|
SetScriptResult(5200);
|
|
}
|
|
|
|
case(EV_REQUEST_TIMER) {
|
|
SetScriptResult(40);
|
|
}
|
|
|
|
}
|
|
|
|
@MainLoop {
|
|
|
|
playerY = GetPlayerY();
|
|
playerX = GetPlayerX();
|
|
//The player position is ALWAYS UPDATED
|
|
|
|
bossX = ObjMove_GetX(bossObj);
|
|
bossY = ObjMove_GetY(bossObj);
|
|
|
|
ObjEnemy_SetIntersectionCircleToShot(bossObj, ObjMove_GetX(bossObj), ObjMove_GetY(bossObj), 100);
|
|
|
|
yield;
|
|
|
|
}
|
|
|
|
@Finalize {
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
Spell 3 (Sakuya):
|
|
|
|
Remilia moves to the horizontal middle and starts slowly moving from top to bottom, firing slow red rings. As she moves, she fires bursts of knives to the sides that reflect off the walls towards the player (one burst per 3 rings).
|
|
When she reaches the bottom, she fires a large burst of knives everywhere, following the same reflecting formula.
|
|
|
|
Parameters:
|
|
|
|
- Movement speed (in frames)
|
|
- Ring density
|
|
- Ring speed
|
|
|
|
- Density of one knife line
|
|
- Speed of knives
|
|
|
|
- Number of knife rings
|
|
- Density of each knife ring
|
|
- Speed of each knife ring
|
|
|
|
*/
|
|
|
|
task mainTask {
|
|
|
|
_Warn();
|
|
wait(45);
|
|
|
|
while(ObjEnemy_GetInfo(bossObj, INFO_LIFE) > 0){
|
|
|
|
MoveToBottom();
|
|
//BurstAttack();
|
|
//wait(360);
|
|
wait(frameMove[difficultySelect]*2);
|
|
}
|
|
|
|
}
|
|
|
|
task _Warn(){
|
|
|
|
int time = 30;
|
|
int timeDisappear = 45;
|
|
|
|
int pointText = CreateTextObject(
|
|
STG_WIDTH/2, 5.5*STG_HEIGHT/6, 120,
|
|
"WATCH OUT!", "Exotc350 DmBd BT",
|
|
0xFF6868, 0xFFFFFF,
|
|
0x800E0E, 6,
|
|
51
|
|
);
|
|
ObjText_SetHorizontalAlignment(pointText, ALIGNMENT_CENTER);
|
|
|
|
ascent(i in 0..time){
|
|
ObjRender_SetAlpha(pointText, Interpolate_Decelerate(0, 255, i/time));
|
|
ObjRender_SetY(pointText, Interpolate_Decelerate(5.2*STG_HEIGHT/6, 5*STG_HEIGHT/6, i/time));
|
|
yield;
|
|
}
|
|
|
|
wait(30);
|
|
|
|
ascent(i in 0..timeDisappear){
|
|
ObjRender_SetAlpha(pointText, Interpolate_Decelerate(255, 0, i/timeDisappear));
|
|
yield;
|
|
}
|
|
Obj_Delete(pointText);
|
|
|
|
}
|
|
|
|
function <void> MoveToBottom(){
|
|
|
|
float x = GetPlayerX();
|
|
|
|
ObjMove_SetDestAtFrame(bossObj, x, STG_HEIGHT/7, 45, LERP_DECELERATE);
|
|
wait(60);
|
|
|
|
// Anti-cheese
|
|
|
|
async{
|
|
loop(60){
|
|
int shot = CreateShotA1(bossX, bossY, 15, rand(180, 360), KEV_BUBBLE_RED, 10);
|
|
if(ObjEnemy_GetInfo(bossObj, INFO_LIFE) == 0){Obj_Delete(shot);}
|
|
else{
|
|
_Delay(shot, 10);
|
|
_BulletRescale(shot, 0.8, true, 1);
|
|
Shoot1;
|
|
}
|
|
yield;
|
|
}
|
|
}
|
|
|
|
// Slow movement
|
|
|
|
ObjMove_SetDestAtFrame(bossObj, x, 5.5*STG_HEIGHT/6, frameMove[difficultySelect], LERP_SMOOTHER);
|
|
|
|
async{
|
|
loop(9){
|
|
|
|
float ang = GetAngleToPlayer(bossObj);
|
|
float[] spawn = [bossX+rand(-30, 30), bossY+rand(-30, 30)];
|
|
|
|
ascent(i in -1..denseRing[difficultySelect]-1){
|
|
int shot = CreateShotA2(spawn[0], spawn[1], speedRing[difficultySelect], ang+(360/denseRing[difficultySelect])*i, -speedRing[difficultySelect]/[30, 35, 40][difficultySelect], 0, KEV_AURABALL_RED, 10);
|
|
if(ObjEnemy_GetInfo(bossObj, INFO_LIFE) == 0){Obj_Delete(shot);}
|
|
else{
|
|
ObjMove_AddPatternA2(shot, frameMove[difficultySelect]/1.5, NO_CHANGE, NO_CHANGE, speedRing[difficultySelect]/45, speedRing[difficultySelect], 0);
|
|
_Delay(shot, 10);
|
|
_BulletRescale(shot, 0.6, true, 1);
|
|
Shoot1;
|
|
}
|
|
}
|
|
|
|
wait(frameMove[difficultySelect]/9);
|
|
}
|
|
|
|
// If you're at bottom, you die. (Hyper and above)
|
|
|
|
if(difficultySelect >= 0){
|
|
loop(9){
|
|
|
|
float ang = GetAngleToPlayer(bossObj);
|
|
float[] spawn = [bossX+rand(-25, 25), bossY+rand(-25, 25)];
|
|
|
|
ascent(i in -1..denseRing[difficultySelect]-1){
|
|
int shot = CreateShotA2(spawn[0], spawn[1], speedRing[difficultySelect]*2.5, ang+(360/denseRing[difficultySelect])*i, -speedRing[difficultySelect]*2.5/[30, 40, 45][difficultySelect], speedRing[difficultySelect]*[0.3, 0.2, 0.1][difficultySelect], KEV_KNIFE_RED, 10);
|
|
if(ObjEnemy_GetInfo(bossObj, INFO_LIFE) == 0){Obj_Delete(shot);}
|
|
else{
|
|
ObjMove_AddPatternA2(shot, 90, NO_CHANGE, NO_CHANGE, speedRing[difficultySelect]/45, speedRing[difficultySelect]*[1.65, 1.4, 1.25][difficultySelect], 0);
|
|
_Delay(shot, 10);
|
|
ObjRender_SetBlendType(shot, BLEND_ADD_ARGB);
|
|
_BulletRescale(shot, 1.25, true, 1);
|
|
Shoot1;
|
|
if(difficultySelect >= 1){_ReflectToPlayer(shot);}
|
|
}
|
|
}
|
|
|
|
wait(frameMove[difficultySelect]/36);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
async{
|
|
loop(3){
|
|
|
|
CreateFan(3, KEV_KNIFE_LAVENDER, denseKnifeLine[difficultySelect],
|
|
0, spaceKnifeFan[difficultySelect], speedKnife[difficultySelect]/1.3, speedKnife[difficultySelect], 1.25,
|
|
PATTERN_FAN, true);
|
|
|
|
CreateFan(3, KEV_KNIFE_LAVENDER, denseKnifeLine[difficultySelect],
|
|
180, spaceKnifeFan[difficultySelect], speedKnife[difficultySelect]/1.3, speedKnife[difficultySelect], 1.25,
|
|
PATTERN_FAN, true);
|
|
|
|
wait(frameMove[difficultySelect]/3);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
function <int> CreateFan (int way, int graphic, int stack,
|
|
float ang, float angspace, float spd1, float spd2, float scale,
|
|
int type, bool reflect){
|
|
|
|
int objPattern = ObjPatternShot_Create();
|
|
|
|
ObjPatternShot_SetParentObject(objPattern, bossObj);
|
|
|
|
if(ObjEnemyBossScene_GetInfo(GetEnemyBossSceneObjectID(), INFO_CURRENT_LIFE) == 0){Obj_Delete(objPattern); return;}
|
|
|
|
ObjPatternShot_SetPatternType(objPattern, type); // PATTERN_FAN or PATTERN_FAN_AIMED
|
|
ObjPatternShot_SetShotType(objPattern, OBJ_SHOT);
|
|
ObjPatternShot_SetInitialBlendMode(objPattern, BLEND_ALPHA);
|
|
|
|
ObjPatternShot_SetShotCount(objPattern, way, stack);
|
|
ObjPatternShot_SetSpeed(objPattern, spd1, spd2);
|
|
ObjPatternShot_SetAngle(objPattern, ang, angspace);
|
|
|
|
ObjPatternShot_SetBasePointOffset(objPattern, 0, 0);
|
|
//ObjPatternShot_SetDelay(objPattern, 15);
|
|
ObjPatternShot_SetGraphic(objPattern, graphic);
|
|
|
|
Shoot2;
|
|
int[] arrayPattern = ObjPatternShot_FireReturn(objPattern);
|
|
|
|
for each (int bullet in ref arrayPattern){
|
|
_BulletRescale(bullet, scale, true, 1);
|
|
_Delay(bullet, 10);
|
|
_EnemyShotFade(bullet, 600, true, 2.5); // Placeholder
|
|
Obj_SetRenderPriorityI(bullet, 51);
|
|
if (reflect) {_ReflectToPlayer(bullet);}
|
|
}
|
|
|
|
async{
|
|
wait(600);
|
|
Obj_Delete(objPattern);
|
|
return;
|
|
}
|
|
|
|
return objPattern;
|
|
|
|
}
|
|
|
|
task _ReflectToPlayer(int target){
|
|
|
|
ObjShot_SetAutoDelete(target, false);
|
|
|
|
while(!Obj_IsDeleted(target)){
|
|
if(ObjEnemy_GetInfo(bossObj, INFO_LIFE) == 0){Obj_Delete(target); return;}
|
|
if (ObjMove_GetX(target) <= -15 || ObjMove_GetX(target) >= GetStgFrameWidth()+15){
|
|
ObjMove_AddPatternA4(target, 0, NO_CHANGE, 0, NO_CHANGE, NO_CHANGE, 0, KEV_KNIFE_GREEN, GetPlayerObjectID());
|
|
Shoot2;
|
|
ObjShot_SetAutoDelete(target, true);
|
|
break;
|
|
}
|
|
yield;
|
|
}
|
|
|
|
}
|
|
|
|
task endingnew(){
|
|
|
|
while(ObjEnemy_GetInfo(bossObj, INFO_LIFE)>0){
|
|
yield;
|
|
}
|
|
|
|
_GoToBrazil(objScene, bossObj, 12, 24);
|
|
wait(120);
|
|
ObjSound_SetVolumeRate(fire2, 20);
|
|
|
|
CloseScript(GetOwnScriptID);
|
|
|
|
}
|
|
|
|
|