274 lines
6.6 KiB
Plaintext
274 lines
6.6 KiB
Plaintext
#TouhouDanmakufu[Single]
|
|
#ScriptVersion[3]
|
|
#Title["the fruit of your labors, part 1"]
|
|
#Text["ayyy lmao"]
|
|
|
|
// Declaring variables
|
|
|
|
// Boss positions + Boss graphic + Shot sheet
|
|
let bossObj;
|
|
let bossX = 0; //These are important
|
|
let bossY = 0;
|
|
|
|
//Animation frames
|
|
let aniframe = 0;
|
|
let aniframe2 = 0;
|
|
|
|
let imgBoss = "script/basic4/sprite/enm_yuyuko.png";
|
|
let angleO = 90;
|
|
let wintery = "script/basic4/sprite/cardbg3.png";
|
|
let sakura = "script/basic4/sprite/cardbg4.png";
|
|
|
|
let spellSFX = "script/basic4/sounds/cardstart.wav";
|
|
let bossdefeatSFX = "script/basic4/sounds/bossdie.wav";
|
|
|
|
#include "script/default_system/Default_ShotConst.txt" // Shot sheet goes here, include DOES NOT include semicolon
|
|
#include "script/default_system/Default_Effect.txt"
|
|
|
|
// Hell
|
|
|
|
@Initialize {
|
|
|
|
// Auto-delete objects when script ends
|
|
SetAutoDeleteObject(true);
|
|
|
|
// Define a bossObj is boss, register into script
|
|
bossObj = ObjEnemy_Create(OBJ_ENEMY_BOSS);
|
|
ObjEnemy_Regist(bossObj);
|
|
|
|
// Start position OUTSIDE playing bounds
|
|
ObjMove_SetPosition(bossObj,192,-100);
|
|
// Moving boss to x, y location at speed
|
|
ObjMove_SetDestAtSpeed(bossObj,192,120,4);
|
|
|
|
// Load sounds
|
|
|
|
LoadSound(spellSFX);
|
|
LoadSound(bossdefeatSFX);
|
|
|
|
//Play sounds
|
|
|
|
PlaySE(spellSFX);
|
|
|
|
mainTask;
|
|
}
|
|
|
|
@Event {
|
|
// Setting boss timer and life
|
|
alternative(GetEventType())
|
|
|
|
case(EV_REQUEST_LIFE) {
|
|
SetScriptResult(2500);
|
|
}
|
|
|
|
case(EV_REQUEST_TIMER) {
|
|
SetScriptResult(30);
|
|
}
|
|
|
|
case(EV_REQUEST_SPELL_SCORE) {
|
|
SetScriptResult(2500000);
|
|
}
|
|
|
|
}
|
|
|
|
//MainLoop - everything always happens, all the time
|
|
@MainLoop {
|
|
bossX = ObjMove_GetX(bossObj);
|
|
bossY = ObjMove_GetY(bossObj);
|
|
//The boss position is ALWAYS UPDATED
|
|
|
|
// Collision for the shots and player
|
|
ObjEnemy_SetIntersectionCircleToShot(bossObj, bossX, bossY, 36);
|
|
ObjEnemy_SetIntersectionCircleToShot(bossObj, bossX, bossY, 18);
|
|
yield; // yielding mainloop tells the script to "look for other tasks" to perform
|
|
}
|
|
|
|
@Finalize {
|
|
|
|
}
|
|
|
|
//Creating functions for simplicity
|
|
function wait(w) {loop(w) {yield;}}
|
|
|
|
task mainTask {
|
|
renderBoss;
|
|
render;
|
|
BossMove;
|
|
ending;
|
|
shotyeet;
|
|
}
|
|
|
|
// NEW : BACKGROUNDS AND SPELL OVERLAYS
|
|
|
|
// Note : textures are objects
|
|
|
|
task render {
|
|
let scrollTex = 0;
|
|
|
|
// BG
|
|
let bgObj = ObjPrim_Create(OBJ_SPRITE_2D);
|
|
// NOTE : Obj_SetRenderPriorityI DIFFERENT FROM Obj_SetRenderPriority
|
|
Obj_SetRenderPriorityI(bgObj,20);
|
|
ObjPrim_SetTexture(bgObj,wintery);
|
|
ObjSprite2D_SetSourceRect(bgObj,0,0,512,512);
|
|
ObjSprite2D_SetDestRect(bgObj,0,0,GetStgFrameWidth,GetStgFrameHeight);
|
|
|
|
// SPELL BG
|
|
let spellObj = ObjPrim_Create(OBJ_SPRITE_2D);
|
|
// RENDER PRIORITY NOTICE : OVERLAY ABOVE BG
|
|
Obj_SetRenderPriorityI(spellObj,21);
|
|
ObjPrim_SetTexture(spellObj,sakura);
|
|
ObjRender_SetBlendType(spellObj,BLEND_ADD_ARGB); // Blending option : ADDITIVE + Alpha + RGB (opacity + glow)
|
|
ObjRender_SetAlpha(spellObj,240);
|
|
ObjSprite2D_SetSourceRect(spellObj,0,0,1024,1024);
|
|
ObjSprite2D_SetDestRect(spellObj,0,0,GetStgFrameWidth,GetStgFrameHeight);
|
|
|
|
// Scroll overlay while boss is alive
|
|
while(!Obj_IsDeleted(bossObj)){
|
|
ObjSprite2D_SetSourceRect(spellObj,0-scrollTex,0-scrollTex,1024-scrollTex,1024-scrollTex);
|
|
scrollTex+=1;
|
|
yield;
|
|
}
|
|
Obj_Delete(spellObj);
|
|
}
|
|
|
|
task fire {
|
|
let playerdir;
|
|
let newdir;
|
|
playerdir = GetAngleToPlayer(bossObj);
|
|
CreateShotA1(bossX,bossY,5,playerdir+10,55,5);
|
|
CreateShotA1(bossX,bossY,5,playerdir+5,55,5);
|
|
CreateShotA1(bossX,bossY,5,playerdir,55,5);
|
|
CreateShotA1(bossX,bossY,5,playerdir-5,55,5);
|
|
CreateShotA1(bossX,bossY,5,playerdir-10,55,5);
|
|
newdir = playerdir-15;
|
|
wait(5);
|
|
|
|
loop(40){
|
|
CreateShotA1(bossX,bossY,5,newdir+10,55,5);
|
|
CreateShotA1(bossX,bossY,5,newdir+5,55,5);
|
|
CreateShotA1(bossX,bossY,5,newdir,55,5);
|
|
CreateShotA1(bossX,bossY,5,newdir-5,55,5);
|
|
CreateShotA1(bossX,bossY,5,newdir-10,55,5);
|
|
newdir = newdir-15;
|
|
wait(5);
|
|
}
|
|
}
|
|
|
|
task renderBoss {
|
|
// Declare local variables, used for this task only
|
|
let dir;
|
|
let speed;
|
|
|
|
// Moved from @Initialize
|
|
|
|
// Giving the bossObj a "texture"
|
|
ObjPrim_SetTexture(bossObj, imgBoss);
|
|
// Which part to render -> remember to base this on the sprite itself
|
|
ObjSprite2D_SetSourceRect(bossObj,0,0,128,128);
|
|
// Moving our boss around from "true centre"
|
|
ObjSprite2D_SetDestCenter(bossObj);
|
|
// Scaling the boss sprite
|
|
ObjRender_SetScaleXYZ(bossObj,1.2,1.2,0);
|
|
// While the boss is not defeated yet
|
|
|
|
while (!Obj_IsDeleted(bossObj)){ // "!" mark means "OPPOSITE of whatever comes next, meaning overall : While boss is NOT DELETED"
|
|
|
|
// Update boss speed/direction
|
|
dir = ObjMove_GetAngle(bossObj);
|
|
speed = ObjMove_GetSpeed(bossObj);
|
|
|
|
// Actual code for animation handling
|
|
|
|
// Idle animation
|
|
if(speed == 0){
|
|
ObjRender_SetAngleXYZ(bossObj,0,0,0);
|
|
|
|
// if (aniframe....) -> IF the aniframe is this value, SHOW this sprite image
|
|
if (aniframe < 15){ObjSprite2D_SetSourceRect(bossObj,0,0,128,128);}
|
|
if (aniframe >= 15 && aniframe < 30){ObjSprite2D_SetSourceRect(bossObj,0,128,128,256);}
|
|
if (aniframe >= 30 && aniframe < 45){ObjSprite2D_SetSourceRect(bossObj,0,256,128,384);}
|
|
if (aniframe >= 45){ObjSprite2D_SetSourceRect(bossObj,128,128,256,256);}
|
|
}
|
|
// Left/Right animation
|
|
else if (cos(dir)<0){
|
|
|
|
aniframe2=0;
|
|
aniframe2+=2;
|
|
if(aniframe2 > 60){aniframe2 = 15;}
|
|
|
|
ObjRender_SetAngleXYZ(bossObj,0,0,0);
|
|
if (aniframe2 < 15){ObjSprite2D_SetSourceRect(bossObj,256,0,384,128);}
|
|
if (aniframe2 >= 15){ObjSprite2D_SetSourceRect(bossObj,256,128,384,256);}
|
|
}
|
|
|
|
else if (cos(dir)>0){
|
|
|
|
aniframe2=0;
|
|
aniframe2+=2;
|
|
if(aniframe2 > 60){aniframe2 = 15;}
|
|
|
|
ObjRender_SetAngleXYZ(bossObj,0,0,0);
|
|
if (aniframe2 < 15){ObjSprite2D_SetSourceRect(bossObj,256,256,384,384);}
|
|
if (aniframe2 >= 15){ObjSprite2D_SetSourceRect(bossObj,256,384,384,512);}
|
|
}
|
|
|
|
//Counting aniframe - ++ = up 1 per frame
|
|
aniframe+=2;
|
|
//Resetting aniframe if over predefined value
|
|
if(aniframe > 60){aniframe = 0;}
|
|
|
|
// These two code lines above will ensure the idle loop.
|
|
|
|
yield;
|
|
}
|
|
}
|
|
|
|
task BossMove{
|
|
|
|
wait(60);
|
|
fire;
|
|
wait(250);
|
|
|
|
loop{
|
|
while(ObjEnemy_GetInfo(bossObj,INFO_LIFE)<=0){return;}
|
|
ObjMove_SetDestAtSpeed(bossObj,rand(10,280),bossY,3);
|
|
wait(30);
|
|
fire;
|
|
wait(250);
|
|
yield;
|
|
}
|
|
|
|
}
|
|
|
|
task ending{
|
|
// While the boss is still alive, keep yielding (script works normally)
|
|
|
|
while(ObjEnemy_GetInfo(bossObj,INFO_LIFE)>0){
|
|
yield;
|
|
}
|
|
|
|
DeleteShotAll(TYPE_ALL,TYPE_ITEM);
|
|
PlaySE(bossdefeatSFX);
|
|
TExplosionA(bossX,bossY,10,0.5);
|
|
wait(120);
|
|
PlaySE(bossdefeatSFX);
|
|
Obj_Delete(bossObj);
|
|
TExplosionA(bossX,bossY,10,0.5);
|
|
wait(120);
|
|
CloseScript(GetOwnScriptID);
|
|
}
|
|
|
|
// I SPENT TWO DAYS TO FIGURE THIS OUT LMAO
|
|
|
|
task shotyeet{
|
|
while(ObjEnemy_GetInfo(bossObj,INFO_LIFE)>0){
|
|
yield;
|
|
}
|
|
|
|
loop{
|
|
DeleteShotAll(TYPE_ALL,TYPE_ITEM);
|
|
yield;
|
|
}
|
|
|
|
} |