const int BARBA_QUAKE_TIME = 80; //Time in frames to shake the screen for.
const int BARBA_QUAKE_SFX = 61; //This should loop on it's own. LTTP has a good one. DO NOT SET TO BARBA'S DEFAULT ROAR SFX! IT WILL BREAK EVERYTHING!
const int BARBA_WATER_OKAY = 1; //Whether he will surface from water.
const int BARBA_PITS_OKAY = 1; //Whether he will emerge from pits.
ffc script Barba
{
void run(int enemyID)
{
// Init
npc head = Ghost_InitAutoGhost(this,enemyID);
npc body = Screen->CreateNPC(enemyID);
head->DrawXOffset+=1000;
body->DrawXOffset+=1000;
Ghost_MarkAsInUse(body);
Ghost_SetAllDefenses(body, NPCDT_IGNORE);
// Position, Resize, and store Ghost_Data
Ghost_X=256; Ghost_Y=176; //Spawn off screen;
Ghost_Transform(this,head,-1,-1,2,1);
int baseCombo=Ghost_Data;
// Flags
Ghost_SetFlag(GHF_4WAY);
Ghost_SetFlag(GHF_NO_FALL);
// Movement
int movestate;
int counter;
int basePos; //Combo
int ZVelocity=Ghost_GetAttribute(head,0,160)/100;
int segmentCount=Ghost_GetAttribute(head,1,3,1,6);
int segmentLag=Ghost_GetAttribute(head,2,10);
int segmentCombo=Ghost_Data+12;
int xoffsets[] = {-1,0,1,0,-1,0,1,0};
// int movehistory[128]; //removed as their is no use now.
// Attacking
int attackTimer;
int wDamage=head->WeaponDamage;
int wSprite=Ghost_GetAttribute(head,3,-1);
int wSound=Ghost_GetAttribute(head,4,-1);
// Misc
int dSound=head->SFX;
int frame;
int defenses[18];
Ghost_StoreDefenses(head, defenses);
// Barba Time!
do
{
if(movestate==0) //Quake
{
if(head->SFX!=BARBA_QUAKE_SFX) BarbaQuake(head);
else if(Screen->Quake==0)
{
movestate=1;
counter=0;
head->SFX=dSound;
Ghost_SetDefenses(head,defenses);
basePos = FindSpawnPoint(false,false,BARBA_WATER_OKAY,BARBA_ PITS_OKAY);
BarbaHitOffsets(head);
Ghost_X=ComboX(basePos)-8;
Ghost_Y=ComboY(basePos);
}
}
else if(movestate==1) //Surfacing
{
Ghost_Data=baseCombo;
counter++;
Ghost_Z+=ZVelocity;
if(counter==segmentCount*segmentLag)
{
Ghost_Z=(segmentCount*16);
movestate=2;
counter=0;
attackTimer=0;
}
SegmentDrawing(head, basePos, counter, segmentLag, segmentCombo, xoffsets);
}
else if(movestate==2) //Attacking
{
Ghost_Data=baseCombo+4;
if(counter==32)
{
Ghost_Data=baseCombo+8;
if(attackTimer==0)
attackTimer=Rand(50,99);
if(attackTimer%8==0)
{
float x=BarbaMouthX();
float y=head->Y+InFrontY(Ghost_Dir,3);
eweapon e=FireAimedEWeapon(EW_FIREBALL, x, y, 0, 300, wDamage,wSprite,wSound,NULL); //|EWF_UNBLOCKABLE); No... and never again rapid fire unblockable is a bad idea.
}
attackTimer--;
}
else if(counter==48)
{
movestate=3;
counter=segmentCount*segmentLag;
}
if(attackTimer==0)
counter++;
SegmentDrawing(head, basePos, segmentCount*segmentLag, segmentLag, segmentCombo, xoffsets);
}
else if(movestate==3) //Submerging
{
Ghost_Data=baseCombo;
counter--;
Ghost_Z-=ZVelocity;
if(counter<=0)
{
movestate=0;
counter=0;
Ghost_Z=0;
Ghost_X=256+Ghost_TileWidth;
}
SegmentDrawing(head, basePos, counter, segmentLag, segmentCombo, xoffsets);
}
frame++;
if(frame%8==0)
{
//pushfront and loop front to back
int front = xoffsets[0];
memmove(xoffsets, 0, xoffsets, 1, 7);
xoffsets[7]=front;
frame=0;
}
BarbaWaitframe(this,head,body,basePos);
} while(Ghost_HP>0)
if(movestate==2)
counter=segmentCount*segmentLag;
BarbaExplode(this, head, body, counter, segmentLag, segmentCombo, xoffsets, basePos);
}
void BarbaQuake(npc head)
{
Screen->Quake=BARBA_QUAKE_TIME;
head->SFX=BARBA_QUAKE_SFX;
Ghost_SetAllDefenses(head,NPCDT_IGNORE);
}
int BarbaMouthX()
{
int aimx=Ghost_X+8;
return aimx+InFrontX(Ghost_Dir, 3);
}
void BarbaHitOffsets(npc head)
{
if(Ghost_Dir==DIR_LEFT)
Ghost_SetHitOffsets(head,0,0,0,.25);
else if(Ghost_Dir==DIR_RIGHT)
Ghost_SetHitOffsets(head,0,0,.25,0);
else // if(Ghost_Dir==DIR_UP || Ghost_Dir==DIR_DOWN);
Ghost_SetHitOffsets(head,0,0,.25,.25);
}
void BarbaWaitframe(ffc this, npc head, npc body, int basePos)
{
body->X=ComboX(basePos);
if(IsSideview())
{
body->Y=160;
body->Jump=0; //keep it from falling do to sideview gravity
if(Ghost_X+8>=Link->X) Ghost_Dir=DIR_LEFT;
else Ghost_Dir=DIR_RIGHT;
}
else
{
body->Y=ComboY(basePos);
Ghost_Dir=RadianAngleDir4(ArcTan(Link->X-(Ghost_X+8),Link->Y-Ghost_Y));
}
body->HitZHeight=Ghost_Z;
Ghost_Waitframe(this,head,false,false);
}
void BarbaExplode(ffc this, npc head, npc body, int counter, int segmentLag, int segmentCombo, int xoffsets, int basePos) //Custom Death cause why not? o_O
{
//Miscellaneous Crap that has to be done first.
body->ItemSet=IS_NONE;
body->HP=HP_SILENT;
body->X=1024;
__DeathAnimStart(this, head);
__DeathAnimSFX(head->ID, head->X);
__Ghost_FlashCounter=10000; //Should last long enough.
int baseX=ComboX(basePos);
int baseY=ComboY(basePos);
int segmentCount = Div(counter,segmentLag);
int layer=3; int x; int y; int x2; int y2;
int timer;
int j=0;
if(!IsSideview())
{
head->DrawXOffset-=1000;
Ghost_Y-=Ghost_Z;
Ghost_Z=0;
}
lweapon explosion;
while(j<segmentCount)
{
for(int i=j; i < segmentCount; i++)
{
x = baseX+xoffsets[i];
y = Cond(IsSideview(),160,baseY)-16*i;
y -= Ghost_Y%16;
if(i==j)
{
x2=x;
y2=y;
}
Screen->FastCombo(layer,x,y-2,segmentCombo+Ghost_Dir,Ghost_CSet,128);
}
timer++;
if(timer%16==0)
{
explosion=Screen->CreateLWeapon(LW_BOMBBLAST);
explosion->X=x2;
explosion->Y=y2;
explosion->CollDetection=false;
j++;
}
Ghost_SetPosition(this, head); // Make sure it doesn't wander off
__Ghost_UpdateFlashing(this, head);
Ghost_WaitframeLight(this,head);
}
baseX=Ghost_X+head->DrawXOffset;
baseY=Ghost_Y+head->DrawYOffset;
// One explosion every 16 frames, 15 times
for(int i=0; i<15; i++)
{
explosion=Screen->CreateLWeapon(LW_BOMBBLAST);
explosion->X=baseX+Rand(16*Ghost_TileWidth)-8;
explosion->Y=baseY+Rand(16*Ghost_TileHeight)-8;
explosion->CollDetection=false;
for(int j=0; j<16; j++)
{
Ghost_SetPosition(this, head); // Make sure it doesn't wander off
__Ghost_UpdateFlashing(this, head);
Ghost_WaitframeLight(this, head);
}
}
__DeathAnimEnd(this, head);
}
void SegmentDrawing(npc head, int basePos, int counter, int segmentLag, int segmentCombo, int xoffsets)
{
int baseX=ComboX(basePos);
int baseY=Cond(IsSideview(),160,ComboY(basePos));
int segmentCount = Div(counter,segmentLag);
int layer=2;
int x; int y;
for(int i; i < segmentCount; i++)
{
x = baseX+xoffsets[i];
y = baseY-(16*i);
if(!IsSideview() && (i*16) >= GH_DRAW_OVER_THRESHOLD) //additional segments have a drawover threshold.
{
layer=4;
}
y-=Ghost_Z%16;
Screen->FastCombo(layer,x,y-2,segmentCombo+Ghost_Dir,Ghost_CSet,128);
}
int w=1;
if(Ghost_Dir==DIR_LEFT||Ghost_Dir==DIR_RIGHT) w=2;
x-=8;
y=baseY-Ghost_Z;
layer=Cond(Ghost_Z>=GH_DRAW_OVER_THRESHOLD,4,2);
Screen->DrawCombo(4,x,y-2,Ghost_Data+Ghost_Dir,w,1,Ghost_CSet,-1,-1,0,0,0,0,0,true,128);
}
}