// Hole worm LA style - uses ghost.zh with AutoGhost
// Notes:
// - modify the hole/lava script in order to avoid enemies with Misc[4] > 0 to fall
// - create an enemy with "other" type, set as tile the first of the set, in the order seen in the image file
// enemy attributes (can be left to 0 to set the default values - see below)
const int HOLE_ATTR_RADIUS = 1;
const int HOLE_ATTR_LENGHT = 2;
const int HOLE_ATTR_WAITTIME = 3;
// const int CT_HOLELAVA = 5; // add this if you are not defining this variable in the hole/lava script
bool loc_is_busy[176];
ffc script HoleWorm{
void run(int enemyID){
npc enemy;
float angle;
int dir;
float distance;
int counter;
int xstep;
int ystep;
int x0;
int y0;
int radius;
int lenght;
float speed;
int waittime;
// Initialize
enemy=Ghost_InitAutoGhost(this, enemyID, GHF_NORMAL);
Ghost_SpawnAnimationPuff(this, enemy);
speed=enemy->Step/100;
radius=enemy->Attributes[HOLE_ATTR_RADIUS];
lenght=enemy->Attributes[HOLE_ATTR_LENGHT];
waittime=enemy->Attributes[HOLE_ATTR_WAITTIME];
// default inputs
if(enemyID == 0) enemyID = 1;
if(radius == 0) radius = 3*16;
if(lenght == 0) lenght = 3*16;
if(speed == 0) speed = 2;
if(waittime == 0) waittime = 20;
int loc = ComboAt(enemy->X+8,enemy->Y+8);
int i = 0;
while(!isHole(Screen->ComboT[loc]) || loc_is_busy[loc]){
loc ++;
if(i>=176) break;
i ++;
if(loc>=176) loc = 0;
}
if(i>=176){
enemy->X = 200;
Quit();
}
loc_is_busy[loc] = true;
enemy->X = ComboX(loc);
enemy->Y = ComboY(loc);
Ghost_X = ComboX(loc);
Ghost_Y = ComboY(loc);
this->Data = INV_COMBO_ID;
x0 = GridX(enemy->X);
y0 = GridX(enemy->Y);
int original_tile = enemy->OriginalTile;
enemy->Misc[4] = 1;
// main loop
while(true){
// initialize enemy and ffc
enemy->X = x0;
enemy->Y = y0;
enemy->OriginalTile = INV_TILE_ID;
enemy->Tile = INV_TILE_ID;
enemy->CollDetection = false;
// wait until Link is near
counter = 0;
while(counter < waittime){
if(Distance(enemy->X,enemy->Y,Link->X,Link->Y)<radius){
counter ++;
}
else counter = 0;
Waitframe();
loc_is_busy[loc] = false;
}
// start to show up
enemy->OriginalTile = original_tile - 2;
enemy->Tile = original_tile -2;
Waitframes(20);
enemy->Tile = INV_TILE_ID;
Waitframes(20);
enemy->CollDetection = true;
angle = Angle(enemy->X,enemy->Y,Link->X,Link->Y);
dir = AngleDir8(angle);
enemy->OriginalTile = original_tile + dir;
enemy->Tile = original_tile + dir;
enemy->Dir = dir;
Waitframes(20);
// Jump outside
distance = 0.0;
if(dir == DIR_UP || dir == DIR_LEFTUP || dir == DIR_RIGHTUP) ystep = -speed;
else if(dir == DIR_DOWN || dir == DIR_LEFTDOWN || dir == DIR_RIGHTDOWN) ystep = speed;
else ystep = 0;
if(dir == DIR_LEFT || dir == DIR_LEFTDOWN || dir == DIR_LEFTUP) xstep = -speed;
else if(dir == DIR_RIGHT || dir == DIR_RIGHTDOWN || dir == DIR_RIGHTUP) xstep = speed;
else xstep = 0;
while(distance < lenght){
enemy->X += xstep;
enemy->Y += ystep;
distance = Distance(enemy->X,enemy->Y,x0,y0);
Screen->FastTile(0, (enemy->X+1.5*x0)/2.5, (enemy->Y+1.5*y0)/2.5, original_tile-1 , enemy->CSet, 128);
Screen->FastTile(0, (2*enemy->X+x0)/3, (2*enemy->Y+y0)/3, original_tile-1 , enemy->CSet, 128);
Waitframe();
if(!enemy->isValid()) break;
}
for(int i=0;i<40;i++){
Screen->FastTile(0, (enemy->X+1.5*x0)/2.5, (enemy->Y+1.5*y0)/2.5, original_tile-1 , enemy->CSet, 128);
Screen->FastTile(0, (2*enemy->X+x0)/3, (2*enemy->Y+y0)/3, original_tile-1 , enemy->CSet, 128);
Waitframe();
if(!enemy->isValid()) break;
}
while(distance > 8){
enemy->X -= xstep;
enemy->Y -= ystep;
distance = Distance(enemy->X,enemy->Y,x0,y0);
Screen->FastTile(0, (enemy->X+2*x0)/3, (enemy->Y+2*y0)/3, original_tile-1 , enemy->CSet, 128);
Screen->FastTile(0, (2*enemy->X+x0)/3, (2*enemy->Y+y0)/3, original_tile-1 , enemy->CSet, 128);
Waitframe();
if(!enemy->isValid()) break;
}
if(!enemy->isValid()) break;
// end of main loop
}
Waitframe();
Quit();
}
}