415 lines
10 KiB
Plaintext
415 lines
10 KiB
Plaintext
|
#include "./Player_Function_Laser.dnh"
|
||
|
|
||
|
// 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 CreateOption(distX, distY, startang, wvel, counterspin){
|
||
|
|
||
|
//let shot = CreatePlayerShotA1(playerX+x, playerY-150+y, 0, startang, 0, 99999, KEV_OPTION);
|
||
|
let dummy = CreatePlayerShotA1(playerX, playerY-180, 0, startang, 0, 99999, 0);
|
||
|
|
||
|
bool visible = true;
|
||
|
|
||
|
int shotspeedhome = 0;
|
||
|
float counter = 0;
|
||
|
|
||
|
float scythex = 0;
|
||
|
float scythey = 0;
|
||
|
|
||
|
float offset = 0;
|
||
|
|
||
|
float dummyX = ObjMove_GetX(dummy);
|
||
|
float dummyY = ObjMove_GetY(dummy);
|
||
|
|
||
|
let shot = CreatePlayerShotA1(dummyX, dummyY, 0, startang, 0, 99999, OPTION);
|
||
|
|
||
|
float spaceX = 0, spaceY = 0;
|
||
|
float shotang = startang;
|
||
|
|
||
|
//ObjShot_SetSpinAngularVelocity(shot, wvel);
|
||
|
ObjShot_SetAutoDelete(shot, false);
|
||
|
ObjShot_SetAutoDelete(dummy, false);
|
||
|
|
||
|
_BulletRescalePlayer(shot, 1, true, 1);
|
||
|
ObjRender_SetBlendType(shot, BLEND_ALPHA);
|
||
|
ObjRender_SetAlpha(shot, 255);
|
||
|
|
||
|
float shotX = ObjMove_GetX(shot);
|
||
|
float shotY = ObjMove_GetY(shot);
|
||
|
|
||
|
// Handles the spinning and shooting of the options.
|
||
|
|
||
|
async{
|
||
|
|
||
|
//SetShotAutoDeleteClip(-500, 128, -500, -500);
|
||
|
|
||
|
//int i = 0;
|
||
|
|
||
|
loop{
|
||
|
|
||
|
shotX = ObjMove_GetX(shot);
|
||
|
shotY = ObjMove_GetY(shot);
|
||
|
|
||
|
ObjRender_SetAngleZ(shot, 0);
|
||
|
|
||
|
if(!IsPermitPlayerShot || ripplayer){
|
||
|
|
||
|
//spaceX = clamp(spaceX-2, 0, x);
|
||
|
|
||
|
//Obj_SetVisible(shot, false);
|
||
|
Obj_SetVisible(dummy, false);
|
||
|
visible = false;
|
||
|
shotspeedhome = 0;
|
||
|
|
||
|
}
|
||
|
|
||
|
else{
|
||
|
|
||
|
//spaceX = min(x, spaceX+x/45);
|
||
|
//spaceY = min(y, spaceY+y/45);
|
||
|
|
||
|
Obj_SetVisible(shot, true);
|
||
|
visible = true;
|
||
|
Obj_SetVisible(dummy, true);
|
||
|
|
||
|
if(shotspeedhome % 4 == 0 && GetVirtualKeyState(VK_USER1) == KEY_FREE && GetVirtualKeyState(VK_SHOT) != KEY_FREE){
|
||
|
|
||
|
let bullet = CreatePlayerShotA1(shotX, shotY, 50, 270, shotDamageOption, 1.5, FIRE_OPTION);
|
||
|
|
||
|
//let water2 = CreatePlayerShotA1(shotx+25, shoty, 15, shotang+180, 1.82, 1.25, KEV_OPTIONSHOT);
|
||
|
|
||
|
ObjShot_SetAutoDelete(bullet, false);
|
||
|
_HandleDeletion(bullet);
|
||
|
|
||
|
ObjRender_SetAlpha(bullet, shotAlpha);
|
||
|
|
||
|
_BulletRescalePlayer(bullet, shotScaleOption, true, 1);
|
||
|
|
||
|
//ObjMove_SetAngularVelocity(water, [0, 0.2][typeGun]);
|
||
|
//ObjMove_SetAngularVelocity(water2, [0, 0.2][typeGun]);
|
||
|
|
||
|
Obj_SetRenderPriorityI(bullet, plrender-1);
|
||
|
|
||
|
ObjSound_Play(Base2);
|
||
|
}
|
||
|
shotspeedhome++;
|
||
|
//counter;
|
||
|
}
|
||
|
|
||
|
yield;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
task _HandleDeletion(int target){
|
||
|
|
||
|
while(ObjMove_GetY(target) > -96){
|
||
|
if(Obj_IsDeleted(target)){break;}
|
||
|
yield;
|
||
|
}
|
||
|
Obj_Delete(target);
|
||
|
return;
|
||
|
|
||
|
}
|
||
|
|
||
|
// Having the options move with Kevin if not shooting and/or focused.
|
||
|
async{
|
||
|
float angmove = 0;
|
||
|
|
||
|
loop{
|
||
|
|
||
|
ObjMove_SetPosition(shot, playerX+counterspin*spaceX*cos(shotang), playerY-offset+counterspin*spaceY*sin(shotang));
|
||
|
shotang += 3*counterspin;
|
||
|
|
||
|
ObjMove_SetPosition(dummy, playerX, playerY);
|
||
|
|
||
|
// If under player: render above
|
||
|
|
||
|
if(shotY > playerY){Obj_SetRenderPriorityI(shot, plrender+1);}
|
||
|
else{Obj_SetRenderPriorityI(shot, plrender-1);}
|
||
|
|
||
|
if(GetVirtualKeyState(VK_SLOWMOVE) != KEY_FREE){
|
||
|
|
||
|
spaceX = max(distX*0.6, spaceX-distX*1/15);
|
||
|
spaceY = max(distY*0.6, spaceY-distY*1/15);
|
||
|
|
||
|
}
|
||
|
|
||
|
else{
|
||
|
|
||
|
spaceX = min(distX*1, spaceX+distX*1/15);
|
||
|
spaceY = min(distY*1, spaceY+distY*1/15);
|
||
|
|
||
|
}
|
||
|
|
||
|
yield;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
async{
|
||
|
loop{
|
||
|
|
||
|
if(visible == true){ObjShot_SetIntersectionEnable(shot, true); ObjShot_SetIntersectionEnable(dummy, true); counter += (1/240); counter = min(counter, 1);}
|
||
|
|
||
|
else if (visible != true && GetVirtualKeyState(VK_SLOWMOVE) != KEY_FREE){ObjShot_SetIntersectionEnable(shot, false); ObjShot_SetIntersectionEnable(dummy, false);}
|
||
|
|
||
|
else {ObjShot_SetIntersectionEnable(shot, false); ObjShot_SetIntersectionEnable(dummy, false); counter = 0;}
|
||
|
yield;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return shot;
|
||
|
|
||
|
}
|
||
|
|
||
|
// CALL THIS TASK FIRST
|
||
|
|
||
|
task InitiateOptions(){
|
||
|
|
||
|
// Far left, left, right, far right
|
||
|
|
||
|
float distX = 175;
|
||
|
float distY = 175;
|
||
|
float[] angArr = [0, 90, 180, 270];
|
||
|
|
||
|
int count = 0;
|
||
|
|
||
|
for each (float entry in ref angArr){
|
||
|
|
||
|
int option = CreateOption(distX, distY, angArr[count], 1, -1);
|
||
|
|
||
|
optionArr = optionArr ~ [option];
|
||
|
|
||
|
count++;
|
||
|
|
||
|
}
|
||
|
|
||
|
SpecialWeapon(objPlayer);
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
task BaseShot(){
|
||
|
|
||
|
int angMultiplier = 0;
|
||
|
|
||
|
// lASER!!!
|
||
|
|
||
|
_RenderLaser(objPlayer, 0, 300, GetStgFrameHeight()*1.5, 64, 0, shotDamageLaser);
|
||
|
|
||
|
}
|
||
|
|
||
|
task SpecialWeapon(int ID){
|
||
|
|
||
|
int angMultiplier = 0;
|
||
|
float angFlux = 10;
|
||
|
float ang1 = 180;
|
||
|
float ang2 = 180;
|
||
|
float[] angFire = [270-20, 270+20];
|
||
|
|
||
|
while(true){
|
||
|
|
||
|
if(GetVirtualKeyState(VK_USER1) != KEY_FREE && GetCommonDataPtr(POINTER_SPECIALAMMO, 100) > 0 && IsPermitPlayerShot && !ripplayer){
|
||
|
|
||
|
SetCommonDataPtr(POINTER_SPECIALCHECK, true);
|
||
|
SetCommonDataPtr(POINTER_CHAINCHECK, true);
|
||
|
|
||
|
// (Approx.) 20 ammo per second
|
||
|
|
||
|
SetCommonDataPtr(POINTER_SPECIALAMMO, max(0, GetCommonDataPtr(POINTER_SPECIALAMMO, 100)-(20/60)));
|
||
|
|
||
|
if(shotspeed % 4 == 0){
|
||
|
|
||
|
float x = ObjMove_GetX(ID);
|
||
|
float y = ObjMove_GetY(ID);
|
||
|
|
||
|
// 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, GetCommonData("MinRank", 1), GetCommonData("MaxRank", 12)));
|
||
|
|
||
|
angFire[0] = 270 + angFlux * sin(ang1) + rand(-5, 5);
|
||
|
angFire[1] = 270 + angFlux * sin(ang2) + rand(-5, 5);
|
||
|
// YASS FIRE THOSE BITCH KILLER SLASHES
|
||
|
FireSlash(angFire[0], 50, 35, 45);
|
||
|
FireSlash(angFire[1], 50, 35, 45);
|
||
|
|
||
|
ang1 += 25;
|
||
|
ang2 -= 25;
|
||
|
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
else{
|
||
|
|
||
|
SetCommonDataPtr(POINTER_CHAINCHECK, false);
|
||
|
if(GetCommonDataPtr(POINTER_CHAINGAUGE, 0) <= 0){SetCommonDataPtr(POINTER_SPECIALCHECK, false);}
|
||
|
|
||
|
}
|
||
|
|
||
|
yield;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
task FireSlash(
|
||
|
float angle, baseSpd,
|
||
|
int decelTime, lifeTime
|
||
|
){
|
||
|
|
||
|
int slash = CreatePlayerShotA1(playerX, playerY, baseSpd, angle, shotDamageSpecial, 8, FIRE_SPECIAL);
|
||
|
ObjShot_SetPenetrateShotEnable(slash, false);
|
||
|
_BulletRescalePlayer(slash, shotScaleSpecial, true, 1);
|
||
|
|
||
|
Obj_SetRenderPriorityI(slash, plrender-1);
|
||
|
|
||
|
//ObjRender_SetBlendType(slash, BLEND_ADD_ARGB);
|
||
|
ObjSound_Play(Base5);
|
||
|
ObjShot_SetEraseShot(slash, true);
|
||
|
|
||
|
async{
|
||
|
|
||
|
ascent(i in 0..3){
|
||
|
int slashA = CreatePlayerShotA1(playerX, playerY, baseSpd, angle, shotDamageSpecial/5, 32, FIRE_SPECIAL);
|
||
|
_BulletRescalePlayer(slashA, shotScaleSpecial/2, true, 1);
|
||
|
//ObjRender_SetBlendType(slashA, BLEND_ADD_ARGB);
|
||
|
ObjShot_SetPenetrateShotEnable(slashA, false);
|
||
|
Obj_SetRenderPriorityI(slashA, plrender-1);
|
||
|
Fade(slashA);
|
||
|
wait(10);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
task Fade(int ID){
|
||
|
|
||
|
ObjMove_AddPatternA2(ID, 0, baseSpd/2, [rand(180, 230), rand(-50, 30)][rand_int(0, 1)], (-baseSpd/2)/(decelTime), 2, 0);
|
||
|
|
||
|
ascent(i in 0..(decelTime)){
|
||
|
ObjRender_SetAlpha(ID, Interpolate_Accelerate(shotAlpha, 0, i/(decelTime)));
|
||
|
yield;
|
||
|
}
|
||
|
|
||
|
Obj_Delete(ID);
|
||
|
|
||
|
}
|
||
|
|
||
|
async{
|
||
|
|
||
|
ObjMove_SetAcceleration(slash, -baseSpd/decelTime);
|
||
|
ObjMove_SetMaxSpeed(slash, baseSpd/50);
|
||
|
ObjRender_SetAlpha(slash, shotAlpha);
|
||
|
|
||
|
ascent(i in 0..decelTime){
|
||
|
ObjRender_SetScaleXYZ(slash, Interpolate_Accelerate(shotScaleSpecial/1.25, shotScaleSpecial, i/decelTime));
|
||
|
yield;
|
||
|
}
|
||
|
|
||
|
ascent(i in 0..(lifeTime-decelTime)){
|
||
|
ObjRender_SetAlpha(slash, Interpolate_Accelerate(shotAlpha, 0, i/(lifeTime-decelTime)));
|
||
|
yield;
|
||
|
}
|
||
|
|
||
|
Obj_Delete(slash);
|
||
|
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Bomb
|
||
|
// Holy fuck its literally YoumuA IBP
|