#TouhouDanmakufu[Player] #ScriptVersion[3] #ID["PL1_LAVENDER"] #Title["Lavender Mushihime"] #Text["Player 1"] //#Image["./mariremi_lib/mariremi_illust.png"] #ReplayName["Lavender"] #include "script/KevinSystem/kevin_system/Lib_Const.dnh" #include "script/KevinSystem/Kevin_PlayerLib.txt" #include "script/KevinSystem/PlayerSoundLib.dnh" #include "./Player_Function.dnh" #include "./Player_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/Player_Sheet.png"; LoadTextureEx(teamimg, true, true); //ObjRender_SetTextureFilterMip(teamimg, FILTER_LINEAR); let plimg = csd ~ "./playerlib/PlSheet_Lavender.png"; LoadTextureEx(plimg, true, true); ObjRender_SetTextureFilter(plimg, FILTER_NONE, FILTER_NONE, FILTER_NONE); let sndpath = csd ~ "./sound"; int[] _enemyArray = []; int[] _existArray = []; int[] _shotArray = []; bool isChain = false; bool isUseSpecialWpn = false; float curChain = 0; // Other stuff float playerX = 0; float playerY = 0; let objPlayer = GetPlayerObjectID(); int plrender = Obj_GetRenderPriorityI(objPlayer); bool ripplayer = false; float shotspeed = 0; float bombrand = 0; int grazecounter = 0; // For basic graze = PIV mechanic int shotAlpha = (GetAreaCommonData("Config", "PlayerShotOpacity", 60)*0.01)*255; float shotDamage = 3.1; float shotDamageSpecial = 6.25; float shotScale1 = 1; float[] PlayerSpd = [13, 6.5]; // 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); SetAreaCommonData("PIV", "ChainAmount", 1); } else{} SetPlayerStateEndEnable(true); // Stuff Parameter(); RenderPlayer(); UpdateAng(); BaseShot(); InitiateOptions(); Obj_SetRenderPriorityI(objPlayer, 43); plrender = Obj_GetRenderPriorityI(objPlayer); _SoundTask(); //SetIntersectionVisualization(true); // Debug _Mechanic(ripplayer, _enemyArray, _existArray, GetStgFrameWidth(), GetStgFrameHeight(), objPlayer, GetEnemyBossSceneObjectID(), 1, 2, 80); _ShowChain(); _HandleChainGauge(); _HitboxRender(ripplayer, objPlayer, plimg, teamimg, 768, 192, 832, 256, 1536, 896, 2048, 1408, 0.5, 0.65); SetShotAutoDeleteClip(256, 256, 256, 256); _Countdown(); // Shot data loading LoadPlayerShotData(csd ~ "./Player_ShotData.dnh"); } @MainLoop{ _enemyArray = GetIntersectionRegistedEnemyID; 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){ if(GetCommonDataPtr(EFFECTCUT_PTR, 0) >= 3){} else{ 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, graphic == FIRE_SPECIAL ? shotScale1 * 2 : shotScale1); } //if(graphic == ELECTRIC_FIRE_ALT) {_DeleteEffectAlt(obj);} //else{_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); _Bomb(); SetCommonData("Rank", clamp(max(1, GetCommonData("Rank", 1)-0.25), GetCommonData("MinRank", 1), GetCommonData("MaxRank", 12))); _SigilCall(false, teamimg, 768+256, 512, 768+512, 768, objPlayer, GetPlayerInvincibilityFrame()); } else { SetScriptResult(false); } } case(EV_HIT){ ObjSound_Play(PlayerHit); _DeathbombWarning(plimg, [832, 0, 1088, 256], 20, 3); } case(EV_CHAIN_MAX){ if(!isChain){ ObjSound_Play(Shine); isChain = true; curChain = GetCommonDataPtr(POINTER_CHAIN, 1); } else{} } case(EV_CHAIN_RELEASE){ } case(EV_CHAIN_END){ SetAreaCommonData("PIV", "ChainAmount", 1); isChain = false; // Increase rank depending on curChain (>= 32), then reset curChain. MAX CHAIN increases rank by 0.4. if(curChain >= 32){ SetCommonData("Rank", clamp(GetCommonData("Rank", 1) + Interpolate_Linear(0.25, 0.5, curChain/64), GetCommonData("MinRank", 1), GetCommonData("MaxRank", 12))); } curChain = 1; } case(EV_PLAYER_SHOOTDOWN){ ObjSound_Play(PlayerDie2); SetPlayerSpell(GetPlayerSpell()+2); ripplayer = true; DeleteShotAll(TYPE_SHOT, TYPE_ITEM); // Decrease rank by 1/4 SetCommonData("Rank", clamp(GetCommonData("Rank", 1) * 0.75, GetCommonData("MinRank", 1), GetCommonData("MaxRank", 12))); _SigilCall(true, teamimg, 768, 512, 768+256, 768, objPlayer, 60); } case(EV_PLAYER_REBIRTH){ ripplayer = false; SetPlayerInvincibilityFrame(180); //_Countdown(); _SigilCall(false, teamimg, 768+256, 512, 768+512, 768, objPlayer, 150); } case(EV_GRAZE){ } } @Finalize{ } // Basic player parameters task Parameter(){ // im trying to not be collected by the player but their item scope is dummy thicc and im alerted by its cheek SetPlayerItemScope(360); SetPlayerLife(9); // Debug SetPlayerSpell(2); SetPlayerSpeed(PlayerSpd[0], PlayerSpd[1]); // (original: 5.25/2.0) SetPlayerRebirthFrame(20); SetPlayerDownStateFrame(60); SetPlayerAutoItemCollectLine(GetStgFrameHeight/3); SetPlayerRebirthLossFrame(0); ObjPlayer_AddIntersectionCircleA1(objPlayer, 0, 0, 0, 40); } // Player render task RenderPlayer(){ // Why is this movement code so cursed jesus fucking christ float scale = 1; // Scalies int frame = 0; ObjPrim_SetTexture(objPlayer, plimg); ObjSprite2D_SetSourceRect(objPlayer, 0, 0, 128, 192); ObjSprite2D_SetDestCenter(objPlayer); Obj_SetRenderPriorityI(objPlayer, 42); //ObjRender_SetTextureFilterMin(objPlayer, FILTER_ANISOTROPIC); ObjRender_SetScaleXYZ(objPlayer, scale, scale, 1); // Lower "speed" parameter = FASTER SPEED loop{ frame++; _RenderPlayerMovement(objPlayer, frame, 0, 0, 128, 192, scale, 3, 6); if (frame >= (3*6-1)){frame = 0;} yield; } } // Handling of bomb task _Bomb(){ // Fire rings explode in a straight line, bomb lasts 90 frames with 240-frame total invincibility // Preparation SetForbidPlayerShot(true); SetForbidPlayerSpell(true); SetPlayerInvincibilityFrame(120); // Spell object let manageObj = GetSpellManageObject(); // SPELL BEGINS ObjSpell_Regist(manageObj); // Fully refills chain gauge for 120 frames // Activates chain but not FUN MODE async{ loop(60){ SetCommonDataPtr(POINTER_CHAINCHECK, true); SetCommonDataPtr(POINTER_CHAINGAUGE, 100); yield; } } task CreateFireRing(x, y){ float startAng = rand(0, 360); ascent(i in 0..16){ int slash = CreatePlayerShotA1(x, y, 35, startAng + i * 360/16, shotDamageSpecial/8, 64, FIRE_SPECIAL); ObjShot_SetPenetrateShotEnable(slash, false); ObjRender_SetColorHSV(slash, 180, 255, 255); _BulletRescalePlayer(slash, shotScale1*2.5, true, 1); ObjShot_SetSpellFactor(slash, true); ObjShot_SetEraseShot(slash, true); Obj_SetRenderPriorityI(slash, plrender-1); //ObjRender_SetBlendType(slash, BLEND_ADD_ARGB); Fade(slash); } ObjSound_Play(Explosion2); } task Fade(int ID){ ObjRender_SetAlpha(ID, 255); ObjMove_AddPatternA2(ID, 0, 40, NO_CHANGE, -40/25, 15, 0); ascent(i in 0..15){ ObjRender_SetAlpha(ID, Interpolate_Accelerate(255, 0, i/15)); yield; } Obj_Delete(ID); } float bombX = playerX; ascent(i in 0..15){ CreateFireRing(rand(0, STG_WIDTH), rand(0, STG_HEIGHT)); wait(4); } SetPlayerSpeed(PlayerSpd[0], PlayerSpd[1]); SetForbidPlayerShot(false); Obj_Delete(manageObj); // !!! IMPORTANT !!! wait(60); SetForbidPlayerSpell(false); }