829 lines
25 KiB
Plaintext
829 lines
25 KiB
Plaintext
|
/* --------------------------------------------------------------------
|
||
|
|
||
|
UNIVERSAL/GENERAL FUNCTIONS USED FOR PLAYERS
|
||
|
|
||
|
These functions may/will be reused for future scripts as well.
|
||
|
|
||
|
--------------------------------------------------------------------
|
||
|
*/
|
||
|
|
||
|
#include "script/KevinSystem/kevin_system/Kevin_ItemConst.txt"
|
||
|
#include "script/KevinSystem/kevin_system/Kevin_ItemLib.txt"
|
||
|
#include "script/KevinSystem/kevin_system/Lib_Const.dnh"
|
||
|
#include "script/KevinSystem/Kevin_PlayerLib_HUD.dnh"
|
||
|
//#include "script/KevinSystem/Universal_Lib.txt"
|
||
|
|
||
|
float universalAlpha = GetAreaCommonData("Config", "PlayerShotOpacity", 60);
|
||
|
|
||
|
let POINTER_PIV = LoadAreaCommonDataValuePointer("PIV", "currentvalue", 1000);
|
||
|
let POINTER_CHAIN = LoadAreaCommonDataValuePointer("PIV", "ChainAmount", 1);
|
||
|
let POINTER_CHAINGAUGE = LoadAreaCommonDataValuePointer("PIV", "ChainGauge", 0);
|
||
|
let POINTER_SPECIALAMMO = LoadAreaCommonDataValuePointer("PIV", "SpecialAmmo", 100);
|
||
|
let POINTER_SPECIALCHECK = LoadAreaCommonDataValuePointer("PIV", "IsUsingSpecial", false);
|
||
|
let POINTER_CHAINCHECK = LoadAreaCommonDataValuePointer("PIV", "IsChaining", false);
|
||
|
|
||
|
//universalAlpha = 255; // Debug
|
||
|
|
||
|
function CreateTextObject(
|
||
|
float mx, my, size,
|
||
|
string text, font,
|
||
|
int colorTop, colorBottom,
|
||
|
int borderColor, borderWidth,
|
||
|
int renderPriority
|
||
|
){
|
||
|
|
||
|
let obj = ObjText_Create();
|
||
|
ObjText_SetText(obj, text);
|
||
|
ObjText_SetFontSize(obj, size);
|
||
|
ObjText_SetFontType(obj, font);
|
||
|
ObjText_SetFontColorTop(obj, colorTop);
|
||
|
ObjText_SetFontColorBottom(obj, colorBottom);
|
||
|
ObjText_SetFontBorderType(obj, BORDER_FULL);
|
||
|
ObjText_SetFontBorderColor(obj, borderColor);
|
||
|
ObjText_SetFontBorderWidth(obj, borderWidth);
|
||
|
Obj_SetRenderPriorityI(obj, renderPriority);
|
||
|
ObjRender_SetX(obj, mx);
|
||
|
ObjRender_SetY(obj, my);
|
||
|
return obj;
|
||
|
|
||
|
}
|
||
|
|
||
|
function <int> _Create2DImage(imgpath, int[] rectarray){
|
||
|
|
||
|
int imgname = ObjPrim_Create(OBJ_SPRITE_2D);
|
||
|
ObjPrim_SetTexture(imgname, imgpath);
|
||
|
ObjSprite2D_SetSourceRect(imgname, rectarray);
|
||
|
ObjSprite2D_SetDestCenter(imgname);
|
||
|
//ObjRender_SetPosition(imgname, positionstart)
|
||
|
|
||
|
return imgname;
|
||
|
}
|
||
|
|
||
|
// thanks ttbd owo
|
||
|
|
||
|
function CreateEffectObject(px, py, img, blendtype, left, top, right, bottom)
|
||
|
{
|
||
|
let obj = ObjPrim_Create(OBJ_SPRITE_2D);
|
||
|
ObjPrim_SetTexture(obj, img);
|
||
|
ObjSprite2D_SetSourceRect(obj, left, top, right, bottom);
|
||
|
ObjSprite2D_SetDestCenter(obj);
|
||
|
|
||
|
if(blendtype=="ALPHA"){ObjRender_SetBlendType(obj, BLEND_ALPHA);}
|
||
|
else if(blendtype=="MULTIPLY"){ObjRender_SetBlendType(obj, BLEND_MULTIPLY);}
|
||
|
else if(blendtype=="SUBTRACT"){ObjRender_SetBlendType(obj, BLEND_SUBTRACT);}
|
||
|
else if(blendtype=="SHADOW"){ObjRender_SetBlendType(obj, BLEND_SHADOW);}
|
||
|
else if(blendtype=="RGB"){ObjRender_SetBlendType(obj, BLEND_ADD_RGB);}
|
||
|
else if(blendtype=="ARGB"){ObjRender_SetBlendType(obj, BLEND_ADD_ARGB);}
|
||
|
else if(blendtype=="INVERT"){ObjRender_SetBlendType(obj, BLEND_INV_DESTRGB);}
|
||
|
|
||
|
ObjRender_SetPosition(obj, px, py, 0);
|
||
|
ObjRender_SetTextureFilter(obj, FILTER_POINT, FILTER_POINT, FILTER_POINT);
|
||
|
|
||
|
return obj;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
|
||
|
CHAIN SYSTEM: Crystals fill up your chain amount and refill your chain gauge, up to a max of 64x
|
||
|
Gauge starts to go down when you don't collect crystals: it resets the entire chain after 3 seconds
|
||
|
|
||
|
*/
|
||
|
|
||
|
task _HandleChainGauge(){
|
||
|
|
||
|
// Gauge maxes at 100.
|
||
|
// If gauge reaches 0, reset the chain
|
||
|
float rateReduceNormal = 100/120;
|
||
|
|
||
|
float rateReduceCashin = 100/180; // x48-64
|
||
|
|
||
|
float rateReduceCashin_MED = 100/90; // x32-48
|
||
|
float rateReduceCashin_LOW = 100/60; // x16-32
|
||
|
float rateReduceCashin_PLACEBO = 100/30; // under x16
|
||
|
|
||
|
while(true){
|
||
|
|
||
|
if(GetCommonDataPtr(POINTER_SPECIALCHECK, false) == false && GetCommonDataPtr(POINTER_CHAIN, 1) >= 64 && !isChain){NotifyEventAll(EV_CHAIN_MAX, 1);}
|
||
|
|
||
|
else{}
|
||
|
|
||
|
if(GetCommonDataPtr(POINTER_SPECIALCHECK, false) == true){
|
||
|
|
||
|
if(GetCommonDataPtr(POINTER_CHAINGAUGE, 0) <= 1){NotifyEventAll(EV_CHAIN_END, 1);}
|
||
|
|
||
|
if(GetCommonDataPtr(POINTER_CHAIN, 1) >= 48)
|
||
|
{SetCommonDataPtr(POINTER_CHAINGAUGE, max(0, GetCommonDataPtr(POINTER_CHAINGAUGE, 0)-rateReduceCashin));}
|
||
|
|
||
|
else if(GetCommonDataPtr(POINTER_CHAIN, 1) >= 32 && GetCommonDataPtr(POINTER_CHAIN, 1) < 48)
|
||
|
{SetCommonDataPtr(POINTER_CHAINGAUGE, max(0, GetCommonDataPtr(POINTER_CHAINGAUGE, 0)-rateReduceCashin_MED));}
|
||
|
|
||
|
else if(GetCommonDataPtr(POINTER_CHAIN, 1) >= 16 && GetCommonDataPtr(POINTER_CHAIN, 1) < 32)
|
||
|
{SetCommonDataPtr(POINTER_CHAINGAUGE, max(0, GetCommonDataPtr(POINTER_CHAINGAUGE, 0)-rateReduceCashin_LOW));}
|
||
|
|
||
|
else
|
||
|
{SetCommonDataPtr(POINTER_CHAINGAUGE, max(0, GetCommonDataPtr(POINTER_CHAINGAUGE, 0)-rateReduceCashin_PLACEBO));}
|
||
|
|
||
|
}
|
||
|
|
||
|
else{
|
||
|
SetCommonDataPtr(POINTER_CHAINGAUGE, max(0, GetCommonDataPtr(POINTER_CHAINGAUGE, 0)-rateReduceNormal));
|
||
|
}
|
||
|
|
||
|
if(
|
||
|
GetCommonDataPtr(POINTER_CHAINGAUGE, 0) <= 0
|
||
|
&& GetCommonDataPtr(POINTER_CHAIN, 1) > 1
|
||
|
)
|
||
|
{
|
||
|
SetCommonDataPtr(POINTER_CHAIN, 1);
|
||
|
SetCommonDataPtr(POINTER_SPECIALCHECK, false);
|
||
|
}
|
||
|
|
||
|
yield;
|
||
|
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
task _ShowChain(){
|
||
|
|
||
|
// HUD
|
||
|
|
||
|
//_ShowChainHUD();
|
||
|
|
||
|
// Playfield
|
||
|
|
||
|
let objPIVNum = ObjText_Create();
|
||
|
|
||
|
ObjText_SetFontSize(objPIVNum, 40);
|
||
|
ObjText_SetFontBold(objPIVNum, true);
|
||
|
ObjText_SetFontType(objPIVNum, "GravityRegular5");
|
||
|
ObjText_SetFontColorTop(objPIVNum, 0xFFFFFF);
|
||
|
ObjText_SetFontColorBottom(objPIVNum, 0xFFFFFF);
|
||
|
ObjText_SetFontBorderType(objPIVNum, BORDER_FULL);
|
||
|
ObjText_SetFontBorderColor(objPIVNum, 0xFF9A4F);
|
||
|
ObjText_SetFontBorderWidth(objPIVNum, 4);
|
||
|
ObjText_SetHorizontalAlignment(objPIVNum, ALIGNMENT_LEFT);
|
||
|
//ObjText_SetFontWeight(objPIVNum, 1000);
|
||
|
Obj_SetRenderPriorityI(objPIVNum, 60);
|
||
|
ObjText_SetSidePitch(objPIVNum, -3);
|
||
|
ObjRender_SetPosition(objPIVNum, STG_WIDTH * 1/2 + 96, STG_HEIGHT * 10/11, 0);
|
||
|
// DEBUG
|
||
|
//Obj_SetVisible(objPIV, false);
|
||
|
|
||
|
float value = 0;
|
||
|
|
||
|
//todo: change params
|
||
|
let objI = CreateEffectObject(STG_WIDTH/60, STG_HEIGHT/7, "script/KevinSystem/img/lol.png", "ALPHA", 0, 0, 244, 12);
|
||
|
ObjSprite2D_SetDestRect(objI, 0, 0, 122, 6);
|
||
|
Obj_SetRenderPriorityI(objI, 60);
|
||
|
|
||
|
while(true){
|
||
|
value = min(GetCommonDataPtr(POINTER_SPECIALAMMO, 1), 100);
|
||
|
ObjText_SetText(objPIVNum, IntToString(GetCommonDataPtr(POINTER_PIV, 1000)));
|
||
|
|
||
|
//PIVMultiplierValue = value/1000;
|
||
|
let yass = rtos("00.00", value);
|
||
|
|
||
|
let mx = 60*5;
|
||
|
ObjSprite2D_SetDestRect(objI, 0, 0, (GetCommonDataPtr(POINTER_SPECIALAMMO, 100)/100)*mx, 32);
|
||
|
|
||
|
ObjRender_SetPosition(objI, STG_WIDTH/60+160, STG_HEIGHT * 11/12, 1);
|
||
|
|
||
|
if (GetPlayerY() >= STG_HEIGHT * 7/8){
|
||
|
ObjRender_SetAlpha(objI, 125);
|
||
|
ObjRender_SetAlpha(objPIVNum, 125);
|
||
|
}
|
||
|
|
||
|
else{
|
||
|
ObjRender_SetAlpha(objI, 255);
|
||
|
ObjRender_SetAlpha(objPIVNum, 255);
|
||
|
}
|
||
|
|
||
|
if (GetCommonDataPtr(POINTER_CHAINCHECK, false) == true) {
|
||
|
ObjRender_SetColor(objI, 0xFFAF1E);
|
||
|
}
|
||
|
else {
|
||
|
if(value >= 100){
|
||
|
ObjRender_SetColor(objI, 255, 90, 46);
|
||
|
}
|
||
|
else{
|
||
|
ObjRender_SetColor(objI, 255, 145, 115);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
if(GetCommonDataPtr(POINTER_SPECIALCHECK, false) == false){
|
||
|
|
||
|
ObjText_SetFontBorderWidth(objPIVNum, 3);
|
||
|
|
||
|
if(value < CHAIN_MAX){
|
||
|
|
||
|
ObjText_SetFontColorTop(objPIVNum, 0x9DEFFF);
|
||
|
ObjText_SetFontBorderColor(objPIVNum, 42, 0, 237);
|
||
|
ObjText_SetText(objPIVNum,
|
||
|
"[font size=23 oy=-8]FUN MODE CHARGING[r]" ~ yass ~ "[font size=25 oy=32]x[r]"
|
||
|
~ "[r][font size=21 oc=(172, 50, 50) oy=32]AMMO: " ~ rtos("00.00", GetCommonDataPtr(POINTER_SPECIALAMMO, 100))
|
||
|
);
|
||
|
|
||
|
}
|
||
|
|
||
|
else{
|
||
|
|
||
|
ObjText_SetFontColorTop(objPIVNum, 0x9DFFBC);
|
||
|
ObjText_SetFontBorderColor(objPIVNum, 0x39C832);
|
||
|
ObjText_SetText(objPIVNum,
|
||
|
"[font size=23 oy=-8]FUN MODE READY![r]" ~ yass ~ "[font size=25 oy=32]x[r]"
|
||
|
~ "[r][font size=21 oc=(172, 50, 50) oy=32]AMMO: " ~ rtos("00.00", GetCommonDataPtr(POINTER_SPECIALAMMO, 100))
|
||
|
);
|
||
|
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
else{
|
||
|
|
||
|
ObjText_SetFontColorTop(objPIVNum, 0xFFED9D);
|
||
|
ObjText_SetFontBorderColor(objPIVNum, 0xFF9A00);
|
||
|
ObjText_SetFontBorderWidth(objPIVNum, 4);
|
||
|
NotifyEvent(GetPlayerScriptID(), EV_CHAIN_MAX, 0);
|
||
|
ObjText_SetText(objPIVNum,
|
||
|
"[font size=23 oc=(241, 180, 0) oy=-8]CASH-IN[r]" ~ yass ~ "[font size=25 oy=32]x[r]"
|
||
|
~ "[r][font size=21 oc=(172, 50, 50) oy=32]AMMO: " ~ rtos("00.00", GetCommonDataPtr(POINTER_SPECIALAMMO, 100))
|
||
|
);
|
||
|
|
||
|
}
|
||
|
*/
|
||
|
|
||
|
yield;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
// Self-explanatory
|
||
|
|
||
|
task _DeleteEffect(obj, scale){
|
||
|
ObjRender_SetBlendType(obj, BLEND_ADD_ARGB);
|
||
|
Obj_SetRenderPriorityI(obj, 49);
|
||
|
ascent(i in 0..30){
|
||
|
ObjRender_SetAlpha(obj, Interpolate_Decelerate(100*(universalAlpha/100), 0, i/30));
|
||
|
ObjRender_SetScaleXYZ(obj, Interpolate_Decelerate(scale, scale*1.5, i/20));
|
||
|
ObjMove_SetSpeed(obj, 12);
|
||
|
yield;
|
||
|
}
|
||
|
Obj_Delete(obj);
|
||
|
}
|
||
|
|
||
|
// Renders player movement. Assumes that all sprites are ORGANIZED HORIZONTALLY IN THE SHEET.
|
||
|
// flipscale can only be 1 or -1.
|
||
|
|
||
|
task _RenderPlayerMovement(int obj, int frame, int offsetleft, int offsettop, int width, int height, float flipscale, int frameno, int speed){
|
||
|
|
||
|
ObjSprite2D_SetSourceRect(obj, offsetleft+width*floor(frame/speed), offsettop, width+width*floor(frame/speed), offsettop+height);
|
||
|
ObjRender_SetScaleX(objPlayer, flipscale);
|
||
|
|
||
|
}
|
||
|
|
||
|
// Bullet rescaling... for player shots.
|
||
|
task _BulletRescalePlayer(int target, float scale, bool hitboxscale, float hitboxlevel){
|
||
|
ObjRender_SetScaleXYZ(target, scale, scale, 1);
|
||
|
if (hitboxscale){
|
||
|
ObjShot_SetIntersectionScaleXY(target, scale*hitboxlevel, scale*hitboxlevel);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Handles death/respawn sigil. Assumes sigils are 512x512 in size.
|
||
|
// If death is true (the player dies), the circle expands outwards. Otherwise (the player bombs/respawns), it shrinks inwards.
|
||
|
|
||
|
task _SigilCall(bool death, texture, int rectleft, int recttop, int rectright, int rectbottom, int objPlayer, int time){
|
||
|
|
||
|
let DeathCircle = ObjPrim_Create(OBJ_SPRITE_2D);
|
||
|
|
||
|
ObjPrim_SetTexture(DeathCircle,teamimg);
|
||
|
ObjSprite2D_SetSourceRect(DeathCircle, rectleft, recttop, rectright, rectbottom);
|
||
|
ObjSprite2D_SetDestCenter(DeathCircle);
|
||
|
ObjRender_SetBlendType(DeathCircle,BLEND_ALPHA);
|
||
|
ObjRender_SetAlpha(DeathCircle,255);
|
||
|
|
||
|
ObjRender_SetPosition(DeathCircle,GetPlayerX(),GetPlayerY(),1);
|
||
|
Obj_SetRenderPriorityI(DeathCircle,Obj_GetRenderPriorityI(objPlayer)-10);
|
||
|
|
||
|
alternative(death)
|
||
|
case(true){
|
||
|
ascent(i in 0..time){
|
||
|
float scaliealpha = Interpolate_Decelerate(255, 0, i/time);
|
||
|
float scaliesize = Interpolate_Decelerate(0.1, 3, i/time);
|
||
|
ObjRender_SetAlpha(DeathCircle, scaliealpha);
|
||
|
ObjRender_SetPosition(DeathCircle,GetPlayerX(),GetPlayerY(),1);
|
||
|
ObjRender_SetScaleXYZ(DeathCircle, scaliesize, scaliesize, 1);
|
||
|
yield;
|
||
|
}
|
||
|
}
|
||
|
case(false){
|
||
|
ascent(i in 0..time){
|
||
|
float scaliealpha = Interpolate_Accelerate(255, 0, i/time);
|
||
|
float scaliesize = Interpolate_Accelerate(3, 0.1, i/time);
|
||
|
ObjRender_SetAlpha(DeathCircle, scaliealpha);
|
||
|
ObjRender_SetPosition(DeathCircle,GetPlayerX(),GetPlayerY(),1);
|
||
|
ObjRender_SetScaleXYZ(DeathCircle, scaliesize, scaliesize, 1);
|
||
|
yield;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
while(ObjRender_GetAlpha(DeathCircle) > 0){yield;}
|
||
|
Obj_Delete(DeathCircle);
|
||
|
|
||
|
}
|
||
|
|
||
|
// Handles the hitbox and its aura. What the fuck.
|
||
|
|
||
|
task _HitboxRender(
|
||
|
bool playerdeathbool, int objPlayer, texture_hbox, texture_aura,
|
||
|
int rectleft_hbox, int recttop_hbox, int rectright_hbox, int rectbottom_hbox,
|
||
|
int rectleft_aura, int recttop_aura, int rectright_aura, int rectbottom_aura,
|
||
|
float scale_hbox, float scale_aura){
|
||
|
|
||
|
// Handle hitbox
|
||
|
bool visible = false;
|
||
|
int hitbox = ObjPrim_Create(OBJ_SPRITE_2D);
|
||
|
|
||
|
ObjPrim_SetTexture(hitbox, texture_hbox);
|
||
|
ObjSprite2D_SetSourceRect(hitbox, rectleft_hbox, recttop_hbox, rectright_hbox, rectbottom_hbox);
|
||
|
ObjSprite2D_SetDestCenter(hitbox);
|
||
|
ObjRender_SetScaleXYZ(hitbox, scale_hbox, scale_hbox, 1);
|
||
|
ObjRender_SetBlendType(hitbox, BLEND_ALPHA);
|
||
|
Obj_SetRenderPriorityI(hitbox, 79);
|
||
|
|
||
|
Obj_SetVisible(hitbox, false);
|
||
|
|
||
|
// Handle hitbox's aura
|
||
|
|
||
|
int aura = ObjPrim_Create(OBJ_SPRITE_2D);
|
||
|
|
||
|
ObjPrim_SetTexture(aura, texture_aura);
|
||
|
ObjSprite2D_SetSourceRect(aura, rectleft_aura, recttop_aura, rectright_aura, rectbottom_aura);
|
||
|
ObjSprite2D_SetDestCenter(aura);
|
||
|
ObjRender_SetScaleXYZ(aura, scale_aura, scale_aura, 1);
|
||
|
ObjRender_SetAlpha(aura, 70);
|
||
|
//ObjRender_SetBlendType(aura, BLEND_ADD_ARGB);
|
||
|
Obj_SetRenderPriorityI(aura, Obj_GetRenderPriorityI(objPlayer)+3);
|
||
|
|
||
|
Obj_SetVisible(aura, false);
|
||
|
|
||
|
loop{
|
||
|
if (visible && (!Obj_IsVisible(objPlayer) || GetVirtualKeyState(VK_SLOWMOVE) != KEY_HOLD)){
|
||
|
visible = false;
|
||
|
Obj_SetVisible(hitbox, false);
|
||
|
Obj_SetVisible(aura, false);
|
||
|
}
|
||
|
else if (!visible && (Obj_IsVisible(objPlayer) && (GetVirtualKeyState(VK_SLOWMOVE) == KEY_HOLD || GetVirtualKeyState(VK_SLOWMOVE) == KEY_PUSH))){
|
||
|
visible = true;
|
||
|
Obj_SetVisible(aura, true);
|
||
|
Obj_SetVisible(hitbox, true);
|
||
|
async{
|
||
|
while(Obj_IsVisible(aura)){
|
||
|
float[] curang = [ObjRender_GetAngleZ(hitbox), ObjRender_GetAngleZ(aura)];
|
||
|
ObjRender_SetAngleZ(hitbox, curang[0]+1.5);
|
||
|
ObjRender_SetAngleZ(aura, curang[1]+1.5);
|
||
|
yield;
|
||
|
}
|
||
|
}
|
||
|
async{
|
||
|
ascent(i in 0..20){
|
||
|
float scalie = Interpolate_Decelerate(scale_aura*1.5, scale_aura, i/20);
|
||
|
ObjRender_SetScaleXYZ(aura, scalie, scalie, 1);
|
||
|
yield;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
async{
|
||
|
ascent(i in 0..20){
|
||
|
float scalie = Interpolate_Decelerate(0, 80, i/20);
|
||
|
ObjRender_SetAlpha(aura, scalie);
|
||
|
yield;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
ObjRender_SetPosition(hitbox, ObjMove_GetX(objPlayer), ObjMove_GetY(objPlayer), 1);
|
||
|
ObjRender_SetPosition(aura, ObjMove_GetX(objPlayer), ObjMove_GetY(objPlayer), 1);
|
||
|
yield;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
Simple function that handles player options. These options simply follow the player at an offset - they do not have any trajectories of their own like spinning around the player, etc.
|
||
|
If the options have animations, set triggeranimation to true and adjust the number of frames + speed using delay and frameno.
|
||
|
If the options rotate (in place), set triggerspin to true and adjust spinning speed using spinspeed.
|
||
|
If the options only appear unfocused or focused, set either onlyFocus or onlyUnfocus to true. Setting both to true or false makes the options always visible.
|
||
|
*/
|
||
|
|
||
|
function PlayerOption(
|
||
|
float offsetx, float offsety,
|
||
|
texture,
|
||
|
int left, int top, int right, int bottom, float scale,
|
||
|
int width, int animdelay, int frameno, bool triggeranimation,
|
||
|
bool triggerspin, float spinspeed,
|
||
|
bool onlyFocus, bool onlyUnfocus
|
||
|
){
|
||
|
|
||
|
let option = ObjPrim_Create(OBJ_SPRITE_2D);
|
||
|
bool visible;
|
||
|
int animate = 0;
|
||
|
float optx;
|
||
|
float opty;
|
||
|
|
||
|
ObjPrim_SetTexture(option, texture);
|
||
|
ObjSprite2D_SetSourceRect(option, left, top, right-1, bottom-1); // Allows the options to spin smoothly should the user choose to do so.
|
||
|
ObjSprite2D_SetDestCenter(option);
|
||
|
ObjRender_SetScaleXYZ(option, scale);
|
||
|
ObjRender_SetBlendType(option, BLEND_ALPHA);
|
||
|
ObjRender_SetAlpha(option, 255);
|
||
|
Obj_SetRenderPriorityI(option, 41);
|
||
|
ObjRender_SetPosition(option, offsetx, offsety, 1);
|
||
|
|
||
|
// Animation
|
||
|
async{
|
||
|
while(triggeranimation){
|
||
|
ObjSprite2D_SetSourceRect(option, left+width*floor(animate/animdelay), top, right+width*floor(animate/animdelay)-1, bottom-1);
|
||
|
animate++;
|
||
|
if (animate >= animdelay*frameno){animate = 0;}
|
||
|
yield;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Rotation
|
||
|
async{
|
||
|
float i = 0;
|
||
|
while(triggerspin){
|
||
|
//ObjRender_SetPosition(option, GetPlayerX()+offsetx, GetPlayerY()+offsety, 1);
|
||
|
ObjRender_SetAngleZ(option, i);
|
||
|
i += spinspeed;
|
||
|
yield;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Follow
|
||
|
async{
|
||
|
while(true){
|
||
|
ObjRender_SetPosition(option, GetPlayerX()+offsetx, GetPlayerY()+offsety, 1);
|
||
|
yield;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Visibility
|
||
|
async{
|
||
|
// Always visible
|
||
|
if((onlyFocus && onlyUnfocus) || (!onlyFocus && !onlyUnfocus)) {
|
||
|
loop
|
||
|
{
|
||
|
if(GetPlayerState != STATE_NORMAL && GetPlayerState != STATE_HIT){ObjRender_SetAlpha(option, max(0, ObjRender_GetAlpha(option)-15)); visible = false;}
|
||
|
else {ObjRender_SetAlpha(option, min(225, ObjRender_GetAlpha(option)+15)); visible = true;}
|
||
|
yield;
|
||
|
}
|
||
|
}
|
||
|
// Visible when focused only
|
||
|
else if(onlyFocus && !onlyUnfocus){
|
||
|
loop
|
||
|
{
|
||
|
if((GetPlayerState != STATE_NORMAL && GetPlayerState != STATE_HIT) || GetVirtualKeyState(VK_SLOWMOVE) == KEY_FREE){ObjRender_SetAlpha(option, max(0, ObjRender_GetAlpha(option)-15)); visible = false;}
|
||
|
else {ObjRender_SetAlpha(option, min(225, ObjRender_GetAlpha(option)+15)); visible = true;}
|
||
|
yield;
|
||
|
}
|
||
|
}
|
||
|
// Visible when unfocused only
|
||
|
else if(!onlyFocus && onlyUnfocus){
|
||
|
loop
|
||
|
{
|
||
|
if((GetPlayerState != STATE_NORMAL && GetPlayerState != STATE_HIT) || GetVirtualKeyState(VK_SLOWMOVE) != KEY_FREE){ObjRender_SetAlpha(option, max(0, ObjRender_GetAlpha(option)-15)); visible = false;}
|
||
|
else {ObjRender_SetAlpha(option, min(225, ObjRender_GetAlpha(option)+15)); visible = true;}
|
||
|
yield;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function _FadeIn(){
|
||
|
ascent(i in 0..15){
|
||
|
ObjRender_SetAlpha(option, Interpolate_Decelerate(0, 225, i/15));
|
||
|
yield;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function _FadeOut(){
|
||
|
ascent(i in 0..15){
|
||
|
ObjRender_SetAlpha(option, Interpolate_Decelerate(225, 0, i/15));
|
||
|
yield;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return option;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
A form of PlayerOption that handles basic movement towards different positionings based on whether the player is focusing or unfocusing.
|
||
|
If the options have animations, set triggeranimation to true and adjust the number of frames + speed using delay and frameno.
|
||
|
If the options rotate (in place), set triggerspin to true and adjust spinning speed using spinspeed.
|
||
|
If the options only appear unfocused or focused, set either onlyFocus or onlyUnfocus to true. Setting both to true or false makes the options always visible.
|
||
|
*/
|
||
|
|
||
|
function PlayerOption_LinearMove(
|
||
|
float offsetX_uf, offsetY_uf, offsetX_f, offsetY_f,
|
||
|
bool angchange, float ang_uf, ang_f,
|
||
|
texture,
|
||
|
int graphic, float texScale, int priorityRender,
|
||
|
int texWidth, int animDelay, int animFrameNo, bool animMode,
|
||
|
bool spinMode, float spinSpeed,
|
||
|
bool onlyFocus, bool onlyUnfocus
|
||
|
){
|
||
|
|
||
|
int option = CreatePlayerShotA1(0, 0, 0, 0, 0, 9999999, graphic);
|
||
|
bool visible;
|
||
|
int animate = 0;
|
||
|
float optx;
|
||
|
float opty;
|
||
|
|
||
|
float playerX = 0, playerY = 0;
|
||
|
|
||
|
/*
|
||
|
ObjPrim_SetTexture(option, texture);
|
||
|
ObjSprite2D_SetSourceRect(option, texRect[0], texRect[1], texRect[2]-1, texRect[3]-1); // Allows the options to spin smoothly should the user choose to do so.
|
||
|
ObjSprite2D_SetDestCenter(option);
|
||
|
*/
|
||
|
|
||
|
ObjShot_SetAutoDelete(option, false);
|
||
|
ObjRender_SetScaleXYZ(option, texScale);
|
||
|
ObjRender_SetBlendType(option, BLEND_ALPHA);
|
||
|
//ObjRender_SetAlpha(option, 255);
|
||
|
Obj_SetRenderPriorityI(option, priorityRender);
|
||
|
ObjRender_SetPosition(option, playerX+offsetX_uf, playerY+offsetY_uf, 1);
|
||
|
|
||
|
///// MISC /////
|
||
|
async{
|
||
|
while(true){
|
||
|
playerX = ObjRender_GetX(GetPlayerObjectID());
|
||
|
playerY = ObjRender_GetY(GetPlayerObjectID());
|
||
|
yield;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
///// ANIMATION /////
|
||
|
|
||
|
/*
|
||
|
async{
|
||
|
while(animMode){
|
||
|
ObjSprite2D_SetSourceRect(option, texRect[0]+texWidth*floor(animate/animDelay), texRect[1], texRect[2]+texWidth*floor(animate/animDelay)-1, texRect[3]-1);
|
||
|
animate++;
|
||
|
if (animate >= animDelay*animFrameNo){animate = 0;}
|
||
|
yield;
|
||
|
}
|
||
|
}*/
|
||
|
|
||
|
///// ROTATION /////
|
||
|
async{
|
||
|
float i = 0;
|
||
|
while(spinMode){
|
||
|
//ObjRender_SetPosition(option, GetPlayerX()+offsetx, GetPlayerY()+offsety, 1);
|
||
|
ObjRender_SetAngleZ(option, i);
|
||
|
i += spinSpeed;
|
||
|
yield;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
///// VISIBILITY /////
|
||
|
async{
|
||
|
// Always visible
|
||
|
if((onlyFocus && onlyUnfocus) || (!onlyFocus && !onlyUnfocus)) {
|
||
|
loop
|
||
|
{
|
||
|
if(GetPlayerState != STATE_NORMAL && GetPlayerState != STATE_HIT){ObjRender_SetAlpha(option, max(0, ObjRender_GetAlpha(option)-15)); visible = false;}
|
||
|
else {ObjRender_SetAlpha(option, min(255, ObjRender_GetAlpha(option)+15)); visible = true;}
|
||
|
yield;
|
||
|
}
|
||
|
}
|
||
|
// Visible when focused only
|
||
|
else if(onlyFocus && !onlyUnfocus){
|
||
|
loop
|
||
|
{
|
||
|
if((GetPlayerState != STATE_NORMAL && GetPlayerState != STATE_HIT) || GetVirtualKeyState(VK_SLOWMOVE) == KEY_FREE){ObjRender_SetAlpha(option, max(0, ObjRender_GetAlpha(option)-15)); visible = false;}
|
||
|
else {ObjRender_SetAlpha(option, min(255, ObjRender_GetAlpha(option)+15)); visible = true;}
|
||
|
yield;
|
||
|
}
|
||
|
}
|
||
|
// Visible when unfocused only
|
||
|
else if(!onlyFocus && onlyUnfocus){
|
||
|
loop
|
||
|
{
|
||
|
if((GetPlayerState != STATE_NORMAL && GetPlayerState != STATE_HIT) || GetVirtualKeyState(VK_SLOWMOVE) != KEY_FREE){ObjRender_SetAlpha(option, max(0, ObjRender_GetAlpha(option)-15)); visible = false;}
|
||
|
else {ObjRender_SetAlpha(option, min(255, ObjRender_GetAlpha(option)+15)); visible = true;}
|
||
|
yield;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
///// MOVEMENT /////
|
||
|
async{
|
||
|
|
||
|
loop{
|
||
|
|
||
|
if(GetVirtualKeyState(VK_SLOWMOVE) != KEY_FREE){
|
||
|
|
||
|
async{
|
||
|
|
||
|
ascent(i in 0..15){
|
||
|
if(angchange){ObjRender_SetAngleZ(option, Interpolate_Decelerate(ObjRender_GetAngleZ(option), ang_f, i/15));}
|
||
|
ObjRender_SetX(option, Interpolate_Decelerate(ObjRender_GetX(option), playerX+offsetX_f, i/15));
|
||
|
ObjRender_SetY(option, Interpolate_Decelerate(ObjRender_GetY(option), playerY+offsetY_f, i/15));
|
||
|
yield;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
else{
|
||
|
|
||
|
async{
|
||
|
|
||
|
ascent(i in 0..15){
|
||
|
if(angchange){ObjRender_SetAngleZ(option, Interpolate_Decelerate(ObjRender_GetAngleZ(option), ang_uf, i/15));}
|
||
|
ObjRender_SetX(option, Interpolate_Decelerate(ObjRender_GetX(option), playerX+offsetX_uf, i/15));
|
||
|
ObjRender_SetY(option, Interpolate_Decelerate(ObjRender_GetY(option), playerY+offsetY_uf, i/15));
|
||
|
yield;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
yield;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
function _FadeIn(){
|
||
|
ascent(i in 0..15){
|
||
|
ObjRender_SetAlpha(option, Interpolate_Decelerate(0, 225, i/15));
|
||
|
yield;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function _FadeOut(){
|
||
|
ascent(i in 0..15){
|
||
|
ObjRender_SetAlpha(option, Interpolate_Decelerate(225, 0, i/15));
|
||
|
yield;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return option;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
------------------------------------------------------
|
||
|
|
||
|
POINTBLANK-PIV MECHANIC FUNCTIONS
|
||
|
Will be optimized somewhere down the line.
|
||
|
|
||
|
------------------------------------------------------
|
||
|
*/
|
||
|
|
||
|
// Selects an enemy in the @MainLoop-updated _enemyArray, executes _PetalDrop, and adds it to _existArray so the task isn't called again for the same enemy. maxX and maxY are the bounds of the playing field.
|
||
|
|
||
|
task _Mechanic(bool playerdeathbool, int[] _enemyArray, int [] _existArray, float maxX, float maxY, int objPlayer, int bossScene, int maxrate, int addrate, float adddist){
|
||
|
while(!playerdeathbool){
|
||
|
_enemyArray = GetIntersectionRegistedEnemyID();
|
||
|
bossScene = GetEnemyBossSceneObjectID();
|
||
|
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 && !contains(_existArray, enemy)){
|
||
|
_PetalDrop(enemy, playerdeathbool, objPlayer, bossScene, maxrate, addrate, adddist);
|
||
|
_existArray = _existArray ~ [enemy];
|
||
|
}
|
||
|
else{continue;}
|
||
|
}
|
||
|
yield;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Checks the boss scene type (nonspell/spell/last spell/invalid), the ID of the player object, and the target enemy. Drops petals with a type and drop rate that depends on the boss scene type and how close the player is to the target enemy.
|
||
|
|
||
|
task _PetalDrop(int target, bool playerdeathbool, int objPlayer, int bossScene, int maxrate, int addrate, float adddist){
|
||
|
|
||
|
while(!Obj_IsDeleted(target) && !playerdeathbool){
|
||
|
float dist = hypot(ObjMove_GetX(target)-ObjMove_GetX(objPlayer), ObjMove_GetY(target)-ObjMove_GetY(objPlayer));
|
||
|
let atktype = GetEnemyBossSceneObjectID();
|
||
|
if(dist <= (GetStgFrameHeight()-100) && atktype != ID_INVALID && ObjEnemy_GetInfo(target, INFO_SHOT_HIT_COUNT) >= 1 && ObjEnemy_GetInfo(target, INFO_DAMAGE_PREVIOUS_FRAME) > 0){
|
||
|
|
||
|
wait(maxrate + addrate*floor(dist/adddist));
|
||
|
|
||
|
}
|
||
|
else{yield;}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
task _DeathbombWarning(imgpath, int[] imgrectarray, int deathbombframes, float basescale){
|
||
|
|
||
|
int circle = _Create2DImage(imgpath, imgrectarray);
|
||
|
Obj_SetRenderPriorityI(circle, 75);
|
||
|
ObjRender_SetAlpha(circle, 255);
|
||
|
ObjRender_SetPosition(circle, ObjRender_GetX(GetPlayerObjectID()), ObjRender_GetY(GetPlayerObjectID()), 1);
|
||
|
ObjRender_SetBlendType(circle, BLEND_INV_DESTRGB);
|
||
|
|
||
|
ascent(i in 0..deathbombframes-1){
|
||
|
ObjRender_SetScaleXYZ(circle, Interpolate_Accelerate(basescale, 0, i/(deathbombframes-1)));
|
||
|
yield;
|
||
|
}
|
||
|
|
||
|
Obj_Delete(circle);
|
||
|
return;
|
||
|
|
||
|
}
|
||
|
|
||
|
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;
|
||
|
}
|
||
|
|
||
|
task _Countdown(){
|
||
|
|
||
|
//_FunIndicator;
|
||
|
|
||
|
//int timer = time;
|
||
|
int counter = CreateTextObject(
|
||
|
playerX, playerY, 45,
|
||
|
"", "GravityRegular5",
|
||
|
0xFFFFFF, 0xFFFFFF,
|
||
|
0x1AEC8C, 8,
|
||
|
51
|
||
|
);
|
||
|
|
||
|
int counter2 = CreateTextObject(
|
||
|
1720, 870, 40,
|
||
|
"", "Unispace",
|
||
|
0xFFFFFF, 0xFFFFFF,
|
||
|
0x1AEC8C, 2,
|
||
|
19
|
||
|
);
|
||
|
|
||
|
ObjText_SetHorizontalAlignment(counter, ALIGNMENT_CENTER);
|
||
|
|
||
|
while(true){
|
||
|
|
||
|
if(GetPlayerInvincibilityFrame() <= 0){Obj_SetVisible(counter, false);}
|
||
|
else{Obj_SetVisible(counter, true);}
|
||
|
ObjRender_SetPosition(counter, playerX, playerY - 96, 1);
|
||
|
ObjText_SetText(counter, IntToString(GetPlayerInvincibilityFrame()));
|
||
|
ObjText_SetText(counter2, IntToString(GetPlayerInvincibilityFrame()));
|
||
|
yield;
|
||
|
|
||
|
}
|
||
|
|
||
|
//Obj_Delete(counter);
|
||
|
|
||
|
}
|
||
|
|
||
|
task _FunIndicator(){
|
||
|
|
||
|
int counter = CreateTextObject(
|
||
|
1720, 910, 41,
|
||
|
"FUN IS PREPARED", "Origami Mommy",
|
||
|
0xFFD9B8, 0xFFFFFF,
|
||
|
0xD96600, 4,
|
||
|
39
|
||
|
);
|
||
|
|
||
|
ObjText_SetHorizontalAlignment(counter, ALIGNMENT_CENTER);
|
||
|
|
||
|
while(true){
|
||
|
|
||
|
if(GetCommonDataPtr(POINTER_CHAIN, 1) >= 64 && GetCommonDataPtr(POINTER_SPECIALCHECK, false) == false)
|
||
|
|
||
|
{Obj_SetVisible(counter, true);}
|
||
|
|
||
|
else{Obj_SetVisible(counter, false);}
|
||
|
|
||
|
ObjRender_SetPosition(counter, playerX, playerY + 128, 1);
|
||
|
|
||
|
yield;
|
||
|
|
||
|
}
|
||
|
|
||
|
//Obj_Delete(counter);
|
||
|
|
||
|
}
|