1. Set 8-way movement flag
Ghost_SetFlag(GHF_8WAY);
2. Stun moving enemy using any method.
3. Random tiles are drawn under enemy, using enemy`s CSet.
const int SFX_BLIND_BERSERK = 31;//Sound to play,when boss goes berserk //Blind the Thief from Link to the Past //Moves around, firing eweapons at Link. whehen damaged high rnough, spawns one loose head enemy, when all loose head enemies are spawned, he will move faster. //Uses 2 rows of tiles, 1 for normal movement and for stunned state (4 frames.) ffc script Blind_the_Thief{ void run(int enemyID){ npc ghost = Ghost_InitAutoGhost(this, enemyID); int HF = ghost->Homing; int HR = ghost->Haltrate; int RR = ghost->Rate; int HNG = ghost->Hunger; int SPD = ghost->Step; int WPND = ghost->WeaponDamage; int sizex = Ghost_GetAttribute(ghost, 0, 4);//Tile Width int sizey = Ghost_GetAttribute(ghost, 1, 2);//Tile Height int looseheadID = Ghost_GetAttribute(ghost, 2, ghost->ID+1);//ID of loose heads enemy int numheads = Ghost_GetAttribute(ghost, 3, 3);//Number of heads hidden inside int berserkSPD = Ghost_GetAttribute(ghost, 4, 100);//Speed of enemy, when it went berserk int shotspeed = Ghost_GetAttribute(ghost, 5, 120);//Delay between shooting, in frames. int WPNS = Ghost_GetAttribute(ghost, 6, -1);//Eweapon sprite. int knockdown = Ghost_GetAttribute(ghost, 7, 180);//Knockdown duration, un frames. Used when spawning head int xOffset = Ghost_GetAttribute(ghost, 8, 32);//Offset used for head spawning and shooting. int yOffset = Ghost_GetAttribute(ghost, 9, 0); ghost->Extend=3; Ghost_SetSize(this, ghost, sizex, sizey); if (sizex>2)Ghost_SetHitOffsets(ghost, 4, 4, 8, 8); int State = 0; int haltcounter = -1; float angle=Rand(360); int statecounter = 0; eweapon e; int heads = 0; int shootcounter=shotspeed; int shoottimer =0; int Ghost_MaxHP = Ghost_HP; int hpthreshold = Lerp(0, Ghost_MaxHP,1-((heads+1)/(numheads+1))); int origtile = ghost->OriginalTile; int offset = 0; int facedir = 0; npc head = Screen->CreateNPC(looseheadID); int headtile=head->OriginalTile; Remove(head); bool berserk=false; Ghost_SetFlag(GHF_NORMAL); Ghost_SetFlag(GHF_IGNORE_WATER); Ghost_SetFlag(GHF_IGNORE_PITS); Ghost_SetFlag(GHF_NO_FALL); Ghost_SetFlag(GHF_8WAY); Ghost_UnsetFlag(GHF_KNOCKBACK); Ghost_SetFlag(GHF_FLYING_ENEMY); while(true){ if (State==0){ haltcounter = Ghost_ConstantWalk8(haltcounter, SPD, RR, HF, HNG); facedir = AngleDir4(Angle(ghost->X+xOffset, ghost->Y+yOffset, Link->X, Link->Y)); if (!berserk)Screen->FastTile (3,ghost->X+xOffset, ghost->Y+yOffset, headtile+facedir, Ghost_CSet,OP_OPAQUE); shootcounter--; if (shootcounter<=0){ e = FireAimedEWeapon(ghost->Weapon, ghost->X+xOffset, ghost->Y+yOffset, 0, 180, WPND, WPNS, -1, 0); shootcounter=shotspeed; } if (Ghost_HP>0 && Ghost_HP<=hpthreshold){ head = CreateNPCAt(looseheadID, Ghost_X+xOffset, Ghost_Y+yOffset); ghost->CollDetection =false; ghost->OriginalTile = GH_BLANK_TILE; heads++; hpthreshold = Lerp(0, Ghost_MaxHP,1-((heads+1)/(numheads+1))); if (heads>=numheads){ SPD = berserkSPD; berserk=true; } statecounter=knockdown; State=1; } } else if (State==1){ for (int i=0;i<=3;i++){ if (i==4){ offset = 3*Ghost_TileWidth+20*Ghost_TileHeight; break; } if (statecounter<=(ghost->ASpeed*i)||(knockdown-statecounter)<(ghost->ASpeed*i)){ offset = i*Ghost_TileWidth+20*Ghost_TileHeight; break; } } Screen->DrawTile (2, ghost->X, ghost->Y,origtile+offset, Ghost_TileWidth, Ghost_TileHeight,Ghost_CSet, -1, -1,0, 0, 0,0,true, OP_OPAQUE); statecounter--; if (statecounter<=0){ ghost->CollDetection=true; ghost->OriginalTile=origtile; State=0; if (heads==numheads)Game->PlaySound(SFX_BLIND_BERSERK); } } // debugValue(1, hpthreshold); // debugValue(2, heads); if(!Ghost_Waitframe(this, ghost, false, false)){ for (int i=1;i<=Screen->NumNPCs();i++){ npc n=Screen->LoadNPC(i); if (n->ID!=looseheadID) continue; SetEnemyProperty(n, ENPROP_HP, 0); } Ghost_DeathAnimation(this, ghost, 2); Quit(); } } } } ffc script BlindLooseHead{ void run(int enemyID){ npc ghost = Ghost_InitAutoGhost(this, enemyID); int HF = ghost->Homing; int HR = ghost->Haltrate; int RR = ghost->Rate; int HNG = ghost->Hunger; int SPD = ghost->Step; int WPND = ghost->WeaponDamage; int firenum = Ghost_GetAttribute(ghost, 0, 1);//Number of eweapons to fire per burst int shotspeed = Ghost_GetAttribute(ghost, 1, 60);//Delay between shots, in frames. Enemy won`t fire , if Weapon Damage is 0. int ewsprite = Ghost_GetAttribute(ghost, 2, -1);//Eweapon sprite int firerate = Ghost_GetAttribute(ghost, 3, 4); Ghost_SetFlag(GHF_NORMAL); Ghost_SetFlag(GHF_IGNORE_WATER); Ghost_SetFlag(GHF_IGNORE_PITS); Ghost_SetFlag(GHF_NO_FALL); Ghost_SetFlag(GHF_8WAY); Ghost_UnsetFlag(GHF_KNOCKBACK); Ghost_SetFlag(GHF_FLYING_ENEMY); int State = 0; int shotcounter=shotspeed; int shoottimer =0; int haltcounter = -1; eweapon e; int defs[18]; Ghost_StoreDefenses(ghost,defs); while(true){ if (State==0){ haltcounter = Ghost_ConstantWalk8(haltcounter, SPD, RR, HF, HNG); shotcounter--; if (shotcounter==0 && WPND>0){ shoottimer = firerate*firenum; shotcounter=shotspeed; } if (shoottimer>0){ if ((shoottimer%firerate)==0){ e = FireAimedEWeapon(ghost->Weapon, Ghost_X, Ghost_Y, 0, 200, WPND, ewsprite, -1, 0); } shoottimer--; } } if (!Ghost_Waitframe(this, ghost, false, false)){ Quit(); } } } }
https://drive.google...iew?usp=sharing