#TouhouDanmakufu[Player] #ScriptVersion[3] #ID["ByakMiko"] #Title["Byakuren Hijiri & Toyosatomimi no Miko"] #Text["Unfocused Shot: Indra's Sorcery Buzzsaws[r]An elegant spread of thunder needles.[r][r]Focused Shot: Four Shining Articles[r]A crossing of high-power divine lasers.[r][r]Special Ability: Smaller hitbox."] //#Image["./marimiko_lib/marimiko_illust.png"] #ReplayName["ByakMiko"] #include "script/KevinSystem/Kevin_PlayerLib.txt" #include "script/KevinSystem/PlayerSoundLib.dnh" #include "./ByakMiko_Function.dnh" #include "./ByakMiko_ShotConst.dnh" #include "script/KevinSystem/kevin_system/Kevin_ItemConst.txt" #include "script/KevinSystem/kevin_system/Kevin_ItemLib.txt" let csd = GetCurrentScriptDirectory(); // Global Variables float maxX = GetStgFrameWidth(); float maxY = GetStgFrameHeight(); // Images & Sound let teamimg = csd ~ "./playerlib/ByakMiko_Sheet.png"; LoadTextureEx(teamimg, true, true); //ObjRender_SetTextureFilterMip(teamimg, FILTER_LINEAR); let sndpath = csd ~ "./sound"; // Other stuff float playerX = 0; float playerY = 0; let objPlayer = GetPlayerObjectID(); int plrender = Obj_GetRenderPriorityI(objPlayer); int frameidlebyak = 0; int frameidlemiko = 0; int framemovebyak = 0; int framemovemiko = 0; bool ripplayer = false; float shotspeed = 0; float bombrand = 0; bool bombenable = false; bool focusactive = false; bool ishoming = false; int[] _enemyArray = []; // Prepare an array to store enemy IDs for Kouda's homing shot int[] _existArray = []; int[] _shotArray = []; int grazecounter = 0; // For basic graze = PIV mechanic float[] PlayerSpd = [11.5, 5.8]; // Custom events for scoring mechanic const EV_PIV_100 = EV_USER + 100i; // Normal enemies and nons const EV_PIV_250 = EV_USER + 101i; // Spells const EV_PIV_500 = EV_USER + 102i; // Last Spells const EV_PIV_2000 = EV_USER + 103i; // What. @Initialize{ if(!IsCommonDataAreaExists("PIV")){ CreateCommonDataArea("PIV"); SetAreaCommonData("PIV", "currentvalue", 10000); } else{} SetPlayerStateEndEnable(true); // Stuff parameterrender(); playerrender(); Obj_SetRenderPriorityI(objPlayer, 43); plrender = Obj_GetRenderPriorityI(objPlayer); _SoundTask(); //SetIntersectionVisualization(true); // Debug _Mechanic(ripplayer, _enemyArray, _existArray, GetStgFrameWidth(), GetStgFrameHeight(), objPlayer, GetEnemyBossSceneObjectID(), 5, 2, 80); _HitboxRender(ripplayer, objPlayer, teamimg, teamimg, 2560, 512, 2688, 640, 2816, 1024, 2816+511, 1024+511, 0.22, 0.65); SetShotAutoDeleteClip(256, 256, 256, 256); // Shot functions //_CAVELaser(); ByakShot(); _MikoOption(); // Shot data loading LoadPlayerShotData(csd ~ "./ByakMiko_ShotData.dnh"); } @MainLoop{ shotspeed += 1; // Managing the shot rate //_shotArray = GetAllShotID(TARGET_PLAYER); //UniversalAlphaHandle(_shotArray); playerX = ObjMove_GetX(objPlayer); playerY = ObjMove_GetY(objPlayer); yield; } @Event{ alternative(GetEventType) // Delete effect case(EV_DELETE_SHOT_PLAYER){ let graphic = GetEventArgument(2); float[] position = GetEventArgument(1); let obj = CreatePlayerShotA1(position[0], position[1], 0, ObjMove_GetAngle(GetEventArgument(0)), 0, 99999, graphic); ObjShot_SetIntersectionEnable(obj, false); _DeleteEffect(obj); } // PIV-item spawning events case(EV_PIV_100){ let arg = GetEventArgument(0); CreatePIVItem(PIV_100, arg[0], arg[1]); } case(EV_PIV_250){ let arg = GetEventArgument(0); CreatePIVItem(PIV_250, arg[0], arg[1]); } case(EV_PIV_500){ let arg = GetEventArgument(0); CreatePIVItem(PIV_500, arg[0], arg[1]); } // Basic functionality events case(EV_REQUEST_SPELL){ let bomb = GetPlayerSpell(); if (bomb >= 1){ SetScriptResult(true); SetPlayerSpell(bomb - 1); if(GetVirtualKeyState(VK_SLOWMOVE) != KEY_FREE){_FocusBomb(); _SigilCall(false, teamimg, 2816+256, 512, 2816+512, 768, objPlayer, GetPlayerInvincibilityFrame());} else{_UnfocusBomb(); _SigilCall(false, teamimg, 2816+256, 512, 2816+512, 768, objPlayer, GetPlayerInvincibilityFrame()); } } else { SetScriptResult(false); } } case(EV_HIT){ ObjSound_Play(predeathsfx); _DeathbombWarning(teamimg, [1792, 512, 1792+512, 512+512], 15, 0.75); } case(EV_PLAYER_SHOOTDOWN){ ObjSound_Play(deathsfx); ripplayer = true; _SigilCall(true, teamimg, 2816, 512, 2816+256, 768, objPlayer, 120); } case(EV_PLAYER_REBIRTH){ ripplayer = false; SetPlayerInvincibilityFrame(180); _SigilCall(false, teamimg, 2816+256, 512, 2816+512, 768, objPlayer, 150); SetPlayerSpell( max(2,GetPlayerSpell()) ); } case(EV_GRAZE){ grazecounter += GetEventArgument(0); ObjSound_Play(grazesfx); while(grazecounter >= 10){ SetAreaCommonData("PIV", "currentvalue", GetAreaCommonData("PIV", "currentvalue")+10); grazecounter -= 10; } } } @Finalize{ } task _MikoOption(){ // Offsets for 4 front options float offsetX1 = 90; float offsetX2 = offsetX1 * 2; float offsetY1 = 45; // Array that contains static/unchanging values for the PlayerOption let val = [1792, 256, 2048, 512, 0.65, 256, 1, 1, false, false, 0, true, false]; // Option handling (right -> rightmost -> left -> leftmost) float[][] offsetArray = [[offsetX1, offsetY1], [offsetX2, 0], [-offsetX1, offsetY1], [-offsetX2, 0]]; int opt1 = PlayerOption( offsetArray[0][0], offsetArray[0][1], teamimg, val[0], val[1], val[2], val[3], val[4], val[5], val[6], val[7], val[8], val[9], val[10], val[11], val[12]); int opt2 = PlayerOption( offsetArray[1][0], offsetArray[1][1], teamimg, val[0], val[1], val[2], val[3], val[4], val[5], val[6], val[7], val[8], val[9], val[10], val[11], val[12]); int opt3 = PlayerOption( offsetArray[2][0], offsetArray[2][1], teamimg, val[0], val[1], val[2], val[3], val[4], val[5], val[6], val[7], val[8], val[9], val[10], val[11], val[12]); int opt4 = PlayerOption( offsetArray[3][0], offsetArray[3][1], teamimg, val[0], val[1], val[2], val[3], val[4], val[5], val[6], val[7], val[8], val[9], val[10], val[11], val[12]); int[] optArray = [opt1, opt2, opt3, opt4]; ascent(i in -1..length(optArray)-1){ _SwingBehaviour(optArray[i]); } task _SwingBehaviour(target){ float ang = 0; Obj_SetRenderPriorityI(target, 42); while(true){ ObjRender_SetAngleZ(target, 0+20*sin(ang)); ang += 360/120; yield; } } int laser1 = _RenderLaser(opt1, -7, 300, GetStgFrameHeight*1.25, 65, 0, 2.6); int laser2 = _RenderLaser(opt2, -14, 600, GetStgFrameHeight*1.25, 65, 0, 2.6); int laser3 = _RenderLaser(opt3, 7, 300, GetStgFrameHeight*1.25, 65, 0, 2.6); int laser4 = _RenderLaser(opt4, 14, 600, GetStgFrameHeight*1.25, 65, 0, 2.6); //int laser3 = _RenderLaser(opt3, 0, 300, GetStgFrameHeight*1.25, 50, 0, 5); float focusDist = 280; let dummy = CreatePlayerShotA1(playerX, playerY-focusDist, 0, 0, 0, 99999, 0); ObjShot_SetAutoDelete(dummy, false); ObjShot_SetIntersectionEnable(dummy, false); //ObjMove_AddPatternA4(laser1, 0, NO_CHANGE, 0, NO_CHANGE, NO_CHANGE, NO_CHANGE, NO_CHANGE, dummy); //ObjMove_AddPatternA4(laser2, 0, NO_CHANGE, 0, NO_CHANGE, NO_CHANGE, NO_CHANGE, NO_CHANGE, dummy); } // Miko's lasers // Basic player parameters task parameterrender(){ SetPlayerItemScope(120); SetPlayerLife(9); // Debug SetPlayerSpell(2); SetPlayerSpeed(PlayerSpd[0], PlayerSpd[1]); // (original: 5.25/2.0) SetPlayerRebirthFrame(25); SetPlayerAutoItemCollectLine(GetStgFrameHeight/3); SetPlayerRebirthLossFrame(0); ObjPlayer_AddIntersectionCircleA1(objPlayer, 0, 0, 2.0, 55); } // Renders the shottype // Player sprites task playerrender(){ // Why is this movement code so cursed jesus fucking christ float scale = 0.34; // Scalies ObjPrim_SetTexture(objPlayer, teamimg); ObjSprite2D_SetSourceRect(objPlayer, 0, 0, 320, 384); ObjSprite2D_SetDestCenter(objPlayer); Obj_SetRenderPriorityI(objPlayer, 42); ObjRender_SetScaleXYZ(objPlayer, scale, scale, 1); // Lower "speed" parameter = FASTER SPEED // FOR WHEN ONLY IDLE SPRITES ARE DONE loop{ // Focused if(GetVirtualKeyState(VK_SLOWMOVE) != KEY_FREE){ frameidlemiko++; _RenderPlayerMovement(objPlayer, frameidlemiko, 0, 1152, 320, 384, scale, 4, 5); if (frameidlemiko >= (5*4-1)){frameidlemiko = 0;} } // Unfocused else{ frameidlebyak++; _RenderPlayerMovement(objPlayer, frameidlebyak, 0, 0, 320, 384, scale, 5, 5); if (frameidlebyak >= (5*5-1)){frameidlebyak = 0;} } yield; } } task ByakShot(){ // Offsets for 4 front options float offsetX1 = 75; float offsetX2 = offsetX1 * 2; float offsetY1 = -75; // Array that contains static/unchanging values for the PlayerOption let valL = [2048, 256, 2048+256, 512, 0.32, 256, 1, 1, false, true, 6, false, true]; let valR = [2048, 256, 2048+256, 512, 0.32, 256, 1, 1, false, true, -6, false, true]; // Option handling float[][] offsetArray = [[offsetX1, offsetY1], [offsetX2, 0], [-offsetX1, offsetY1], [-offsetX2, 0]]; int opt1 = PlayerOption( offsetArray[0][0], offsetArray[0][1], teamimg, valR[0], valR[1], valR[2], valR[3], valR[4], valR[5], valR[6], valR[7], valR[8], valR[9], valR[10], valR[11], valR[12]); int opt2 = PlayerOption( offsetArray[1][0], offsetArray[1][1], teamimg, valR[0], valR[1], valR[2], valR[3], valR[4], valR[5], valR[6], valR[7], valR[8], valR[9], valR[10], valR[11], valR[12]); int opt3 = PlayerOption( offsetArray[2][0], offsetArray[2][1], teamimg, valL[0], valL[1], valL[2], valL[3], valL[4], valL[5], valL[6], valL[7], valL[8], valL[9], valL[10], valL[11], valL[12]); int opt4 = PlayerOption( offsetArray[3][0], offsetArray[3][1], teamimg, valL[0], valL[1], valL[2], valL[3], valL[4], valL[5], valL[6], valL[7], valL[8], valL[9], valL[10], valL[11], valL[12]); int[] optArray = [opt1, opt2, opt3, opt4]; ObjRender_SetAngleX(opt1, (-1)*valR[4]); ObjRender_SetAngleX(opt2, (-1)*valR[4]); ascent(i in -1..length(optArray)-1){ _ThunderNeedle(optArray[i], 270, 7.5, 2); } _ThunderNeedle(optArray[1], 135, 7.5, 2); _ThunderNeedle(optArray[3], 45, 7.5, 2); //_ThunderNeedle(opt1, 270, 12, 2); //_ThunderNeedle(opt2, 250, 5, 2); //_ThunderNeedle(opt4, 290, 5, 2); //_ThunderNeedle(opt3, 270, 12, 2); // Byakuren's shot task _ThunderNeedle(int target, float baseang, float tiltang, int num){ //float baseang = 270; int a = 0; loop{ if(IsPermitPlayerShot && !ripplayer && GetVirtualKeyState(VK_SHOT) != KEY_FREE && GetVirtualKeyState(VK_SLOWMOVE) == KEY_FREE){ if(shotspeed % 5 == 0){ ascent(i in 0..num){ float shot = CreatePlayerShotA1(ObjRender_GetX(target), ObjRender_GetY(target), 44, baseang-tiltang+a*tiltang*2, 4.1, 1.8, BYAKUREN_NEEDLE); ObjRender_SetAlpha(shot, 255*(universalAlpha/100)); _BulletRescalePlayer(shot, 0.7, true, 0.7); //Fadein(shot); a++; if (a == num){a = 0;} } ObjSound_Play(basesfx); } } yield; } task Fadein(target){ ascent(i in 0..5){ //ObjRender_SetAlpha(target, Interpolate_Decelerate(180, 255, i/5)); _BulletRescalePlayer(target, Interpolate_Decelerate(0.4, 0.7, i/5), true, Interpolate_Decelerate(0.4, 0.7,i/5)); //ObjRender_SetBlendType(target, BLEND_ADD_ARGB); yield; } ObjRender_SetBlendType(target, BLEND_ALPHA); } } } // Handling of bomb task Fadein(target, len, targetscale, targetscalehitbox){ ascent(i in 0..len){ //ObjRender_SetAlpha(target, Interpolate_Decelerate(180, 255, i/len)); _BulletRescalePlayer(target, Interpolate_Decelerate(0.4, targetscale, i/len), true, Interpolate_Decelerate(1, targetscalehitbox, i/len)); //ObjRender_SetBlendType(target, BLEND_ADD_ARGB); yield; } ObjRender_SetBlendType(target, BLEND_ALPHA); } task _FocusBomb(){ // Preparation SetForbidPlayerShot(true); SetForbidPlayerSpell(true); SetPlayerInvincibilityFrame(32*3+32*3+42*3+120+45); // Spell object let manageObj = GetSpellManageObject(); // SPELL BEGINS ObjSpell_Regist(manageObj); ObjSound_Play(bombsfx); SetPlayerSpeed(5, 5); float angvel = 0.75; float revolve = 2; float spd = 21; float dmg = 2; float revolvechange = 12; ascent(i in 0..16){ float angBase = rand(0, 360); alternative(revolve) case(2){revolve = -2;} case(-2){revolve = 2;} ascent(i in 0..12){ float ang = angBase + 360/12 * i; int shot = CreateShotA2(playerX, playerY, 24, ang, 0, 24, revolve, 3, 0); Fadein(shot, 10, 1.5, 1.5); ObjRender_SetBlendType(shot, BLEND_ADD_ARGB); ObjShot_SetIntersectionEnable(shot, true); ObjShot_SetPenetration(shot, 9999); ObjShot_SetDamage(shot, 2.5); ObjShot_SetEraseShot(shot, true); ObjShot_SetSpellFactor(shot, true); ObjMove_AddPatternA2(shot, 90, NO_CHANGE, NO_CHANGE, 1, 40, 0); //ObjShot_SetDeleteFrame(shot, 120); ObjSound_Play(inferno); } ascent(i in 0..12){ float ang = angBase + 360/12 * i; int shot = CreateShotA2(playerX, playerY, 24, ang, 0, 24, -revolve, 3, 0); Fadein(shot, 10, 1.5, 1.5); ObjRender_SetBlendType(shot, BLEND_ADD_ARGB); ObjShot_SetIntersectionEnable(shot, true); ObjShot_SetPenetration(shot, 9999); ObjShot_SetDamage(shot, 2.5); ObjShot_SetEraseShot(shot, true); ObjShot_SetSpellFactor(shot, true); ObjMove_AddPatternA2(shot, 90, NO_CHANGE, NO_CHANGE, 1, 40, 0); //ObjShot_SetDeleteFrame(shot, 120); ObjSound_Play(inferno); } wait(15); } // Cleanup, end of spell SetPlayerSpeed(PlayerSpd[0], PlayerSpd[1]); SetForbidPlayerShot(false); wait(60); SetForbidPlayerSpell(false); Obj_Delete(manageObj); // !!! IMPORTANT !!! } task _UnfocusBomb(){ // Preparation SetForbidPlayerShot(true); SetForbidPlayerSpell(true); SetPlayerInvincibilityFrame(32*3+32*3+42*3+120+45); // Spell object let manageObj = GetSpellManageObject(); // SPELL BEGINS ObjSpell_Regist(manageObj); ObjSound_Play(bombsfx); SetPlayerSpeed(10, 10); float angvel = 0.75; float revolve = 0; float spd = 21; float dmg = 2; float revolvechange = 12; ascent(i in 0..100){ int shot = CreateShotA1(rand(0, GetStgFrameWidth()), -125, 36, 90, 2, 0); Fadein(shot, 18, 1.4, 1.4); ObjRender_SetBlendType(shot, BLEND_ADD_ARGB); ObjShot_SetSpinAngularVelocity(shot, 5); ObjShot_SetIntersectionEnable(shot, true); ObjShot_SetPenetration(shot, 9999); ObjShot_SetDamage(shot, 3.5); ObjShot_SetEraseShot(shot, true); ObjShot_SetSpellFactor(shot, true); ObjSound_Play(inferno); wait(3); } // Cleanup, end of spell SetPlayerSpeed(PlayerSpd[0], PlayerSpd[1]); SetForbidPlayerShot(false); wait(60); SetForbidPlayerSpell(false); Obj_Delete(manageObj); // !!! IMPORTANT !!! } // Screenshake function for bomb's duration - adapted from Sparen's tutorials task _BombShake(shaketime, intensity){ float baseintensity = intensity; float shakeno = shaketime; ascent(i in 0..shakeno){ Set2DCameraFocusX(GetStgFrameWidth/2 + rand(-intensity, intensity)); Set2DCameraFocusY(GetStgFrameHeight/2 + rand(-intensity, intensity)); intensity = Interpolate_Decelerate(0, baseintensity, 1-i/shakeno); shaketime--; yield; } while(shaketime > 0){yield;} Set2DCameraFocusX(GetStgFrameWidth/2); Set2DCameraFocusY(GetStgFrameHeight/2); yield; }