..Oh, and I believe that pure's post length limits are fairly short for some reason so i'll have to break some ToS here.
Coming soon: Link FFC weapons, some neat B button magic spells, and more scripted bosses.
Right then well here goes:
Instill energy will turn any ordinary screen enemy into a regenerating killing machine, and rapid fire statue, well, um, it's a statue that fires rapidly...or not, it's up to you.
Uses:
Give the Instill Energy to an otherwise boring enemy, such as the Digdogger, or Aquamentus, maybe the digdogger kids too.
You can use the statue script for, well, a statue... Maybe place it on an unwalkable combo?
Actually, You might want to link it to another ffc for something really sick. Perhaps a few rapid fire scripts linked to an enemy with Instill energy?
//=============================================================
// FFC SCRIPT INSTILL ENERGY
// D0 - the first of four ffc's to use as projectiles
// D1 - new enemy HP amount
// D2 - delay between rapid fire attack (in ticks) /default is 300
// D3 - combo to use as projectiles
// D4 - CSet of projectiles
// D5 - speed of projectiles
// D6 - screen enemy number to instill energy to
// D7 - the HP regeneration of the instilled enemy :O
//=============================================================
ffc script Instill_Energy{
void run(int fireball_number, int enemyHP, int max_delay, int cdata, int cset, int speed, int screen_enemy_number, int regen){
int fire = fireball_number;
if(max_delay == 0){max_delay = 300;}
int enemy_number = 0;
npc enemy;
ffc shoot;
int delay = 0;
Waitframes(4);
npc fire_master = Screen->LoadNPC(screen_enemy_number);
npc firestorm;
fire_master->HP = enemyHP;
while(true){
if(fire_master->isValid()){
if(fire >= fireball_number+4){fire = fireball_number;}
this->X = fire_master->X; this->Y = fire_master->Y;
if(delay > max_delay){
delay = 0;
fire_master->HP = fire_master->HP + regen;
}
if(delay==20||delay==40||delay==60||delay==80){
shoot = Screen->LoadFFC(fire);
shoot->Data = cdata;
shoot->CSet = cset;
shoot->X = this->X; shoot->Y = this->Y;
int dx = Link->X - this->X;
int dy = Link->Y - this->Y;
float norm = Sqrt(dx*dx+dy*dy);
if(norm > 0)
{
shoot->Vx = dx/norm*speed;
shoot->Vy = dy/norm*speed;
}
fire++;
}
delay++;
}
else{
this->X = 0; this->Y = 0; this->Data = 0;
}
Waitframe();
}
}
}
//===================================================================================
// FFC SCRIPT RAPID FIRE STATUE
// D0 - the first ffc to use as projectiles
// D1 - the amount of ffc's to use for fireballs. Ex D0; 2, and D1 5, will use ffc's 2-7.
// D2 - speed of projectile
// D3 - combo of projectile
// D4 - Cset of projectile
// D5 - Max delay in ticks before the firing sequence restarts
// D6 - Delay between shots *Note* It will fire five shots
// during the max delay sequence. If you want non-stop firing divide max delay by five.
// ex: Delay - 20, max delay 100. -for crazy statues try delay 8, max 50.
// if the combo of the statue changes the shooting will stop.
// D7 - the ffc to link this ffc to.
//====================================================================================
ffc script Rapid_fire_statue{
void run(int fireball_number, int fireball_amount, int speed, int cdata, int cset, int max_delay, int fireball_delay, int linked_ffc){
int fire = fireball_number;
int swap = fireball_amount;
int armed = fireball_delay;
ffc shoot;
int delay = 0;
int original_combo = this->Data;
ffc linked = Screen->LoadFFC(linked_ffc);
if(max_delay == 0){max_delay = 300;}
while(true){
if(linked_ffc != 0){ this->X = linked->X; this->Y = linked->Y;}
if(fire > fireball_number+swap){ fire = fireball_number;}
if(delay > max_delay){delay = 0;}
if(this->Data == original_combo){
if(delay==armed||delay==armed+armed||delay==armed+armed+armed||
delay==armed+armed+armed+armed||delay==armed+armed+armed+armed+armed){
shoot = Screen->LoadFFC(fire);
shoot->Data = cdata;
shoot->CSet = cset;
shoot->X = this->X; shoot->Y = this->Y;
int dx = Link->X - this->X;
int dy = Link->Y - this->Y;
float norm = Sqrt(dx*dx+dy*dy);
if(norm > 0)
{
shoot->Vx = dx/norm*speed;
shoot->Vy = dy/norm*speed;
}
fire++;
}
delay++;
}
Waitframe();
}
}
}
//=======================================================
// ENEMY SPAWNER 3- Will spawn a preset amount of enemies
// from a pool of 3, chosen at random.
// Will place enemies at random locations if walkable.
// D0-D2; Enemies that might spawn,
// D3; Delay in ticks between spawns
// D4; Max number of enemies that will spawn.
// Thanks C-Dawg!
//=======================================================
ffc script enemyspawner3 {
void run(int e1, int e2, int e3, int delay, int enemy_count ) {
int RandNum = Rand(3);
int en_count = enemy_count;
int counter = delay;
while(en_count > 0){
if ( counter == 0 && RandNum == 0){
putenemy(e1);
counter = delay;
RandNum = Rand(3);
en_count = en_count - 1;
}if ( counter == 0 && RandNum == 1){
putenemy(e2);
counter = delay;
RandNum = Rand(3);
en_count = en_count - 1;
}if ( counter == 0 && RandNum == 2){
putenemy(e3);
counter = delay;
RandNum = Rand(3);
en_count = en_count - 1;
}
counter--;
Waitframe();
} // end of while loop
}
void putenemy(int eid){
int x = Rand(12)+2;
int y = Rand(7)+2;
while(!is_walkable(x,y))
{
x = Rand(12)+2;
y = Rand(7)+2;
}
npc en = Screen->CreateNPC(eid);
if(en->isValid())
{
en->X = x*16;
en->Y = y*16;
}
}
bool is_walkable(int x, int y)
{
return Screen->ComboS[x+y*16]==0;
}
}
// =======================================================
// ENEMY SPAWNER 4 - This script is used to spawn enemies. The FFC running
// the script will continue to spawn particular kinds of enemy at regular intervals
// until there are too many on the screen, or the combo used by the spawner changes.
// This version will always spawn at the location of the FFC running this script and
// will always spawn enemies untill the ghosted enemy at the location of this ffc
// is killed. currently uses enemy z255 as the ghosted enemy. Get used to using
// enemy 255 as a dummy enemy for scripts. Set up this enemy in the enemy editor.
//
// D0 - D2 = enemy_id = The enemy to be spawned. Check the table in std.zh to get values.
// D3 = delay = The delay, in tics, between enemy spawns.
// D4 = max = The maximum number of enemies that the spawner will put on the screen.
// D5 - the HP of the ghosted enemy at this ffc.
// ======================================================
ffc script enemyspawner4{
void run(int enemy_id, int enemy_id2, int enemy_id3, int delay, int max, int enemyHP){
int original_combo = this->Data; // Saves the original combo of this FFC.
int counter = delay; // Used to count the tics until it is time to spawn.
int spawnX = this->X;
int spawnY = this->Y;
int random = Rand(3);
Waitframes(4);
npc enemy_life = Screen->CreateNPC(255);
enemy_life->HP = enemyHP;
while(enemy_life->isValid()){
enemy_life->X = this->X;
enemy_life->Y = this->Y;
if ( (this->Data == original_combo) && (Screen->NumNPCs() < max) ){
if ( counter == 0 && random == 0){
npc spawnee = Screen->CreateNPC(enemy_id);
spawnee->X = spawnX;
spawnee->Y = spawnY;
counter = delay;
random = Rand(3);
}
if ( counter == 0 && random == 1){
npc spawnee = Screen->CreateNPC(enemy_id2);
spawnee->X = spawnX;
spawnee->Y = spawnY;
counter = delay;
random = Rand(3);
}
if ( counter == 0 && random == 2){
npc spawnee = Screen->CreateNPC(enemy_id3);
spawnee->X = spawnX;
spawnee->Y = spawnY;
counter = delay;
random = Rand(3);
}
else{
counter--;
} // end if
} // end if
spawnX = this->X;
spawnY = this->Y;
Waitframe();
} // end of while loop
} // end of void run
} // end of FFC script
//====================================================
// FFC SCRIPT ENEMY MAKER
// D0-D6; Enemies that might spawn,
// D7; Number of max enemies you want to spawn.
// <in Addition to boss or any other enemies set to screen enemies>;)
// Thanks to DarkDragon! :=D
//====================================================
ffc script enemymaker {
void run(int e1, int e2, int e3, int e4, int e5, int e6, int e7, int enemy_max) {
int RandNum = Rand(7);
int en_count = enemy_max;
while(en_count > 0){
if (RandNum == 0){
putenemy(e1);
} if (RandNum == 1){
putenemy(e2);
} if (RandNum == 2){
putenemy(e3);
} if (RandNum == 3){
putenemy(e4);
} if (RandNum == 4){
putenemy(e5);
} if (RandNum == 5){
putenemy(e6);
} if (RandNum == 6){
putenemy(e7);
}
en_count = en_count - 1;
RandNum = Rand(7);
}
}
void putenemy(int eid)
{
//to do this properly we really need priority queues in ZScript;)
int x = Rand(12)+2;
int y = Rand(7)+2;
while(!is_walkable(x,y))
{
x = Rand(12)+2;
y = Rand(7)+2;
}
npc en = Screen->CreateNPC(eid);
if(en->isValid())
{
en->X = x*16;
en->Y = y*16;
}
//simulate staggered spawning
Waitframe();
}
bool is_walkable(int x, int y)
{
return Screen->ComboS[x+y*16]==0;
}
}
Here's how the en_maker random one works:
It will spawn enemies of your choice,(D0-D7)at RANDOM and spawn them in random locations on the screen if walkable. Just like normal enemies. As for what enemies will spawn, check the enemy data either in std.zh, or in you quest under the enemy editor. Any enemy you have made in the editor is an eligible candidate for this script.
If you use this and still don't know why I call it the veg-o-matic, well, then I know something you don't know.
// FFC SCRIPT VEG-O-MATIC---------------------------------------
//D0- vertical guard set 1
//D1- horizontal guard set 1 *NOT BOTH!!!*
//D2- set 1 if can fire weapons
//D3- combo of weapon if d2
//D4- speed of weapon projectile if d2
//D5- time in tics between shots
//D6- CSet of weapon projectile
//D7- the starting ffc to use for projectiles
//---------------------------------------------------------
ffc script Veg_O_Matic{
void run(int vert, int horiz, int armed, int weapon_combo, int speed, int rapid, int cset, int ffc_to_use){
ffc shoot;
int ffc_cycle = ffc_to_use;
int delay = 0;
while(true){
delay++;
if(ffc_cycle >= ffc_to_use+4){ ffc_cycle = ffc_to_use;}
if(vert == 1){ if(this->Y > Link->Y+2){ this->Y--;} if(this->Y < Link->Y-2){ this->Y++;}}
if(horiz == 1){ if(this->X > Link->X+2){ this->X--;} if(this->X < Link->X-2){ this->X++;}}
if(armed == 1){
if(vert == 1){
if(delay == rapid && Link->X > this->X){
shoot = Screen->LoadFFC(ffc_cycle);
shoot->Data = weapon_combo;
shoot->Y = this->Y; shoot->X = this->X + 16;
shoot->Vx = speed;
shoot->CSet = cset;
ffc_cycle++;
delay = 0;
}
if(delay == rapid && Link->X < this->X){
shoot = Screen->LoadFFC(ffc_cycle);
shoot->Data = weapon_combo;
shoot->Y = this->Y; shoot->X = this->X - 16;
shoot->Vx = -speed;
shoot->CSet = cset;
ffc_cycle++;
delay = 0;
}
}
if(horiz == 1){
if(delay == rapid && Link->Y > this->Y){
shoot = Screen->LoadFFC(ffc_cycle);
shoot->Data = weapon_combo;
shoot->Y = this->Y + 16; shoot->X = this->X;
shoot->Vy = speed;
shoot->CSet = cset;
ffc_cycle++;
delay = 0;
}
if(delay == rapid && Link->Y < this->Y){
shoot = Screen->LoadFFC(ffc_cycle);
shoot->Data = weapon_combo;
shoot->Y = this->Y - 16; shoot->X = this->X;
shoot->Vy = -speed;
shoot->CSet = cset;
ffc_cycle++;
delay = 0;
}
}
}
Waitframe();
}
}
}
Ok, Ok, I know what you're thinking right now: "How can I get 255(or is that 256?) enemies on the screen at once and center them on an enemy and set that enemies HP to any obscene amount I want"? Well alrighty then, ask and ye shall recieve.
Flamethrower script:
//=======================================
// FFC SCRIPT FLAMETHROWER
//D0- minions to spawn (id number)
//D1- HP of the summoner
//D2- Max enemies on screen at once
//=======================================
ffc script Flamethrower{
void run(int enemy_id, int enemyHP, int enemy_swarm){
int enemy_number = 0;
npc enemy;
int slow_slowdown=0;
int death = 0;
Waitframes(4);
npc fire_master = Screen->LoadNPC(1);
npc firestorm;
fire_master->HP = enemyHP;
while(true){
if(fire_master->isValid() || fire_master->HP >0){
this->X = fire_master->X; this->Y = fire_master->Y;
if(Screen->NumNPCs() < enemy_swarm){ npc firestorm = Screen->CreateNPC(enemy_id);}
firestorm->X = this->X;
firestorm->Y = this->Y;
}
else{ death = 1;}
enemy_number = Screen->NumNPCs();
while(enemy_number > 1){
enemy = Screen->LoadNPC(enemy_number);
enemy->X = this->X; enemy->Y = this->Y;
if(death == 1){enemy->HP = 0;Screen->ClearSprites(2);}
enemy_number--;
if(enemy_number > 30){
if(slow_slowdown == 0){ slow_slowdown = enemy_number; Waitframe();}
slow_slowdown--;
}
}
Waitframe();
}
}
}
And now to make sure Link walks around in circles while being forced to repeadedly battle these baddies:
Random door generator:
//------------------------------------------------------
// Creates 1-3 closed shutters in a random direction as
// long as there is a wall.-along with a one-way wherever link enters from.
// Once the enemies have been killed the shutter will open.
// This will not overwrite essential doors added for specific dungeon map layouts :)
// For best results run at *SCREEN INIT*
// Not used yet/ -random locked doors, boss doors, open doors-
//------------------------------------------------------
ffc script random_door_generator{ //ver2.1
void run(){
int ddoor = 0;
int udoor = 0;
int ldoor = 0;
int rdoor = 0;
int RandNum = Rand(4);
if (Link->Dir == 0 && Screen->Door[DIR_DOWN] == D_WALL){ ddoor = 1;}
if (Link->Dir == 1 && Screen->Door[DIR_UP] == D_WALL){ udoor = 1;}
if (Link->Dir == 2 && Screen->Door[DIR_RIGHT] == D_WALL){ rdoor = 1;}
if (Link->Dir == 3 && Screen->Door[DIR_LEFT] == D_WALL){ ldoor = 1;}
if (RandNum == 0 && Screen->Door[DIR_DOWN] == D_WALL){ Screen->Door[DIR_DOWN] = D_SHUTTER;}
if (RandNum == 0 && Screen->Door[DIR_UP] == D_WALL){Screen->Door[DIR_UP] = D_SHUTTER;}
if (RandNum == 1 && Screen->Door[DIR_RIGHT] == D_WALL){Screen->Door[DIR_RIGHT] = D_SHUTTER;}
if (RandNum == 1 && Screen->Door[DIR_LEFT] == D_WALL){Screen->Door[DIR_LEFT] = D_SHUTTER; }
if (RandNum == 2 && Screen->Door[DIR_DOWN] == D_WALL){Screen->Door[DIR_DOWN] = D_SHUTTER;}
if (RandNum == 2 && Screen->Door[DIR_UP] == D_WALL){Screen->Door[DIR_UP] = D_SHUTTER;}
if (RandNum == 2 && Screen->Door[DIR_RIGHT] == D_WALL){Screen->Door[DIR_RIGHT] = D_SHUTTER;}
if (RandNum == 3 && Screen->Door[DIR_LEFT] == D_WALL){Screen->Door[DIR_LEFT] = D_SHUTTER;}
if (RandNum == 3 && Screen->Door[DIR_RIGHT] == D_WALL){Screen->Door[DIR_RIGHT] = D_SHUTTER;}
if (RandNum == 3 && Screen->Door[DIR_UP] == D_WALL){Screen->Door[DIR_UP] = D_SHUTTER; }
if (ddoor == 1){Screen->Door[DIR_DOWN] = D_1WAYSHUTTER;}
if (udoor == 1){Screen->Door[DIR_UP] = D_1WAYSHUTTER;}
if (rdoor == 1){Screen->Door[DIR_RIGHT] = D_1WAYSHUTTER;}
if (ldoor == 1){Screen->Door[DIR_LEFT] = D_1WAYSHUTTER; }
}
}
2.6 Armos script:
//======================================
// -ffc script Armos-
//D0 - id of enemy to create
//D1 - HP of created enemy
//======================================
ffc script Armos{
void run(int enemy_id, int enemyHP){
int trigger = 0;
npc armos;
while(true){
if(trigger == 0){
if( Abs(Link->X - this->X) <= 16 && Abs(Link->Y - this->Y) <= 16){
npc armos = Screen->CreateNPC(enemy_id);
armos->X = this->X; armos->Y = this->Y;
armos->HP = enemyHP;
this->Data=0;trigger=1;
}
}
Waitframe();
}
}
}
New one, Custom Armos. This one will get used...alot. I'm sure of it.
I guess it's true with scripts anyway; It's not how big it is, it's how you use it. :laughing:
//==================================================================================
// FFC SCRIPT SENTRY
//
// D0 - Direction can shoot / values greater than 3 return up,down,left,right.
// D1 - combo of weapon projectile
// D2 - speed of projectile
// D3 - CSet of projectile
// D4 - First of 3 ffc's to use as projectiles
//==================================================================================
ffc script Sentry{
void run(int shoot_dir, int weapon_combo, int speed, int cset, int ffc_to_use){
ffc shoot;
int ffc_cycle = ffc_to_use;
int delay = 0;
while(true){
if(ffc_cycle >= ffc_to_use+3){ ffc_cycle = ffc_to_use;}
if(delay > 0){delay--;}
if(shoot_dir > 3 && delay == 0){
if(Abs(Link->X-this->X)<14 && Link->Y < this->Y && canMove(this->X, this->Y-16)) // Up
{
shoot = Screen->LoadFFC(ffc_cycle);
shoot->Data = weapon_combo;
shoot->Y = this->Y - 16; shoot->X = this->X;
shoot->Vy = -speed; shoot->Vx=0;
shoot->CSet = cset;
ffc_cycle++;
delay = 30;
}
else if(Abs(Link->X-this->X)<14 && Link->Y > this->Y && canMove(this->X, this->Y+16)) // Down
{
shoot = Screen->LoadFFC(ffc_cycle);
shoot->Data = weapon_combo;
shoot->Y = this->Y + 16; shoot->X = this->X;
shoot->Vy = speed; shoot->Vx=0;
shoot->CSet = cset;
ffc_cycle++;
delay = 30;
}
else if(Abs(Link->Y-this->Y)<14 && Link->X < this->X && canMove(this->X-16, this->Y)) // Left
{
shoot = Screen->LoadFFC(ffc_cycle);
shoot->Data = weapon_combo;
shoot->Y = this->Y; shoot->X = this->X - 16;
shoot->Vx = -speed; shoot->Vy=0;
shoot->CSet = cset;
ffc_cycle++;
delay = 30;
}
else if(Abs(Link->Y-this->Y)<14 && Link->X > this->X && canMove(this->X+16, this->Y)) // Right
{
shoot = Screen->LoadFFC(ffc_cycle);
shoot->Data = weapon_combo;
shoot->Y = this->Y; shoot->X = this->X + 16;
shoot->Vx = speed; shoot->Vy=0;
shoot->CSet = cset;
ffc_cycle++;
delay = 30;
}
}
else{
if(shoot_dir==0 && delay == 0){
if(Abs(Link->X-this->X)<14 && Link->Y < this->Y && canMove(this->X, this->Y-16)){
shoot = Screen->LoadFFC(ffc_cycle);
shoot->Data = weapon_combo;
shoot->Y = this->Y - 16; shoot->X = this->X;
shoot->Vy = -speed; shoot->Vx=0;
shoot->CSet = cset;
ffc_cycle++;
delay = 30;
}
}
else if(shoot_dir==1 && delay == 0){
if(Abs(Link->X-this->X)<14 && Link->Y > this->Y && canMove(this->X, this->Y+16)){
shoot = Screen->LoadFFC(ffc_cycle);
shoot->Data = weapon_combo;
shoot->Y = this->Y + 16; shoot->X = this->X;
shoot->Vy = speed; shoot->Vx=0;
shoot->CSet = cset;
ffc_cycle++;
&n