This commit is contained in:
Kevinmonitor 2023-01-26 18:34:56 +07:00
commit d3ada59252
391 changed files with 25819 additions and 0 deletions

View file

@ -0,0 +1,299 @@
// Shot Type
int[] optionArr = [];
float angSpace = 2.5;
float[] angStartArr = [];
// Far left, left, right, far right
float[] angStartUF = [230, 270, 270, 310];
float[] angStartUFAlt = [230, 275, 265, 310];
float[] angStartF = [250, 280, 260, 290];
float offsetX = 125;
float offsetY = 75;
int[] bulletNum = [4, 3, 3, 4];
task _HomeShot(int shot_) {
float duration = 55;
bool homingBool = false;
float basepenetrate = ObjShot_GetPenetration(shot_);
float basedmg = ObjShot_GetDamage(shot_);
//
for (int t = 0i; t < duration && !Obj_IsDeleted(shot_); t++) {
// Checks if enemies are on screen. If enemies are visible, enable homing for the shots.
// _enemyArray is an array containing all enemy IDs, and is constantly updated in @MainLoop.
if (0 < length(_enemyArray)) {
float targetDist = 2000; // Arbitrary number (???)
int targetID = 0;
// Checks distance of every enemy on screen.
for each (int enemy in ref _enemyArray) {
float enemyX = ObjMove_GetX(enemy);
float enemyY = ObjMove_GetY(enemy);
if (0 < enemyX && enemyX < maxX && 0 < enemyY && enemyY < maxY) {
// Returns the hypotenuse of the triangle formed by the x & y distances between the shot and the enemy.
float shotDist = hypot(enemyX - ObjMove_GetX(shot_), enemyY - ObjMove_GetY(shot_));
// Locks the shot onto the enemy.
if (shotDist < targetDist) {
targetDist = shotDist;
targetID = enemy;
homingBool = true;
}
}
}
// Code to handle the actual homing.
if (homingBool) {
for (int f = 0; t < duration && !Obj_IsDeleted(shot_) && !Obj_IsDeleted(targetID) && ObjEnemy_GetInfo(targetID, INFO_LIFE) != 0 && !ObjCol_IsIntersected(shot_); t++) {
ObjShot_SetAutoDelete(shot_, false);
float shotAngle = NormalizeAngle(ObjMove_GetAngle(shot_)); // Angle of the player shot
float targetAngle = NormalizeAngle(atan2(ObjMove_GetY(targetID) - ObjMove_GetY(shot_), ObjMove_GetX(targetID) - ObjMove_GetX(shot_))); // Returns angle from the shot to the enemy.
float angleDistance = AngularDistance(shotAngle, targetAngle); // Angular distance between enemy and player shot
float homeRate = Interpolate_Decelerate(0, 0.8, min(45, f) / 45);
// Homing speed?
ObjMove_SetAngle(shot_, Interpolate_Accelerate(shotAngle, shotAngle + angleDistance, homeRate)); // Interpolate_Necko
f++;
yield;
}
ObjShot_SetAutoDelete(shot_, true);
ObjMove_SetAngularVelocity(shot_, 0);
homingBool = false;
}
}
yield;
}
}
task UpdateAng(){
while(true){
if(GetVirtualKeyState(VK_SLOWMOVE) != KEY_FREE){
angStartArr = angStartF;
angSpace = 9;
}
else{
angStartArr = angStartUF;
angSpace = 18;
}
yield;
}
}
task ShotType(){
}
function <int> CreateOption(
float offsetX_uf, offsetY_uf,
float offsetX_f, offsetY_f,
float ang_uf, ang_f
){
// Option
int option = PlayerOption_LinearMove(
offsetX_uf, offsetY_uf, offsetX_f, offsetY_f,
true, ang_uf, ang_f,
plimg,
OPTION, 0.5, 39,
128, 1, 1, false,
false, 1,
false, false
);
return option;
}
// CALL THIS TASK FIRST
task InitiateOptions(){
// Far left, left, right, far right
float[][] offsetArr = [
[-offsetX * 1.5, offsetY * 1.25, -offsetX * 1, offsetY * 0.75],
[-offsetX * 1, 0, -offsetX * 0.75, -offsetY * 0.4],
[offsetX * 1, 0, offsetX * 0.75, -offsetY * 0.4],
[offsetX * 1.5, offsetY * 1.25, offsetX * 1, offsetY * 0.75],
];
int count = 0;
for each (float[] entry in ref offsetArr){
int option = CreateOption(
offsetArr[count][0], offsetArr[count][1],
offsetArr[count][2], offsetArr[count][3],
angStartUF[count], angStartF[count]
);
optionArr = optionArr ~ [option];
ShotType(option, angStartUFAlt[count], angStartF[count], bulletNum[count]);
SpecialWeapon(option, angStartUFAlt[count], angStartF[count], bulletNum[count]);
count++;
}
}
task BaseShot(){
int angMultiplier = 0;
while(true){
if(GetVirtualKeyState(VK_SHOT) != KEY_FREE && GetVirtualKeyState(VK_USER1) == KEY_FREE &&IsPermitPlayerShot && !ripplayer){
if(shotspeed % 4 == 0){
ObjSound_Play(Base3);
let shotA = CreatePlayerShotA1(playerX, playerY, 52, 270, shotDamage*2, 1.2, FIRE_BASE);
_BulletRescalePlayer(shotA, shotScale1, true, 1);
ObjRender_SetAlpha(shotA, shotAlpha);
Obj_SetRenderPriorityI(shotA, 41);
}
}
yield;
}
}
task ShotType(int ID, float startAngUF, startAngF, int bulletNum){
int angMultiplier = 0;
while(true){
if(GetVirtualKeyState(VK_SHOT) != KEY_FREE && GetVirtualKeyState(VK_USER1) == KEY_FREE &&IsPermitPlayerShot && !ripplayer){
if(shotspeed % 3*(bulletNum+1) == 0){
float x = ObjMove_GetX(ID);
float y = ObjMove_GetY(ID);
int multiplier = 1;
if(x-playerX > 0){multiplier = 1;}
else{multiplier = -1;}
//ObjSound_Play(Base3);
loop(bulletNum){
if(GetVirtualKeyState(VK_SLOWMOVE) != KEY_FREE){
let shotA = CreatePlayerShotA1(x, y, 45, startAngF+angSpace*multiplier*angMultiplier, shotDamage, 1.1, FIRE_NORMAL);
_BulletRescalePlayer(shotA, shotScale1, true, 1);
ObjRender_SetAlpha(shotA, shotAlpha);
Obj_SetRenderPriorityI(shotA, 41);
}
else{
let shotA = CreatePlayerShotA1(x, y, 45, startAngUF+angSpace*multiplier*angMultiplier, shotDamage, 1.1, FIRE_NORMAL);
_BulletRescalePlayer(shotA, shotScale1, true, 1);
ObjRender_SetAlpha(shotA, shotAlpha);
Obj_SetRenderPriorityI(shotA, 41);
}
angMultiplier ++;
wait(2);
}
angMultiplier = 0;
}
}
yield;
}
}
task SpecialWeapon(int ID, float startAngUF, startAngF, int bulletNum){
int angMultiplier = 0;
while(true){
if(GetVirtualKeyState(VK_USER1) != KEY_FREE && GetCommonDataPtr(POINTER_SPECIALAMMO, 100) > 0 && IsPermitPlayerShot && !ripplayer){
SetCommonDataPtr(POINTER_SPECIALCHECK, true);
SetCommonDataPtr(POINTER_CHAINCHECK, true);
// 15 ammo per second
if(shotspeed % 4 == 0){
float x = ObjMove_GetX(ID);
float y = ObjMove_GetY(ID);
SetCommonDataPtr(POINTER_SPECIALAMMO, max(0, GetCommonDataPtr(POINTER_SPECIALAMMO, 100)-(15/60)));
// Minimal rank boost -> +0.5 rank for every 10 seconds of the wpn being used -> 1/20 rank every sec -> 1/300 rank every 4 frames
SetCommonData("Rank", clamp(GetCommonData("Rank", 1) + 1/(300*4), GetCommonData("MinRank", 1), GetCommonData("MaxRank", 12)));
int multiplier = 1;
if(x-playerX > 0){multiplier = 1;}
else{multiplier = -1;}
ObjSound_Play(Base2);
loop(1){
let shotA = CreatePlayerShotA1(x, y, 45, startAngF+rand(-1, 1), shotDamageSpecial, 1.1, FIRE_SPECIAL);
_BulletRescalePlayer(shotA, shotScale1*2, true, 1);
_HomeShot(shotA);
ObjRender_SetAlpha(shotA, shotAlpha);
Obj_SetRenderPriorityI(shotA, 41);
angMultiplier ++;
}
angMultiplier = 0;
}
}
else{
SetCommonDataPtr(POINTER_CHAINCHECK, false);
if(GetCommonDataPtr(POINTER_CHAINGAUGE, 0) <= 0){SetCommonDataPtr(POINTER_SPECIALCHECK, false);}
}
yield;
}
}
// Bomb
// Yassbong explosion

View file

@ -0,0 +1,364 @@
#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);
}

View file

@ -0,0 +1,11 @@
let current = GetCurrentScriptDirectory();
let path = current ~ "Player_ShotData.dnh";
LoadPlayerShotData(path);
// -----
const OPTION = 1;
const FIRE_NORMAL = 2;
const FIRE_SPECIAL = 3;
const FIRE_BASE = 4;

View file

@ -0,0 +1,49 @@
shot_image = "./playerlib/PlSheet_Lavender.png"
ShotData{
id = 0 // Dummy
rect = (0,0,0,0)
render = ALPHA
alpha = 0
collision = 32
}
// Option
ShotData{
id = 1
rect = (0, 192, 128, 384)
render = ALPHA
alpha = 255
collision = 0 // Hitbox of arrows is not centered on the sprite
}
// Fire1
ShotData{
id = 2
rect = (128, 192, 256, 384)
render = ALPHA
alpha = 255
collision = 64 // Hitbox of arrows is not centered on the sprite
}
// Fire2
ShotData{
id = 3
rect = (512, 192, 640, 384)
render = ALPHA
alpha = 255
collision = 64 // Hitbox of arrows is not centered on the sprite
}
// Fire0
ShotData{
id = 4
rect = (384, 192, 512, 384)
render = ALPHA
alpha = 255
collision = 64 // Hitbox of arrows is not centered on the sprite
}

View file

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -0,0 +1 @@
2,0.57,,0.3442,,0.2691,0.3,0.2179,,0.3445,,,,,,,,,,,0.2992,,0.5139,,,1,,,,,,,masterVolume

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.