299 lines
8.3 KiB
Plaintext
299 lines
8.3 KiB
Plaintext
// 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 |