Copy to Clipboard Test

death.zh Code

const int SFX_LINK_DEATH_SCREAM = 69; //Link`s scream SFX.

//--
//death.zh A library for making alternate death animations for Link.
//
//Requires ghost.zh
//Import and compile the library. Assign FFC script slots for death sequence scripts and test scripts.
//In subscreen editor, edit HP gauge, so "1 HP" tile looks like "0 HP/empty".
//
//A note for scripting custom death animations. Instead of Waitframe, use WaitNoAction to prevent escapes offscreen. 
//Also make sure Link is not moved by anything, like sideview gravity, again to prevent escapes.
//Always end those scripts with Link->HP=0; to kill Link for real.

//Main function that deals damage to Link and executes alternate death animation, if it drives Link`s HP to <= 0.
//Damage - damage
//Deathtype - FFC script slot number
//args - pointer for array, containing arguments for script
//scream - play SFX_LINK_DEATH_SCREAM sound in additional to and sounds played by script.
void AltDamageLink(int damage, int deathtype, int args, bool scream ){
	if (Link->HP<=1) return;
	if (Link->HP<=damage && deathtype>0){
		if (scream)Game->PlaySound(SFX_LINK_DEATH_SCREAM);
		Link->HP=1;
		ffc death = RunFFCScriptOrQuit(deathtype, args);
		death->X=Link->X;
		death->Y=Link->Y;
		Game->PlayMIDI(0);
	}
	else{
		eweapon e = FireEWeapon(EW_SCRIPT10, Link->X+InFrontX(Link->Dir, 12), Link->Y+InFrontY(Link->Dir, 12), 0, 0, damage, -1, -1, EWF_UNBLOCKABLE);
		e->Dir = Link->Dir;
		e->DrawYOffset = -1000;
		SetEWeaponLifespan(e, EWL_TIMER, 1);
		SetEWeaponDeathEffect(e, EWD_VANISH, 0);
	}
}

//Link gets cut in half. Blades, chompers, lasers etc.
//D0 - 0-sliced horizontally, 1-sliced vertically
//D1 - sprite for left/top half
//D2 - sprite for bottom/right half
//D3 - part flight speed
//D4 - sound to play at the start of horror
//D5 - total duration of sequence, in frames.
//D6 - >0 - Link`s remnants are affected by sideview gravity.
ffc script LinkDeathCutInHalf{
	void run (int dir, int tile1, int tile2, int speed, int sound, int duration, int grav){
		Game->PlaySound(sound);
		lweapon l1 = CreateLWeaponAt(LW_SCRIPT10, Link->X, Link->Y);
		lweapon l2 = CreateLWeaponAt(LW_SCRIPT10, Link->X, Link->Y);
		Link->Invisible=true;
		l1->UseSprite(tile1);
		l2->UseSprite(tile2);
		l1->CollDetection=false;
		l2->CollDetection=false;
		l1->DeadState=duration;
		l2->DeadState=duration;
		int l1x = l1->X;
		int l1y = l1->Y;
		int l2x = l2->X;
		int l2y = l2->Y;
		if (IsSideview()&& grav>0){
			int dir1=Rand(45)+90;
			int dir2=Rand(45)+45;
			int lv1=Sin(dir1)*-speed;
			int lv2=Sin(dir2)*-speed;
			for (int i =0;i<duration;i++){
			//speed+=0.05;
				if (l1->isValid()){
					l1x-=speed;
					l1->X=l1x;
					lv1=Min(TERMINAL_VELOCITY, lv1+GRAVITY);
					l1y+=lv1;
					l1->Y=l1y;
				}
				if (l2->isValid()){
					l2x+=speed;
					l2->X=l2x;
					lv2=Min(TERMINAL_VELOCITY, lv2+GRAVITY);
					l2y+=lv2;
					l2->Y=l2y;
				}
				Link->Jump=0;
				WaitNoAction();
			}
		}
		else{
			for (int i =0;i<duration;i++){
				if (dir==0){
				l1x-=speed;
				l2x+=speed;
					l1->X=l1x;
					l2->X=l2x;
				}
				else{
					l1y-=speed;
				l2y+=speed;
					l1->Y=l1y;
					l2->Y=l2y;
				}
				Link->Jump=0;
				WaitNoAction();
			}
		}
		Link->HP=0;
	}
}

//Link gets blasted into stuff. Explosives, curses etc.
//D0 - Blast size: 0-normal, 1-super
//D1 - Sprite used for remnants
//D2 - Remnant splatter area, in tiles
//D3 - total duration of sequence, in frames.
ffc script LinkDeathExplosion{
	void run (int size, int splash, int splashsize, int duration){
		Game->PlaySound(3);
		Link->Invisible=true;
		lweapon l;
		if (size>0)l=CreateLWeaponAt(LW_SBOMBBLAST, Link->X, Link->Y);
		else l=CreateLWeaponAt(LW_BOMBBLAST, Link->X, Link->Y);
		l->CollDetection=false;
		lweapon s=CreateLWeaponAt(LW_SCRIPT10, Link->X-splashsize*8+8, Link->Y-splashsize*8+8);
		s->UseSprite(splash);
		s->DeadState=duration;
		s->Extend=3;
		s->CollDetection=false;
		s->TileWidth=splashsize;
		s->TileHeight = splashsize;
		for (int i =0;i<duration;i++){
		Link->Jump=0;
		WaitNoAction();
		}
		Link->HP=0;
	}
}

//Burnt to nothing by hell fire. Anything fire-based
//D0 - delay between spawning flames, in frames.
//D1 - total duration of sequence, in frames.
ffc script LinkDeathFire{
	void run(int rate, int duration){
		for (int i =duration;i>0;i--){
			if (i>duration/3 && i%3==0){
			Game->PlaySound(SFX_FIRE);
				lweapon s=CreateLWeaponAt(LW_FIRE, Link->X-8+Rand(16), Link->Y-8+Rand(16));
				s->CollDetection=false;
			}
			Link->Invisible=true;
			Link->Jump=0;
			WaitNoAction();
		}
		Link->HP=0;
	}
}

//Generic Link death animation. Frozen, Petrified, impaled etc. 
//D0 - Sprite used for remnants
//D1 - sound to play at the start of horror
//D2 - Remnant splatter area, in tiles
//D3 - >0 - Link`s remnants are affected by sideview gravity.
//D4 - total duration of sequence, in frames.
//D5 - initial upwards velocity
ffc script LinkDeathGeneric{
	void run(int sprite, int sound, int splashsize, int grav, int duration, int vel){
		Game->PlaySound(sound);
		Link->Invisible=true;
		lweapon s=CreateLWeaponAt(LW_SCRIPT10, Link->X-splashsize*8+8, Link->Y-splashsize*8+8);
		s->UseSprite(sprite);
		s->DeadState=duration;
		s->CollDetection=false;
		s->Extend=3;
		s->TileWidth=splashsize;
		s->TileHeight = splashsize;
		int ly=s->Y;
		vel*=-1;
		if (!IsSideview())vel=0;
		for (int i =0;i<duration;i++){
			if (grav>0 && IsSideview()){
				vel=Min(TERMINAL_VELOCITY, vel+GRAVITY);
				ly = s->Y+vel;
				s->Y=ly;
			}
			Link->Jump=0;
			WaitNoAction();
		}
		Link->HP=0;
	}
}

//Guillotine - cuts in half, if touched, when it has positive Vy
//D0 - death animation script slot
//D1 - Sprite for left remnant
//D2 - sprite for right remnant
//D3 - sound on slice
ffc script Guillotine{
	void run(int scr, int spr1, int spr2, int sfx){
		while(true){
			if (LinkCollision(this) && this->Vy>0){
				int args[]={1, spr1,spr2,2,sfx,128,1};
				AltDamageLink(10000, scr, args, false);
			}
			Waitframe();
		}		
	}
}

//crusher - Reduces one into nothing but bloody smear on actual stomp, or performs one funny death animation
//D0 - script alot for crushing death
//D1 - remnant sprite size
//D2 - remnant sprite slot
//D3 - crush sound
//D4 - script slot for alternate death
//D5 - sprite slot for alternate death
//D6 - sound for alternate death
ffc script Crusher{
	void run(int scr, int spr,int sprsize, int sfx,int altscr, int altspr, int altsfx){
		while(true){
			if (LinkCollision(this) && this->Vy>0 && Link->Y>(this->Y+this->EffectHeight-8)){
				int args[]={spr, sfx,sprsize,0,128,0};
				AltDamageLink(10000, scr, args, true);
			}
			else if (LinkCollision(this)){
				int args[]={altspr, altsfx,1,1,180,4};
				AltDamageLink(10000,altscr , args, false);
			}
			Waitframe();
		}		
	}
}

//Laser - cuts into pieces on touch
//D0 - death animation script slot
//D1 - remnant sprite slot
//D2 - sound on death
//D3 - remnant sprite size
ffc script RE_Laser{
	void run(int scr, int spr, int sfx, int sprsize){
		while(true){
			if (RectCollision(Link->X+7, Link->Y+7, Link->X+12, Link->Y+12, this->X, this->Y, this->X+this->EffectWidth-1, this->Y+this->EffectHeight-1)){
				int args[]={spr, sfx,sprsize,0,128,0};
				AltDamageLink(10000, scr, args, true);
			}
			Waitframe();
		}
	}
}

//Laser slices in half vertically on touch.
//D0 - script alot for crushing death
//D1 - Sprite for left remnant
//D2 - sprite for right remnant
//D3 - sound on slice
ffc script RE_Laser2{
	void run(int scr,int spr1,int spr2, int sfx){
		while(true){
			if (RectCollision(Link->X+7, Link->Y+7, Link->X+12, Link->Y+12, this->X, this->Y, this->X+this->EffectWidth-1, this->Y+this->EffectHeight-1)){
				int args[]={1, spr1,spr2,0.5,sfx,128,1};
				AltDamageLink(10000, scr, args, true);
			}
			Waitframe();
		}
	}
}

//Laser slices in half horizontally on touch.
//D0 - script alot for crushing death
//D1 - Sprite for left remnant
//D2 - sprite for right remnant
//D3 - sound on slice
ffc script RE_LaserHoriz{
	void run(int scr, int spr1, int spr2, int sfx){
		while(true){
			if (RectCollision(Link->X+7, Link->Y+7, Link->X+12, Link->Y+12, this->X, this->Y, this->X+this->EffectWidth-1, this->Y+this->EffectHeight-1)){
				int args[]={0, spr1,spr2,0.5,sfx,128,1};
				AltDamageLink(10000, scr, args, true);
			}
			Waitframe();
		}
	}
}

//Megaman x Castlevania spikes. Explode into ridiclous gibs on tough.
//D0 - death animation script slot
//D1 - remnant sprite slot
//D2 - remnant sprite size
ffc script KillerSpikes{
	void run(int scr, int spr, int sprsize){
		while(true){
			if (RectCollision(Link->X+7, Link->Y+7, Link->X+12, Link->Y+12, this->X, this->Y, this->X+this->EffectWidth-1, this->Y+this->EffectHeight-1)){
				int args[]={1, spr,sprsize,128};
				AltDamageLink(10000, scr, args, true);
			}
			Waitframe();
		}
	}
}

//Lava - incenerates on touch
//D0 - fiery death animation script slot
ffc script KillerLava{
	void run(int scr){
		while(true){
			if (RectCollision(Link->X+7, Link->Y+7, Link->X+12, Link->Y+12, this->X, this->Y, this->X+this->EffectWidth-1, this->Y+this->EffectHeight-1)){
				int args[]={4, 128};
				AltDamageLink(10000, scr, args, true);
			}
			Waitframe();
		}
	}
}