#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 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 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); }