WARNING THE FOLLOWING SCRIPT IS IN DEVELOPMENT
ALSO NOTE THAT THE COMBINING DOESN'T WORK YET
ALSO NOTE THAT THE DWELLER ZOL SEEMS TO NOT SPLIT IT IS A BUG THAT I'M TRYING TO FIX
hello this is my first ghosted script it implements bouncing and dwelling zols from Link's awakening
normal zols will hide in the ground until link gets a certain in a certain radiance of it then it will attempt to hop towards him a random number of times.
when it uses up all its attempts it hides back in the ground and repeats the process.
the following arguments are for the normal zol
dweller zols will generate a random timer and then sit there and move towards link very slowly. they will continue to idle towards link until the timer is up.
then they will vibrate for a while and then jump towards link. then the process is repeated.
the following arguments are for the dweller zols
combos are set up in this order
-1 below ground
-2 first surfacing combo
-3 second surfacing combo / jumping combo
-4 grounded / idle
- Misc Attribute 10 is for the invisible combo for both enemies
NOTE the combos have to be ascending with no combos in between
here is the script Requires STD.zh, Ghost.zh and STDExtra.zh you should also have ffcscript.zh just to be safe
//These enemies behaves like the Zols and Gels from Link's awakening // // //Zol Bouncer Attributes Used: // -Misc. Attr. 1: This is wether or not the enemy starts off in the ground or not (default: 1) (range: 0-1) // -Misc. Attr. 2: This is the length the enemy launches itself when jumping (default: 20) // -Misc. Attr. 3: This is the height the enemy launches itself when jumping (default: 25) // -Misc. Attr. 4: This is the low end of the randomized jump attempts (default: 3) // -Misc. Attr. 5: This is the high end of the randomized jump attempts (default: 6) // -Misc. Attr. 6: This is the pixels radius link needs to be to trigger its aggro (default: 48) // -Misc. Attr. 7: This is wether or not the slime splits when killed (default: 0) // -Misc. Attr. 8: This is the enemy that spawns when the slime splits (default: 42) // -Misc. Attr. 9: This is wether or not the slime merges when close to another of its type(default: 0) // -Misc. Attr. 10: This is the enemy that spawns when the slime merges (default: 43) // -Misc. Attr. 11: This is the first combo index for enemy graphics (default: 0) // -Misc. Attr. 12: This is the FFC Script Slot (default: 0) (range: 0-511) // //Zol Dweller Attributes Used: // -Misc. Attr. 1: This is wether or not the enemy starts off in the ground or not (default: 0) (range: 0-1) // -Misc. Attr. 2: This is the length the enemy launches itself when jumping (default: 20) // -Misc. Attr. 3: This is the height the enemy launches itself when jumping (default: 25) // -Misc. Attr. 4: This is the low end of the randomized delay for the slime jump (default: 60) // -Misc. Attr. 5: This is the high end of the randomized delay for the slime to jump (default: 480) // -Misc. Attr. 6: This is the pixels radius link needs to be to trigger its aggro (default: 48) // -Misc. Attr. 7: This is wether or not the slime splits when killed (default: 0) // -Misc. Attr. 8: This is the enemy that spawns when the slime splits (default: 88) // -Misc. Attr. 9: This is wether or not the slime merges when close to another of its type(default: 0) // -Misc. Attr. 10: This is the enemy that spawns when the slime merges (default: 89) // -Misc. Attr. 11: This is the first combo index for enemy graphics (default: 0) // -Misc. Attr. 12: This is the FFC Script Slot (default: 0) (range: 0-511) // //The combos must right next to each other: // 01. Below ground combo (usually blank) // 02. First surfacing combo // 03. Second surfacing combo / jumping combo // 04. Grounded combo //Config constants const int Z4ZOL_MERGE_DISTANCE = 4; // The Maximum distance the slime will merge const int Z4ZOL_MERGE_WHILE_JUMPING = 0; // Requires at least one slime to be jumping const int Z4ZOL_MERGE_WHILE_LANDING = 1; // Requires at least one slime to be landing const int Z4ZOL_MERGE_WHILE_IDLEING = 1; // Requires at least one slime to be idleing const int Z4ZOL_MERGE_WHILE_VIBRATING = 1; // Requires at least one slime to be vibrating const int Z4ZOL_SPLIT_WHILE_JUMPING = 1; // Requires at least the slime to be jumping const int Z4ZOL_SPLIT_WHILE_LANDING = 1; // Requires at least the slime to be landing (bouncing zol only) const int Z4ZOL_SPLIT_WHILE_IDLEING = 1; // Requires at least the slime to be idleing const int Z4ZOL_SPLIT_WHILE_VIBRATING = 1; // Requires at least the slime to be vibrating const int Z4ZOL_SPLIT_WHILE_SURFACING = 1; // Requires at least the slime to be surfacing const int Z4ZOL_SPLIT_WHILE_BURROWING = 1; // Reqirues at least the slime to be burrowing const int Z4ZOL_TANGABLE_WHILE_SURFACING = 0; // Makes the slime tangable before he surfaces all the way const int Z4ZOL_TANGABLE_WHILE_BURROWING = 0; // Makes the slime intangable after he burrows all the way const int Z4ZOL_BOUNCE_DELAY = 15; // The delay inbetween bounces for the bouncer zol (bouncing zol only) const int Z4ZOL_IDLE_VIBRATE_TIMES = 16; // The time the slime will shift before idleing (dwelling zol only) const int Z4ZOL_IDLE_VIBRATE_SPEED = 2; // The delay between vibrations before idleing (dwelling zol only) const int Z4ZOL_SURFACING_VIBRATE_TIMES = 16; // The time the slime will shift when surfacing const int Z4ZOL_SURFACING_VIBRATE_SPEED = 2; // The delay between vibrations when surfacing //Misc. Attribute Indexes const int Z4ZOL_BOUNCER_COMBO_INDEX = 10; const int Z4ZOL_BOUNCER_BURIED_INDEX = 0; const int Z4ZOL_BOUNCER_LENGTH_INDEX = 1; const int Z4ZOL_BOUNCER_HEIGHT_INDEX = 2; const int Z4ZOL_BOUNCER_LATTEMPTS_INDEX = 3; const int Z4ZOL_BOUNCER_HATTEMPTS_INDEX = 4; const int Z4ZOL_BOUNCER_RADIUS_INDEX = 5; const int Z4ZOL_BOUNCER_SPLIT_INDEX = 6; const int Z4ZOL_BOUNCER_CHILD_INDEX = 7; const int Z4ZOL_BOUNCER_MERGE_INDEX = 8; const int Z4ZOL_BOUNCER_PARENT_INDEX = 9; const int Z4ZOL_DWELLER_COMBO_INDEX = 10; const int Z4ZOL_DWELLER_BURIED_INDEX = 0; const int Z4ZOL_DWELLER_LENGTH_INDEX = 1; const int Z4ZOL_DWELLER_HEIGHT_INDEX = 2; const int Z4ZOL_DWELLER_LDELAY_INDEX = 3; const int Z4ZOL_DWELLER_HDELAY_INDEX = 4; const int Z4ZOL_DWELLER_RADIUS_INDEX = 5; const int Z4ZOL_DWELLER_SPLIT_INDEX = 6; const int Z4ZOL_DWELLER_CHILD_INDEX = 7; const int Z4ZOL_DWELLER_MERGE_INDEX = 8; const int Z4ZOL_DWELLER_PARENT_INDEX = 9; ffc script Ghosted_Z4Zol_Bouncer { void run(int enemyID) { //Basic npc ghost; int random; int combo; int split; bool close; int angle; int attempts; int mod; //Data2 int buried; int length; int height; int lattempts; int hattempts; int radius; int splittable; int child; //Initialize ghost = Ghost_InitAutoGhost(this, enemyID); Ghost_SetFlag(GHF_NORMAL); Ghost_SetFlag(GHF_FAKE_Z); combo = Ghost_GetAttribute(ghost, Z4ZOL_BOUNCER_COMBO_INDEX, 0); buried = Ghost_GetAttribute(ghost, Z4ZOL_BOUNCER_BURIED_INDEX, 1); length = Ghost_GetAttribute(ghost, Z4ZOL_BOUNCER_LENGTH_INDEX, 20)/10; height = Ghost_GetAttribute(ghost, Z4ZOL_BOUNCER_HEIGHT_INDEX, 25)/10; lattempts = Ghost_GetAttribute(ghost, Z4ZOL_BOUNCER_LATTEMPTS_INDEX, 2); hattempts = Ghost_GetAttribute(ghost, Z4ZOL_BOUNCER_HATTEMPTS_INDEX, 6); radius = Ghost_GetAttribute(ghost, Z4ZOL_BOUNCER_RADIUS_INDEX, 48); splittable = Ghost_GetAttribute(ghost, Z4ZOL_BOUNCER_SPLIT_INDEX, 0); child = Ghost_GetAttribute(ghost, Z4ZOL_BOUNCER_CHILD_INDEX, 42); split = splittable; close = (DistanceLink(Ghost_X + Ghost_TileWidth / 2, Ghost_Y + Ghost_TileHeight / 2) <= radius); angle = AnglePos(Ghost_X + Ghost_TileWidth / 2, Ghost_Y + Ghost_TileHeight / 2, CenterLinkX(), CenterLinkY()); attempts = Rand(1, 5); while(true) { //Reinit attemps and mod attempts = Rand(3, 7); mod = 1; //Check if buried and set combo and tangibiltiy accordingly if (buried == 1) mod = 0; Ghost_Data = combo + 3 * mod; ghost->CollDetection = 1 * mod; //Make sure Zol is unkillable when it can split if (splittable) Ghost_HP = 255; //Update close variable and then loop until link is near and then surface close = (DistanceLink(Ghost_X + Ghost_TileWidth / 2, Ghost_Y + Ghost_TileHeight / 2) <= radius); while (!close) { close = (DistanceLink(Ghost_X + Ghost_TileWidth / 2, Ghost_Y + Ghost_TileHeight / 2) <= radius); Ghost_Waitframe(this, ghost, true, true); } Zol_Surface(this, ghost, child, combo, 0, 0, height, 32, splittable); //Loop until link is not near and there are no more attempts while (attempts > 0) { //Recalculate angle angle = AnglePos(Ghost_X + Ghost_TileWidth / 2, Ghost_Y + Ghost_TileHeight / 2, CenterLinkX(), CenterLinkY()); //Jump Wait and Check if hit Zol_Jump(this, ghost, child, combo, length, angle, height, splittable); Ghost_Waitframes(this, ghost, true, true, Z4ZOL_BOUNCE_DELAY); Zol_Check_Death(this, ghost, child, (splittable && Z4ZOL_SPLIT_WHILE_LANDING)); attempts --; //Waitframe since we are in a while loop Ghost_Waitframe(this, ghost, true, true); } //Hide back into ground Zol_Burrow(this, ghost, child, combo, 32, splittable); //Waitframe since we are in a while loop Ghost_Waitframe(this, ghost, true, true); } } } ffc script Ghosted_Z4Zol_Dweller { void run(int enemyID) { //Basic npc ghost; int combo; bool firstframe; int split; bool close; int angle; int timer; int mod; //Data2 int buried; int length; int height; int ldelay; int hdelay; int radius; int splittable; int child; //Initialize ghost = Ghost_InitAutoGhost(this, enemyID); Ghost_SetFlag(GHF_NORMAL); Ghost_SetFlag(GHF_FAKE_Z); combo = Ghost_GetAttribute(ghost, Z4ZOL_DWELLER_COMBO_INDEX, 0); buried = Ghost_GetAttribute(ghost, Z4ZOL_DWELLER_BURIED_INDEX, 0); length = Ghost_GetAttribute(ghost, Z4ZOL_DWELLER_LENGTH_INDEX, 20)/10; height = Ghost_GetAttribute(ghost, Z4ZOL_DWELLER_HEIGHT_INDEX, 25)/10; ldelay = Ghost_GetAttribute(ghost, Z4ZOL_DWELLER_LDELAY_INDEX, 60); hdelay = Ghost_GetAttribute(ghost, Z4ZOL_DWELLER_HDELAY_INDEX, 480); radius = Ghost_GetAttribute(ghost, Z4ZOL_DWELLER_RADIUS_INDEX, 48); splittable = Ghost_GetAttribute(ghost, Z4ZOL_DWELLER_SPLIT_INDEX, 0); child = Ghost_GetAttribute(ghost, Z4ZOL_DWELLER_CHILD_INDEX, 88); firstframe = 1; split = splittable; close = (DistanceLink(Ghost_X + Ghost_TileWidth / 2, Ghost_Y + Ghost_TileHeight / 2) <= radius); angle = AnglePos(Ghost_X + Ghost_TileWidth / 2, Ghost_Y + Ghost_TileHeight / 2, CenterLinkX(), CenterLinkY()); //timer = hdelay; while(true) { timer = Rand(ldelay, hdelay); mod = 1; //Check if buried and set combo and tangibiltiy accordingly if (buried == 1 && firstframe) mod = 0; Ghost_Data = combo + 3 * mod; ghost->CollDetection = 1 * mod; //Make sure Zol is unkillable when it can split if (splittable) Ghost_HP = 255; //Check if buried if (buried == 1 && firstframe) { //Loop until link is near and then surface while (!close) { close = (DistanceLink(Ghost_X + Ghost_TileWidth / 2, Ghost_Y + Ghost_TileHeight / 2) <= radius); Ghost_Waitframe(this, ghost, true, true); } Zol_Surface(this, ghost, child, combo, 0, 0, height, 32, splittable); firstframe = 0; } //Idle around for a while moving towards link Zol_Idle(this, ghost, child, combo, 1, timer/32, 32, splittable); //Vibrate the zol like in link's awakening Zol_Vibrate(this, ghost, child, combo, Z4ZOL_IDLE_VIBRATE_TIMES, Z4ZOL_IDLE_VIBRATE_SPEED, splittable); //Update angle and jump angle = AnglePos(Ghost_X + Ghost_TileWidth / 2, Ghost_Y + Ghost_TileHeight / 2, CenterLinkX(), CenterLinkY()); Zol_Jump(this, ghost, child, combo, length, angle, height, splittable); //Waitframe since we are in a while loop Ghost_Waitframe(this, ghost, true, true); } } } void Zol_Surface(ffc this, npc ghost, int child, int combo, int length, int angle, int height, int animspeed, int splittable) { //if (Ghost_GotHit() && splittable) { Zol_Split(this, ghost, child); } Ghost_Data = combo; Ghost_Waitframes(this, ghost, true, true, animspeed/4); if (Z4ZOL_TANGABLE_WHILE_SURFACING > 0) ghost->CollDetection = true; Ghost_Data = combo+1; Ghost_Waitframes(this, ghost, true, true, animspeed/4); Zol_Check_Death(this, ghost, child, (splittable && Z4ZOL_SPLIT_WHILE_SURFACING)); Ghost_Data = combo+2; Ghost_Waitframes(this, ghost, true, true, animspeed/4); Zol_Check_Death(this, ghost, child, (splittable && Z4ZOL_SPLIT_WHILE_SURFACING)); Ghost_Data = combo+3; Ghost_Waitframes(this, ghost, true, true, animspeed/4); Zol_Check_Death(this, ghost, child, (splittable && Z4ZOL_SPLIT_WHILE_SURFACING)); Zol_Jump(this, ghost, child, combo, length, angle, height, splittable); Zol_Vibrate(this, ghost, child, combo, Z4ZOL_SURFACING_VIBRATE_TIMES, Z4ZOL_SURFACING_VIBRATE_SPEED, splittable); if (Z4ZOL_TANGABLE_WHILE_SURFACING <= 0) ghost->CollDetection = true; } void Zol_Idle(ffc this, npc ghost, int child, int combo, int step, int time, int animspeed, int splittable) { Zol_Check_Death(this, ghost, child, (splittable & Z4ZOL_SPLIT_WHILE_IDLEING)); for(int i=0; i<time; i++) { Ghost_Waitframes(this, ghost, true, true, animspeed / 2); Zol_Check_Death(this, ghost, child, (splittable & Z4ZOL_SPLIT_WHILE_IDLEING)); Ghost_Data = combo+2; Ghost_MoveTowardLink(step, 0); Ghost_Waitframes(this, ghost, true, true, animspeed / 2); Zol_Check_Death(this, ghost, child, (splittable & Z4ZOL_SPLIT_WHILE_IDLEING)); Ghost_Data = combo+3; Ghost_Waitframe(this, ghost, true, true); } } void Zol_Vibrate(ffc this, npc ghost, int child, int combo, int time, int animspeed, int splittable) { int shift_inc = 1; int shift_pos = 0; Zol_Check_Death(this, ghost, child, (splittable && Z4ZOL_SPLIT_WHILE_VIBRATING)); for(int i=0; i<time; i++) { if (shift_pos == 1) shift_inc = -1; if (shift_pos == -1) shift_inc = 1; shift_pos += shift_inc; Ghost_X += shift_pos; Ghost_Waitframes(this, ghost, true, true, animspeed); Zol_Check_Death(this, ghost, child, (splittable && Z4ZOL_SPLIT_WHILE_VIBRATING)); //Ghost_Waitframe(this, ghost, true, true); } } void Zol_Jump(ffc this, npc ghost, int child, int combo, int length, int angle, int height, int splittable) { Ghost_Data = combo + 2; Ghost_Vx = Cos(angle) * length; Ghost_Vy = Sin(angle) * length; Ghost_Jump = height; Ghost_Jump = Max(Ghost_Jump, 0); Zol_Check_Death(this, ghost, child, (splittable && Z4ZOL_SPLIT_WHILE_JUMPING)); while (Ghost_Jump != 0) { Zol_Check_Death(this, ghost, child, (splittable && Z4ZOL_SPLIT_WHILE_JUMPING)); Ghost_Waitframe(this, ghost, true, true); } Ghost_Data = combo + 3; Ghost_Vx = 0; Ghost_Vy = 0; } void Zol_Burrow(ffc this, npc ghost, int child, int combo, int animspeed, int splittable) { if (Z4ZOL_TANGABLE_WHILE_BURROWING <= 0) ghost->CollDetection = false; Zol_Check_Death(this, ghost, child, (splittable && Z4ZOL_SPLIT_WHILE_BURROWING)); Ghost_Data = combo+3; Ghost_Waitframes(this, ghost, true, true, animspeed/4); Zol_Check_Death(this, ghost, child, (splittable && Z4ZOL_SPLIT_WHILE_BURROWING)); Ghost_Data = combo+2; Ghost_Waitframes(this, ghost, true, true, animspeed/4); Zol_Check_Death(this, ghost, child, (splittable && Z4ZOL_SPLIT_WHILE_BURROWING)); Ghost_Data = combo+1; Ghost_Waitframes(this, ghost, true, true, animspeed/4); if (Z4ZOL_TANGABLE_WHILE_BURROWING > 0) ghost->CollDetection = false; Zol_Check_Death(this, ghost, child, (splittable && Z4ZOL_SPLIT_WHILE_BURROWING)); Ghost_Data = combo; Ghost_Waitframes(this, ghost, true, true, animspeed/4); Zol_Check_Death(this, ghost, child, (splittable && Z4ZOL_SPLIT_WHILE_BURROWING)); } void Zol_Check_Death(ffc this, npc ghost, int enemy, bool splits) { if (Ghost_HP <= 0) { while(true) { Ghost_Jump = Ghost_Jump; Ghost_Waitframe(this, ghost, true, true); } } else { if (Ghost_GotHit() && splits) { Ghost_DeathAnimation(this, ghost, 128); npc gel1 = Screen->CreateNPC(enemy); npc gel2 = Screen->CreateNPC(enemy); gel1->X = Ghost_X - 8; gel1->Y = Ghost_Y; gel2->X = Ghost_X + 8; gel2->Y = Ghost_Y; Ghost_HP = 0; } } } bool NPC_DistXY(npc a, npc b, int distance) { int distx; int disty; if ( a->X > b->X ) distx = a->X - b->X; else distx = b->X - a->X; if ( a->Y > b->Y ) disty = a->Y - b->Y; else disty = b->Y - a->Y; return ( distx <= distance && disty <= distance ); }
Edited by Shadowblitz16, 02 January 2017 - 07:47 PM.