Copy to Clipboard Test

FF Ganon Code

const int FFGANON_STATE_NORMAL = 0;
const int FFGANON_STATE_STUNNED = 1;
const int FFGANON_STATE_DAMAGED = 2;
const int FFGANON_STATE_INTRO = 3;

const int SFX_FFGANON_FINISH_HIM  = 15;//Sound used for near death state

//Expanded and un-hardcoded variant of Z1 ganon. Teleports around, firing eweapons at Link, if brought down to 0 HP, Link needs to hit him one last time with specific lweapon to finish off, otherwise boss fully recovers.
//Uses 2 rows of tiles, one below another.

ffc script FFGanon{
	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 stuntime = Ghost_GetAttribute(ghost, 0, 180);//Duration for near death state
		int LWFinisher = Ghost_GetAttribute(ghost, 1, 8);//ID of lweapon needed to finish off Ganon
		int sizex = Ghost_GetAttribute(ghost, 2, 2);//Tile Width
		int sizey = Ghost_GetAttribute(ghost, 3, 2);//Tile Height
		int mindamage = Ghost_GetAttribute(ghost, 4, 8);//Minimum damage of lweapon needed to finish off Ganon
		int stuncset = Ghost_GetAttribute(ghost, 5, 8);//CSet used for near death state
		int invisibility = Ghost_GetAttribute(ghost, 6, 0);//Invisibility: 0 - none, 1 - visible only to Lens of Truth, 2 - completely invisible
		int movedelay = Ghost_GetAttribute(ghost, 7, 60);//Delay between teleporting, in frames
		int ewsprite = Ghost_GetAttribute(ghost, 8, -1);//Eweapon sprite
		int introsequence = Ghost_GetAttribute(ghost, 9, 0);//introduction sequence duration, in frames
		
		ghost->Extend=3;
		Ghost_SetSize(this, ghost, sizex, sizey);
		if (sizex>2 && sizey>2)Ghost_SetHitOffsets(ghost, 8, 8, 8, 8);
		
		Ghost_SetFlag(GHF_NORMAL);
		Ghost_SetFlag(GHF_NO_FALL);
		Ghost_SetFlag(GHF_8WAY);
		Ghost_UnsetFlag(GHF_KNOCKBACK);
		
		int OrigTile = ghost->OriginalTile;
		int OrigCset = ghost->CSet;
		int State = FFGANON_STATE_INTRO;
		int haltcounter = movedelay;
		int defs[18];
		Ghost_StoreDefenses(ghost,defs);
		Ghost_SetAllDefenses(ghost, NPCDT_IGNORE);
		int stuncounter = introsequence;
		int Ghost_MaxHP = ghost->HP;
		int cmb=0;
		
		while(true){
			if (State == FFGANON_STATE_INTRO){
				stuncounter--;
				if (stuncounter==0){
					Ghost_SetDefenses(ghost, defs);
					State = FFGANON_STATE_NORMAL;
					cmb= FindSpawnPoint(true, false, false, false);
					Ghost_X = ComboX(cmb);
					Ghost_Y = ComboY(cmb);
					eweapon e = FireAimedEWeapon(ghost->Weapon, Ghost_X, Ghost_Y, 0, 200, WPND, ewsprite, -1, 0); 
				}
			}
			else if (State == FFGANON_STATE_NORMAL){
				haltcounter--;
				if (haltcounter==0){
					cmb= FindSpawnPoint(true, false, false, false);
					Ghost_X = ComboX(cmb);
					Ghost_Y = ComboY(cmb);
					haltcounter = movedelay;
					eweapon e = FireAimedEWeapon(ghost->Weapon, Ghost_X, Ghost_Y, 0, 200, WPND, ewsprite, -1, 0); 
				}
				if (invisibility>0){
					if (invisibility==1 && UsingItem(I_LENS)) ghost->DrawXOffset=0;
					else ghost->DrawXOffset=1000;
				}
				if ( Ghost_GotHit() && Ghost_HP>0){
					ghost->DrawXOffset=0;
					stuncounter=45;
					State = FFGANON_STATE_DAMAGED;
					Ghost_SetAllDefenses(ghost, NPCDT_IGNORE);
				}
				if(Ghost_HP<=0){
					Game->PlaySound(SFX_FFGANON_FINISH_HIM);
					ghost->DrawXOffset=0;
					Ghost_HP=1;
					Ghost_CSet=stuncset;
					Ghost_SetAllDefenses(ghost, NPCDT_IGNORE);
					stuncounter = stuntime;
					State = FFGANON_STATE_STUNNED;
				}
			}
			else if (State == FFGANON_STATE_DAMAGED){
				stuncounter--;
				if (stuncounter==0){
					Ghost_SetDefenses(ghost, defs);
					State = FFGANON_STATE_NORMAL;
					cmb= FindSpawnPoint(true, false, false, false);
					Ghost_X = ComboX(cmb);
					Ghost_Y = ComboY(cmb);
					eweapon e = FireAimedEWeapon(ghost->Weapon, Ghost_X, Ghost_Y, 0, 200, WPND, ewsprite, -1, 0); 
				}
			}
			else if (State == FFGANON_STATE_STUNNED){
				for (int i=1; i <= Screen->NumLWeapons(); i++){
					lweapon finisher = Screen->LoadLWeapon(i);
					if ((finisher->ID) != LWFinisher) continue;
					if (finisher->Damage<mindamage) continue;
					if (!Collision (ghost, finisher)) continue;
					Remove(finisher);
					ghost->CollDetection=false;
					Ghost_DeathAnimation(this, ghost, GHD_EXPLODE);					
					Ghost_HP=0;
				}
				stuncounter--;
				if(stuncounter==0){
					Ghost_CSet = OrigCset;
					Ghost_HP = Ghost_MaxHP;
					Ghost_SetDefenses(ghost, defs);
					State = FFGANON_STATE_NORMAL;
				}
			}
			GanonAnimation(ghost, OrigTile, State, 4);
			if (State == FFGANON_STATE_NORMAL)Ghost_Waitframe(this, ghost, false, false);
			else Ghost_Waitframe(this, ghost, true, true);
		}
	}
}

void GanonAnimation(npc ghost, int origtile, int state, int numframes){
	int offset = 0;
	if (state >0) offset = 20*(ghost->TileHeight);
	ghost->OriginalTile = origtile + offset;
}

//Remastered Ganon Room sequence.
//Place anywhere in the screen
//D0 - ID of boss NPC
//D1 - Tile used for rendering Link holding Triforce at intro
//D2 - Tile used for rendering Triforce at intro
//D3 - ID of item dropeed by boss, when killed
ffc script FFGanonRoom{
	void run(int boss, int linkholdtile, int triforcetile, int dropitem){
		if (Screen->State[ST_SECRET]) Quit();
		if (dropitem==0)dropitem = I_TRIFORCEBIG;
		Screen->Lit=false;
		Waitframes(30);
		Screen->Lit=true;
		Game->PlaySound(SFX_GANON);
		npc n = SpawnNPC(boss);
		Link->Invisible=true;
		int tr_X = 0;
		int tr_Y = 0;
		for (int i=0; i<90; i++){
			Screen->FastTile(2, Link->X, Link->Y, linkholdtile, 6, OP_OPAQUE);
			Screen->FastTile(2, Link->X, Link->Y-16, triforcetile, 8, OP_OPAQUE);
			NoAction();
			Waitframe();
		}
		Link->Invisible=false;
		while(n->isValid()){
			tr_X = n->X+8;
			tr_Y = n->Y+8;
			Waitframe();
		}
		item dp = CreateItemAt(I_DUST_PILE, tr_X, tr_Y+4);
		item it = CreateItemAt(dropitem, tr_X, tr_Y);		
		it->Pickup=2;
		while(it->isValid())Waitframe();
		Game->PlaySound(SFX_SECRET);
		Screen->TriggerSecrets();
		Screen->State[ST_SECRET]=true;
	}
}