ScarletBlackMarket/script/game/Spell3.dnh

390 lines
9.2 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 = [14, 16, 20];
int[] speedRing = [4, 5, 6];
int[] denseKnifeLine = [4, 5, 6];
float[] speedKnife = [8, 10, 12];
float[] spaceKnifeFan = [4, 6, 8];
int[] ringcountKnife = [3, 5, 7];
int[] ringdenseKnife = [10, 12, 14];
float[] ringspeedKnife = [8, 9, 10];
// Includes ahoy
string tex = "script/game/resourceLib/Spritesheet_StationJam.png";
//LoadTextureEx(tex, true, false);
#include "script/KevinSystem/Universal_Lib.txt" // The library to include all libraries :sans: :nail_care:
@Initialize {
//SetIntersectionVisualization(true);
SetAutoDeleteObject(true);
LoadTextureEx(tex, true, false);
_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);
_RenderBoss(bossObj);
//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), 180);
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 {
ObjMove_SetDestAtFrame(bossObj, STG_WIDTH/2, STG_HEIGHT/2
, 45, LERP_DECELERATE);
wait(45);
_UseCard();
_Warn();
wait(45);
while(ObjEnemy_GetInfo(bossObj, INFO_LIFE) > 0){
MoveToBottom();
//BurstAttack();
//wait(360);
wait(frameMove[difficultySelect]*1.75);
}
}
function <void> _UseCard(){
// Remi spell
int cardImg = _Create2DImage(tex, [512, 256, 768, 512]);
ObjRender_SetPosition(cardImg, bossX, bossY, 0);
ascent(i in 0..30){
ObjRender_SetY(cardImg, Interpolate_Decelerate(bossY, bossY - 256, i/30));
ObjRender_SetAlpha(cardImg, Interpolate_Decelerate(0, 255, i/30));
yield;
}
wait(30);
ascent(i in 0..15){
ObjRender_SetAlpha(cardImg, Interpolate_Decelerate(255, 0, i/15));
yield;
}
Obj_Delete(cardImg);
}
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([6, 7, 9][difficultySelect]){
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_LAVENDER, 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);
Shoot2;
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.18, speedKnife[difficultySelect], 1.25,
PATTERN_FAN, true);
CreateFan(3, KEV_KNIFE_LAVENDER, denseKnifeLine[difficultySelect],
180, spaceKnifeFan[difficultySelect], speedKnife[difficultySelect]/1.18, 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());
Shoot1;
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);
}