Copy to Clipboard Test

FF AcidHandla Code

const int SPR_FFACIDHANDLA_ACID_PUDDLE = 92;//Sprite used for AcidHandla`s puddles of acid.

const int SCREEN_D_ACIDHANDLA_STATUS_EFFECT = 0;//Screen D used for status effects caused by mists generated by Acidhandla

const int C_ACIDHANDLA_STATUS_CONFUSE = 0x52;//colors of status inducing mists - Confuse - swap directions input
const int C_ACIDHANDLA_STATUS_JINX_B = 0x72;//Button jinx - B
const int C_ACIDHANDLA_STATUS_JINX_A = 0x82;//Button jinx - A
const int C_ACIDHANDLA_STATUS_ANTIMAGIC = 0x102;//Strips Link of all MP and prevents regeneration.

const int FF_ACIDHANDLA_ACID_DURATION = 120;//Duration of acid puddles before decomposing into something harmless. -1 - permanent.

//FFAcidhandla
//Extended variant of Acidhandla by MoscowModder with more customizability. Moves and fires like a normal 4, or 8 headed boss. severed heads create damaging acid puddles. Can create mist that induces status effects to Link. When all heads are severes, it can regrow spare ones (1-2 times)
//Uses 2 enemy slots, 1 for core, 1 or head. If core is killed first, all heads are gone instantly and vice versa.
ffc script FFAcidhandla{
	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;		
		
		// Initialize
		ghost->Extend=3;
		Ghost_SetFlag(GHF_NO_FALL);
		Ghost_SetFlag(GHF_NORMAL);
		Ghost_SetFlag(GHF_8WAY);
		Ghost_UnsetFlag(GHF_KNOCKBACK);
		
		int firerate = Ghost_GetAttribute(ghost, 0, 60);//Delay batween firing EWeapons, in frames.
		int size = Ghost_GetAttribute(ghost, 1, 1);//Enemy size and number of heads, 1 - 1x1(4 heads), 2- 2x2(8 heads), 3 -3x3(12 heads), 4 - 4x4(16 heads)
		int speedinc = Ghost_GetAttribute(ghost, 2, 8);//Speed increase modifier with each head killed, stacked additively
		int headID = Ghost_GetAttribute(ghost, 3, enemyID+1);//Enemy ID for heads, uses next ID in list by default, must use "Other" enemy type
		int WPNS = Ghost_GetAttribute(ghost, 4, -1);//Sprite used by fired EWeapons.
		int acid = Ghost_GetAttribute(ghost, 5, 120);//Delay for severed head spots between generating acid puddles, in frames.
		int aciddam = Ghost_GetAttribute(ghost, 6, Ceiling(WPND/2));//Damage caused by stepping into acid, in 1/4th of heart, afterward acid decomposes/disappears.
		int statuseffects = Ghost_GetAttribute(ghost, 7, 31);//Status effects - add together: 1 - Confusion, 2 - magic drain, 4 - Sword Jinx, 8 - Item Jinx, 16 - Blind (white opaque flash across screen.)
		int statustimer = Ghost_GetAttribute(ghost, 8, 120);//Delay between status effect switching, in frames. 
		int regrowcount = Ghost_GetAttribute(ghost, 9, 0);//Number of times AcidHandla can regrow heads after slicing them all.
		
		ghost->Extend=3;
		Ghost_SetSize(this, ghost, size, size);
		
		Ghost_SpawnAnimationPuff(this, ghost);
		int OrigTile = ghost->OriginalTile;
		int state = 0;
		int statecounter=firerate;
		if (size>4)size=4;
		int haltcounter=0;
		int speedmod = 0;
		int statuscounter = statustimer;
		Screen->D[SCREEN_D_ACIDHANDLA_STATUS_EFFECT]=0;
		eweapon e;
		
		//Spawn heads
		int numheads = size*4;
		npc heads[16];
		int offsetX[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
		int offsetY[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
		int dirs[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
		int offsetX1[16] = {0, -16,16,0,0,0,0,0,0,0,0,0,0,0,0,0};
		int	offsetY1[16] = {-16, 0,0,16,0,0,0,0,0,0,0,0,0,0,0,0};
		int dirs1[16] = {0,2,3,1,0,0,0,0,0,0,0,0,0,0,0,0};
		int dirs2[16] = {0,0,2,3,2,3,1,1,0,0,0,0,0,0,0,0};
		int offsetX2[16] = {0, 16,-16,32,-16,32,0,16,0,0,0,0,0,0,0,0};
		int offsetY2[16] = {-16, -16,0,0,16,16,32,32,0,0,0,0,0,0,0,0};
		int dirs3[16] = {0,0,0,2,3,2,3,2,3,1,1,1,0,0,0,0};
		int offsetX3[16] = {0, 16,32,-16,48,-16,48,-16,48,0,16,32,0,0,0,0};
		int offsetY3[16] = {-16, -16,-16,0,0,16,16,32,32,48,48,48,0,0,0,0};
		int dirs4[16] = {0,0,0,0,2,3,2,3,2,3,2,3,1,1,1,1};
		int offsetX4[16] = {0, 16,32,48,-16,64,-16,64,-16,64,-16,64,0,16,32,48};
		int offsetY4[16] = {-16, -16,-16,-16,0,0,16,16,32,32,48,48,64,64,64,64};
		int acidtimer[16];
		int Ghost_MaxHP = Ghost_HP;
		for (int i=0; i<numheads; i++){
			acidtimer[i]=acid;
			heads[i]=SpawnNPC(headID);
			if (size==4){
				offsetX[i]=offsetX4[i];
				offsetY[i]=offsetY4[i];
				dirs[i]=dirs4[i];
			}
			else if (size==3){
				offsetX[i]=offsetX3[i];
				offsetY[i]=offsetY3[i];
				dirs[i]=dirs3[i];
			}
			else if (size==2){
				offsetX[i]=offsetX2[i];
				offsetY[i]=offsetY2[i];
				dirs[i]=dirs2[i];
			}
			else{
				offsetX[i]=offsetX1[i];
				offsetY[i]=offsetY1[i];
				dirs[i]=dirs1[i];
			}
			SetEnemyProperty(heads[i], ENPROP_X, Ghost_X+offsetX[i]);
			SetEnemyProperty(heads[i], ENPROP_Y, Ghost_Y+offsetY[i]);
			SetEnemyProperty(heads[i], ENPROP_DIR, dirs[i]);
			SetEnemyProperty(heads[i], ENPROP_CSET, Ghost_CSet);
		}
		Ghost_Waitframe(this, ghost);
		Ghost_Waitframe(this, ghost);
		Ghost_Waitframe(this, ghost);
		Ghost_Waitframe(this, ghost);
		
		while(true)	{
			speedmod=0;
			for (int i=0; i<numheads; i++){
				if (heads[i]->isValid()){
					SetEnemyProperty(heads[i], ENPROP_X, Ghost_X+offsetX[i]);
					SetEnemyProperty(heads[i], ENPROP_Y, Ghost_Y+offsetY[i]);
					SetEnemyProperty(heads[i], ENPROP_DIR, dirs[i]);
				}
				else speedmod+=speedinc;
				if (speedmod==(numheads*speedinc)){
					if (regrowcount>0){
						regrowcount--;
						speedmod=0;
						for (int i=0; i<numheads; i++){
							acidtimer[i]=acid;
							heads[i]=SpawnNPC(headID);
							SetEnemyProperty(heads[i], ENPROP_X, Ghost_X+offsetX[i]);
							SetEnemyProperty(heads[i], ENPROP_Y, Ghost_Y+offsetY[i]);
							SetEnemyProperty(heads[i], ENPROP_DIR, dirs[i]);
							SetEnemyProperty(heads[i], ENPROP_CSET, Ghost_CSet);
						}
						Ghost_Waitframe(this, ghost);
						Ghost_Waitframe(this, ghost);
						Ghost_Waitframe(this, ghost);
						Ghost_Waitframe(this, ghost);
					}
					else Ghost_HP=0;
				}
			}
			haltcounter = Ghost_VariableWalk8(haltcounter, SPD+speedmod, RR, HF, HNG, 15);
			statecounter--;
			if (statecounter==0){
				for (int i=0; i<numheads; i++){
					if (!heads[i]->isValid()) continue;
					if (WPND==0)continue;
					if (ghost->Weapon==EW_FIREBALL) e = FireAimedEWeapon(ghost->Weapon,heads[i]->X , heads[i]->Y, 0, 150, WPND, WPNS, -1, EWF_ROTATE);
					else e = FireNonAngularEWeapon (ghost->Weapon, heads[i]->X , heads[i]->Y, dirs[i], 200, WPND, WPNS, -1, EWF_ROTATE);
				}
				statecounter=firerate;
			}
			if (acid>0)acidtimer--;
			if (acidtimer<=0){
				for (int i=0; i<numheads; i++){
					if (heads[i]->isValid())continue;						
					e = FireNonAngularEWeapon (EW_SCRIPT1, Ghost_X + offsetX[i] , Ghost_Y + offsetY[i], 0, 0, aciddam, SPR_FFACIDHANDLA_ACID_PUDDLE, -1, EWF_UNBLOCKABLE);
					SetEWeaponDeathEffect(e, EWD_VANISH, 0);
					SetEWeaponLifespan(e, EWL_TIMER, FF_ACIDHANDLA_ACID_DURATION);
					acidtimer=acid;
				}
			}
			if (speedmod>0 && statustimer>0){
				statuscounter--;
				if (statuscounter==0){
					Screen->D[SCREEN_D_ACIDHANDLA_STATUS_EFFECT]=Rand(6);
					if (((1<<Screen->D[SCREEN_D_ACIDHANDLA_STATUS_EFFECT])&statuseffects)==0)Screen->D[SCREEN_D_ACIDHANDLA_STATUS_EFFECT]=0;
					statuscounter =statustimer;
				}
			}
			FFAcidHandlaStatusUpdate(Screen->D[SCREEN_D_ACIDHANDLA_STATUS_EFFECT]);
			if (!Ghost_Waitframe(this, ghost, false, false)){
				Screen->D[SCREEN_D_ACIDHANDLA_STATUS_EFFECT]=0;
				for (int i=0; i<numheads; i++){
					if (heads[i]->isValid())SetEnemyProperty(heads[i], ENPROP_HP, 0);
				}
				Ghost_DeathAnimation(this, ghost, GHD_EXPLODE);
				Quit();
			}		
		}
	}
}

void FFAcidHandlaStatusUpdate(int status){
	if (status==1){ //Credit goes to Mero for original code.
		Screen->Rectangle(6, 0, 0, 256, 176, C_ACIDHANDLA_STATUS_CONFUSE, 1, 1, 1, 0, true, OP_TRANS);
		if(Link->InputUp != Link->InputDown)
		{
			Link->InputUp = !Link->InputUp;
			Link->InputDown = !Link->InputDown;
		}
		if(Link->InputLeft != Link->InputRight)
		{
			Link->InputLeft = !Link->InputLeft;
			Link->InputRight = !Link->InputRight;
		}
	}
	if (status==2){
		Screen->Rectangle(6, 0, 0, 256, 176, C_ACIDHANDLA_STATUS_ANTIMAGIC, 1, 1, 1, 0, true, OP_TRANS);
		Link->MP=0;
	}
	if (status==3){
		Screen->Rectangle(6, 0, 0, 256, 176, C_ACIDHANDLA_STATUS_JINX_A, 1, 1, 1, 0, true, OP_TRANS);
		Link->SwordJinx=2;
	}
	if (status==4){
		Screen->Rectangle(6, 0, 0, 256, 176, C_ACIDHANDLA_STATUS_JINX_B, 1, 1, 1, 0, true, OP_TRANS);
		Link->ItemJinx=2;
	}
	if (status==5){
		Screen->Rectangle(6, 0, 0, 256, 176, 1, 1, 1, 1, 0, true, OP_OPAQUE);
	}
}