Copy to Clipboard Test

FF Zora Code

const int SFX_FFZORA_SPLASH_OUT = 26;//Sound to play when jumping out of water
const int SFX_FFZORA_SPLASH_IN = 26;//Sound to play when jumping into water

const int SPR_FFZORA_SPLASH = 22;//Sprite used for water splash

//Zora variant. Swims underwater, sometimes poke out head out of water to shoot eweapons at Link. Can jump out of water and walk on dry land and jump back into water again.

//Uses 5 rows of tiles
//1. Underwater
//2. About to shoot eweapons out of water
//3. Already shot eweapon out of water
//4. Jumping in-out of water
//5. Walking on dry land


ffc script FF_Zora{
	void run(int enemyID){
		npc ghost = Ghost_InitAutoGhost(this, enemyID);
		
		int HF = ghost->Homing;//All 6 used
		int HR = ghost->Haltrate;
		int RR = ghost->Rate;
		int HNG = ghost->Hunger;
		int SPD = ghost->Step;
		int WPND = ghost->WeaponDamage;
		
		int jumpspeed = Ghost_GetAttribute(ghost, 0, 1);//Affects jumping speed 
		int jumphoriz = Ghost_GetAttribute(ghost, 1, 0);//>0 - Can jump onto dry land
		int candive = Ghost_GetAttribute(ghost, 2, 1);//>0 -Can jump into water after walking on dry land
		int ewsprite = Ghost_GetAttribute(ghost, 3, -1);//Eweapon sprite
		int swimduration = Ghost_GetAttribute(ghost, 4, 240);//Underwater swimming duration between shooting eweapons.
		
		ghost->Extend=3;
		
		Ghost_SetFlag(GHF_NORMAL);
		Ghost_SetFlag(GHF_DEEP_WATER_ONLY);
		Ghost_SetFlag(GHF_NO_FALL);
		
		int OrigTile = ghost->OriginalTile;
		int State = 0;
		int haltcounter = -1;
		int statecounter = swimduration;
		int adjdir = -1;
		int cmb = -1;
		
		int defs[18];
		Ghost_StoreDefenses(ghost,defs);
		Ghost_SetAllDefenses(ghost, NPCDT_IGNORE);
		
		bool fired = false;
		
		while(true){
			if (State==0){
				haltcounter = Ghost_ConstantWalk4(haltcounter, SPD, RR, HF, HNG);
				statecounter--;
				if (statecounter==0){
					Ghost_SetDefenses(ghost, defs);
					statecounter=30;
					State=1;
				}
			}
			if (State==1){
				statecounter--;
				if (statecounter==0){
					
					if (jumpspeed>0){
						if (jumphoriz>0){
							adjdir = FindAdjacentDryCombo(ghost);
							if (adjdir>=0)Ghost_UnsetFlag(GHF_DEEP_WATER_ONLY);
						}
						Game->PlaySound(SFX_FFZORA_SPLASH_OUT);
						lweapon s = CreateLWeaponAt(LW_SPARKLE, Ghost_X, Ghost_Y);
						s->UseSprite(SPR_FFZORA_SPLASH);
						s->CollDetection=false;
						statecounter = 64;
						State=3;
					}
					else{
						statecounter=45;
						State=2;
					}
				}
			}
			if (State==2){
				if (!fired){
					eweapon e = FireAimedEWeapon(ghost->Weapon, Ghost_X, Ghost_Y, 0, 200, WPND, ewsprite, -1, 0);
					fired=true;
				}
				statecounter--;
				if (statecounter==0){
					Game->PlaySound(SFX_FFZORA_SPLASH_OUT);
					lweapon s = CreateLWeaponAt(LW_SPARKLE, Ghost_X, Ghost_Y);
					s->UseSprite(SPR_FFZORA_SPLASH);
					s->CollDetection=false;
					statecounter = swimduration;
					fired=false;
					State=0;
				}
			}
			if (State==3){
				if (adjdir==DIR_UP){
					Ghost_Y-=0.25;
				}
				if (adjdir==DIR_DOWN){
					Ghost_Y+=0.25;					
				}
				if (adjdir==DIR_LEFT){
					Ghost_X-=0.25;
				}
				if (adjdir==DIR_RIGHT){
					Ghost_X+=0.25;
				}
				if (adjdir>=0)Ghost_ForceDir(adjdir);
				if (statecounter>=48)Ghost_Z+=jumpspeed;
				else if (statecounter>=32)Ghost_Z+=jumpspeed/2;
				else if (statecounter>=16)Ghost_Z-=jumpspeed/2;
				else Ghost_Z-=jumpspeed;
				if (statecounter==32){
					eweapon e = FireAimedEWeapon(ghost->Weapon, Ghost_X, Ghost_Y, 0, 200, WPND, ewsprite, -1, 0);
				}
				statecounter--;
				if (statecounter==0){
					Ghost_Z=0;
					cmb = ComboAt(CenterX(ghost), CenterY(ghost));
					if (IsWater(cmb)){
						Game->PlaySound(SFX_FFZORA_SPLASH_IN);
						lweapon s = CreateLWeaponAt(LW_SPARKLE, Ghost_X, Ghost_Y);
						s->UseSprite(SPR_FFZORA_SPLASH);
						s->CollDetection=false;
						statecounter = swimduration;
						Ghost_SetFlag(GHF_DEEP_WATER_ONLY);
						Ghost_SetAllDefenses(ghost, NPCDT_IGNORE);
						fired=false;
						State=0;
					}
					else{
						statecounter = 160;
						State=4;
					}
				}
			}
			if (State==4){
				haltcounter =  Ghost_HaltingWalk4(haltcounter, SPD, RR, HF, HNG, HR, 30);
				if (haltcounter==30){
					eweapon e = FireAimedEWeapon(ghost->Weapon, Ghost_X, Ghost_Y, 0, 200, WPND, ewsprite, -1, 0);
				}
				statecounter--;
				if (statecounter==0){
					adjdir = FindAdjacentWaterCombo(ghost);
					if (adjdir>=0 && candive>0){
						statecounter = 64;
						State=3;
					}
					else statecounter = 32;
				}
			}
			if (State==5){
			}
			// debugValue(1,statecounter);
			// debugValue(2,adjdir);
			ghost->OriginalTile = OrigTile + 20*State;
			Ghost_Waitframe(this, ghost);
		}
	}
}

void FFZoraAnimation(npc ghost, int OrigTile, int State){
	ghost->OriginalTile = OrigTile + 20*State;
}

int FindAdjacentDryCombo(npc ghost){
	int cmb = ComboAt(CenterX(ghost), CenterY(ghost));
	int adjcmb=-1;
	for (int i=0;i<4;i++){
		adjcmb = AdjacentComboFix(cmb, i);
		if (adjcmb<0)continue;
		if (IsWater(adjcmb)) continue;
		if (Screen->ComboS[adjcmb]>0)continue;
		if (ComboFI(adjcmb,96))continue;
		if (ComboFI(adjcmb,97))continue;
		return i;
	}
	return -1;
}

int FindAdjacentWaterCombo(npc ghost){
	int cmb = ComboAt(CenterX(ghost), CenterY(ghost));
	int adjcmb=-1;
	for (int i=0;i<4;i++){
		adjcmb = AdjacentComboFix(cmb, i);
		if (adjcmb<0)continue;
		if (!IsWater(adjcmb)) continue;
		if (Screen->ComboS[adjcmb]>0)continue;
		if (ComboFI(adjcmb,96))continue;
		if (ComboFI(adjcmb,97))continue;
	return i;
	}
	return -1;
}

//Fixed variant of AdjacentCombo function from std_extension.zh
int AdjacentComboFix(int cmb, int dir)
{
	int combooffsets[13]={-0x10, 0x10, -1, 1, -0x11, -0x0F, 0x0F, 0x11};
	if ( cmb % 16 == 0 ) combooffsets[9] = -1;//if it's the left edge
	if ( (cmb % 16) == 15 ) combooffsets[10] = -1; //if it's the right edge
	if ( cmb < 0x10 ) combooffsets[11] = -1; //if it's the top row
	if ( cmb > 0x9F ) combooffsets[12] = -1; //if it's on the bottom row
	if ( combooffsets[9]==-1 && ( dir == DIR_LEFT || dir == DIR_LEFTUP || dir == DIR_LEFTDOWN ) ) return -1; //if the left columb
	if ( combooffsets[10]==-1 && ( dir == DIR_RIGHT || dir == DIR_RIGHTUP || dir == DIR_RIGHTDOWN ) ) return -1; //if the right column
	if ( combooffsets[11]==-1 && ( dir == DIR_UP || dir == DIR_RIGHTUP || dir == DIR_LEFTUP ) ) return -1; //if the top row
	if ( combooffsets[12]==-1 && ( dir == DIR_DOWN || dir == DIR_RIGHTDOWN || dir == DIR_LEFTDOWN ) ) return -1; //if the bottom row
	if ( cmb >= 0 && cmb < 176 ) return cmb + combooffsets[dir];
	else return -1;
}

//Another Item Pickup Message.
//D0-D6 - used for Action item script
//D7 - String.
item script CompatPickupString{
	void run (int foo1, int foo2, int foo3, int foo4, int foo5, int foo6, int foo7, int str){
		Screen->Message(str);
	}
}