const int HURRICANE_SPIN_NUMSPINS = 20;//Number of spins for Hurricane Spin technique.
const int SPIN_ATTACK_DAMAGE_MODIFIER = 2; //Spin attack damage multiplier.
const int HURRICANE_SPIN_DAMAGE_MODIFIER = 4; //Hurricane Spin damage multiplier.
const int PERIL_SCROLL_HP_THRESHOLD = 16;//Peril Beam technique HP threshold.
const int SWORD_BEAM_SHARD_PARTICLE = 105;//Particle sprite for beam shattering.
const int SWORD_BEAM_SPEED = 300;//Speed of sword beam.
//D0-Damage
//D1-Sprite used
//D2-hearts needed to fire sword beams. Negative to have MaxHP precentage requirement.
//D3-Demage from beams. Set to negative for penetrating beams.
//D4, D5 - 2 secret flags to detect with tapping.
//D6 - Sprite for sword beam.
ffc script FFC_Sword{
void run(int dam, int sprite, int beamhearts, int beamdamage, int secrettapdetect1, int secrettapdetect2, int beamsprite){
lweapon l = LweaponInit (this, LW_GHOSTED, dam, sprite, 30);
int OrigHitboxData[4]={0,0,5,5};
bool canSlash = Game->Generic[GEN_CANSLASH];
bool canSpin1 = Link->Item[I_SPINSCROLL1];
bool canSpin2 = Link->Item[I_SPINSCROLL2];
bool canCharge1 = Link->Item[I_CHARGERING1];
bool canCharge2 = Link->Item[I_CHARGERING2];
int counter=0;
int chargetype = 0;
int spinattack = 128;
int hurricane = 256;
SetLweaponHitboxOffsets(l, 0, 0, 5, 5);
if (!canSlash)
MeleeWeaponStab(this, l, l->Misc[LWEAPON_MISC_ORIGTILE], 2, 12, 79, 141, NPCD_SWORD, 41, 2);
else
MeleeWeaponSlash90Alt(this, l, l->Misc[LWEAPON_MISC_ORIGTILE], 2, 20, 79, 141, NPCD_SWORD, 41, 2);
if (!canSpin1){
LaunchSwordBeam(beamdamage, beamsprite, Link->Dir, beamhearts, SWORD_BEAM_SHARD_PARTICLE, this->InitD[7]);
MeleeWeaponEndStrike(this, l, l->Misc[LWEAPON_MISC_ORIGTILE],2, 2,2);
}
MeleeWeaponDraw(this, l, l->Misc[LWEAPON_MISC_ORIGTILE], 1, 8);
if (canCharge2) spinattack=32;
else if (canCharge1) spinattack=64;
if (canCharge2) hurricane=64;
else if (canCharge1) hurricane=128;
LweaponSetFlag(l,LWF_SWING_WHILE_WALKING);
while (UsingItem(this->InitD[7])){
if (Link->Dir!=l->Dir){
MeleeWeaponDraw(this, l, l->Misc[LWEAPON_MISC_ORIGTILE], 1, 8);
AutoRotateLweaponHitbox(l, OrigHitboxData);
}
counter++;
if ((counter>= spinattack)&&(chargetype==0)){
Game->PlaySound(SFX_CHARGE1);
chargetype=1;
}
if ((counter>= hurricane)&&(canSpin2)){
if (chargetype==1){
if (AmmoManager(CR_MAGIC, 8, 118, false)){
Game->PlaySound(SFX_CHARGE2);
chargetype=2;
}
}
}
if ((chargetype>0)&&(counter%15==0)) TapForSecretFlags(this, l, secrettapdetect1, secrettapdetect2);
LweaponWaitframe (this, l, true);
}
LweaponUnSetFlag(l,LWF_SWING_WHILE_WALKING);
int numspins=0;
if (chargetype==2){
numspins = HURRICANE_SPIN_NUMSPINS;
l->Damage*=HURRICANE_SPIN_DAMAGE_MODIFIER;
}
else if (chargetype==1){
numspins =1;
l->Damage*=SPIN_ATTACK_DAMAGE_MODIFIER;
}
if (numspins>1) LweaponSetFlag(l,LWF_SWING_WHILE_WALKING);
for (int i=1; i<=numspins;i++){
Game->PlaySound(SFX_SPINATTACK);
MeleeWeaponSlash360(this, l, l->Misc[LWEAPON_MISC_ORIGTILE], 2, 12, 79, 141, NPCD_SWORD, 41, 1);
}
LweaponUnSetFlag(l,LWF_SWING_WHILE_WALKING);
if ((Link->Item[I_CROSSSCROLL])&&(chargetype>0)){
for (int i=0;i<4;i++){
LaunchSwordBeam(beamdamage, beamsprite,i, beamhearts, SWORD_BEAM_SHARD_PARTICLE, this->InitD[7]);
}
}
else LaunchSwordBeam(beamdamage, beamsprite, Link->Dir, beamhearts, SWORD_BEAM_SHARD_PARTICLE, this->InitD[7]);
MeleeWeaponEndStrike(this, l, l->Misc[LWEAPON_MISC_ORIGTILE], 2, 2,2);
}
}
void LaunchSwordBeam(int damage, int sprite, int dir, int hearts, int shardparticle, int itm){
if (damage<=0) return;
bool canshoot=false;
if ((Link->HP<=PERIL_SCROLL_HP_THRESHOLD)&&(Link->Item[I_PERILSCROLL])) canshoot=true;
if ((hearts<0)&&(Link->HP>=((Link->MaxHP)*(Abs(hearts)/100)))) canshoot=true;
if ((hearts>0)&&(Link->HP>=hearts)) canshoot=true;
if (!canshoot) return;
//Game->PlaySound(32);
int args[8] = {damage, sprite, SWORD_BEAM_SPEED/100, shardparticle, dir ,0,0, itm};
int buffer[] = "SwordBeam";
int scr = Game->GetFFCScript(buffer);
ffc beam = LaunchScriptedLweapon(scr, args);
}
void TapForSecretFlags(ffc f, lweapon l, int flag1, int flag2){
if (!IsTappingSolidCombo (l)) return;
MeleeWeaponDraw(f, l, l->Misc[LWEAPON_MISC_ORIGTILE], 1, 12);
if (ComboAnyFlagCollision (flag1, l, false, -1))Game->PlaySound(SFX_TAP2);
else if(ComboAnyFlagCollision (flag2, l, false, -1))Game->PlaySound(SFX_TAP2);
else Game->PlaySound(SFX_TAP1);
MeleeWeaponDraw(f, l, l->Misc[LWEAPON_MISC_ORIGTILE], 1, 8);
}
//Returns TRUE if Link tries to tap solid combo with scripted sword.
bool IsTappingSolidCombo (lweapon sword){
if (Screen->isSolid((Link->X + 8), (Link->Y - 1))){
if ((Link->InputUp)&&(sword->Dir == DIR_UP)) return true;
}
if (Screen->isSolid((Link->X + 8), (Link->Y + 17))){
if ((Link->InputDown)&&(sword->Dir == DIR_DOWN)) return true;
}
if (Screen->isSolid((Link->X - 1), (Link->Y + 8))){
if ((Link->InputLeft)&&(sword->Dir == DIR_LEFT)) return true;
}
if (Screen->isSolid((Link->X + 17), (Link->Y + 8))){
if ((Link->InputRight)&&(sword->Dir == DIR_RIGHT)) return true;
}
return false;
}
ffc script SwordBeam{
void run (int damage, int sprite, int speed, int particle, int dir){
lweapon l = LweaponInit (this, LW_GHOSTED, Abs(damage), sprite, SFX_BEAM);
SetLweaponHitboxOffsets(l, 0, 0, 5, 5);
int OrigHitboxData[4]={0,0,8,8};
if (dir==DIR_UP) this->Y-=12;
if (dir==DIR_DOWN) this->Y+=12;
if (dir==DIR_LEFT) this->X-=12;
if (dir==DIR_LEFT) this->X+=12;
if (damage<0) LweaponSetFlag(l, LWF_PENETRATING);
LweaponSetFlag(l, LWF_AUTO_DIR_UPDATE);
LweaponSetFlag(l, LWF_AUTO_SPRITE_UPDATE);
LweaponSetFlag(l, LWF_NO_FALL);
SetEnemyDefense(l, NPCD_BEAM);
SetStraightMotion4(this, dir, speed);
while (l->isValid()){
AutoRotateLweaponHitbox (l, OrigHitboxData);
LweaponWaitframe (this,l, false);
}
int angle=45;
int flip[4]={3,2,0,1};
//for (int i=0;i<4;i++){
// lweapon p = CreateParticle (this->X, this->Y, particle, 0, 0, 0, 0, 30, false);
// SetParticleAngularMovement(p, angle,1.5);
// p->Flip=flip[i];
// angle+=90;
//}
}
}