Copy to Clipboard Test

FF Phasing Wizzrobe Code

const int FF_WIZZROBE2_DEFAULT_SUMMON_ID = 106;//Default summoned enemy ID.

//FF Phasing Wizzrobe.

//Walks around, ocassionally phasing through solid combos. Shoots eweapons, when facing Link.

//Step speed, Homiong factor, Random Rate, Hunger, Halt Rate are used.

ffc script FF_PhaseWizzrobe{
	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 Shotspeed = Ghost_GetAttribute(ghost, 0, 30);//Delay between shots, in frames.
		int Teledelay = Ghost_GetAttribute(ghost, 1, 8);//Delay between halting and phassing.
		int Wpn = Ghost_GetAttribute(ghost, 2, 0);//Attack type: 0 - 1 shot, 1- 4 shots orthogonally, 2-8 shots in orthogonal and diagonal directions, 3 - summon enemies, 4 - nukes the whole screen for damage anywhere!, 5 - Aimed eweapon at Link, 6 - tripled aimed eweapon.
		int EWType = Ghost_GetAttribute(ghost, 3, -1);//Weapon sprite / Enemy ID / nuke flash color
		int ewSound = Ghost_GetAttribute(ghost, 4, -1);// Weapon fire sound / enemy count
		int WPNSPD = Ghost_GetAttribute(ghost, 5, 300);//Eweapon speed.
		
		ghost->Extend=3;
		
		Ghost_SetFlag(GHF_NORMAL);
		Ghost_SetFlag(GHF_NO_FALL);
		Ghost_UnsetFlag(GHF_KNOCKBACK);
		
		int OrigTile = ghost->OriginalTile;
		int State = 0;
		int statecounter = 0;
		int haltcounter = -1;
		int shotcounter = 0;
		int phasedir=-1;
		int posarray[8]={0,0,0,0,0,0,0,0};
		int cmb=-1;
		eweapon e;
		int ewflags=0;
		if (ghost->Weapon<139 || ghost->Weapon>=143)ewflags|=EWF_ROTATE;
		
		int defs[18];
		Ghost_StoreDefenses(ghost,defs);
		
		while(true){
			if (State==0){
				haltcounter=Ghost_HaltingWalk4(haltcounter, SPD, RR, HF, HNG, HR, Teledelay);
				if (WPND>0 && shotcounter==0 && LinkAlign(ghost)){
					if (Wpn == 0){
						e = FireNonAngularEWeapon(ghost->Weapon, Ghost_X, Ghost_Y, ghost->Dir, WPNSPD, WPND, EWType,ewSound, ewflags);
					}
					else if (Wpn == 1){
						int dirs[4]= {DIR_UP, DIR_DOWN, DIR_LEFT, DIR_RIGHT};
						Game->PlaySound(ewSound);
						for (int i=0;i<SizeOfArray(dirs);i++){
							e = FireNonAngularEWeapon(ghost->Weapon, Ghost_X, Ghost_Y, dirs[i], WPNSPD, WPND, EWType,0, ewflags);
						}
					}
					else if (Wpn == 2){
						int dirs[8] = {DIR_UP, DIR_RIGHTUP, DIR_RIGHT, DIR_RIGHTDOWN, DIR_DOWN, DIR_LEFTDOWN, DIR_LEFT, DIR_LEFTUP};
						Game->PlaySound(ewSound);
						for (int i=0;i<SizeOfArray(dirs);i++){
							e = FireNonAngularEWeapon(ghost->Weapon, Ghost_X, Ghost_Y, dirs[i], WPNSPD, WPND, EWType,0, ewflags);
						}
					}
					else if (Wpn == 3){
						Game->PlaySound(SFX_SUMMON);
						for (int i=1; i<=ewSound;i++){
							npc en = CreateNPCAt(Cond(EWType>0,EWType,FF_WIZZROBE2_DEFAULT_SUMMON_ID), Ghost_X,Ghost_Y);
						}
					}
					else if (Wpn == 4){
						e = FireEWeapon(EW_SCRIPT10, Link->X+InFrontX(Link->Dir, 12), Link->Y+InFrontY(Link->Dir, 12), 0, 0, WPND, 22, ewSound, EWF_UNBLOCKABLE);
						e->Dir = Link->Dir;
						e->DrawYOffset = -1000;
						SetEWeaponLifespan(e, EWL_TIMER, 1);
						SetEWeaponDeathEffect(e, EWD_VANISH, 0);
						
						for (int i=1; i<=60;i++){
							if(i % 2 == 0) Screen->Rectangle(6, 0, 0, 256, 172, Cond(EWType>0,EWType,22), 1, 0, 0, 0, true, 64);
							Ghost_Waitframe(this, ghost);
						}
					}
					else if (Wpn == 5){
						e = FireAimedEWeapon(ghost->Weapon, CenterX(ghost)-8, CenterY(ghost)-8, 0, WPNSPD, WPND, EWType, -1, ewflags);
					}
					else if (Wpn == 6){
						e = FireAimedEWeapon(ghost->Weapon, CenterX(ghost)-8, CenterY(ghost)-8, 0, WPNSPD, WPND, EWType, -1, ewflags);
						e = FireAimedEWeapon(ghost->Weapon, CenterX(ghost)-8, CenterY(ghost)-8, 0.2, WPNSPD, WPND, EWType, -1, ewflags);
						e = FireAimedEWeapon(ghost->Weapon, CenterX(ghost)-8, CenterY(ghost)-8, -0.2, WPNSPD, WPND, EWType, -1, ewflags);
					}
					shotcounter=Shotspeed;
				}
				cmb = ComboAt(CenterX(ghost), CenterY(ghost));
				if (haltcounter==1){					
					for (int i=0;i<8;i++){
						posarray[i]=AdjacentComboFix(cmb, i, 2);
						int curcmb= posarray[i];
						if (curcmb<0)continue;
						if (Screen->ComboS[curcmb]>0) posarray[i]=-1;
						if (ComboFI(curcmb, CF_NOENEMY)) posarray[i]=-1;
						if (IsWater(curcmb))posarray[i]=-1;
						if (IsPit(curcmb))posarray[i]=-1;
					}
					while(phasedir<0){
						bool nospaces=false;
						for (int i=0;i<=8;i++){
							if (i==8){
								nospaces=true;
								break;
							}
							if (posarray[i]<0)continue;
							else break;
						}
						if (nospaces){
							phasedir=-1;
							break;
						}
						if (Rand(255)<HF){
							phasedir = Cursor_ClosestToPos(posarray, ComboAt(CenterLinkX(),CenterLinkY()));
						}
						else{
							phasedir = Rand(7);
							while(posarray[phasedir]<0)phasedir = Rand(7);
						}
						if (posarray[phasedir]>=0)break;
					}
					if (phasedir>=0){
						statecounter=32;
						State=1;
					}
				}
			}
			else if (State==1){
				if (phasedir==DIR_UP){
					Ghost_Y--;
				}
				if (phasedir==DIR_DOWN){
					Ghost_Y++;
				}
				if (phasedir==DIR_LEFT){
					Ghost_X--;
				}
				if (phasedir==DIR_RIGHT){
					Ghost_X++;
				}
				if (phasedir==DIR_LEFTUP){
					Ghost_Y--;
					Ghost_X--;
				}
				if (phasedir==DIR_RIGHTUP){
					Ghost_Y--;
					Ghost_X++;
				}
				if (phasedir==DIR_LEFTDOWN){
					Ghost_X--;
					Ghost_Y++;
				}
				if (phasedir==DIR_RIGHTDOWN){
					Ghost_X++;
					Ghost_Y++;
				}
				statecounter--;
				if (IsOdd(statecounter))ghost->DrawXOffset=1000;
				else ghost->DrawXOffset=0;
				if (statecounter==0){
					ghost->DrawXOffset=0;
					phasedir=-1;
					State=0;
				}
			}
			if (shotcounter>0)shotcounter--;
			Ghost_Waitframe(this, ghost);
		}
	}
	
	int Cursor_ClosestToPos(int list, int pos){
		int dist = 9999;
		int ret = 0;
		int pos2 = 0;
		int dist2 = 0;
		for (int i = 0; i<SizeOfArray(list);i++){
			if (list[i]==-1)continue;
			pos2 = list[i];
			dist2 = Distance(ComboX(pos2), ComboY(pos2), ComboX(pos), ComboY(pos));
			if (dist2<dist)dist=dist2;
			else continue;
			ret=i;
		}
		return ret;
	}
	
	//! Returns the combo ID of a combo based on a location, in a givem direction, N combos away.
	int AdjacentComboFix(int cmb, int dir, int dist){
		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] && ( dir == DIR_LEFT || dir == DIR_LEFTUP || dir == DIR_LEFTDOWN || dir == DIR_LEFTUP ) ) return -1; //if the left columb
		if ( combooffsets[10] && ( dir == DIR_RIGHT || dir == DIR_RIGHTUP || dir == DIR_RIGHTDOWN ) ) return -1; //if the right column
		if ( combooffsets[11] && ( dir == DIR_UP || dir == DIR_RIGHTUP || dir == DIR_LEFTUP || dir == DIR_LEFTUP ) ) return -1; //if the top row
		if ( combooffsets[12] && ( dir == DIR_DOWN || dir == DIR_RIGHTDOWN || dir == DIR_LEFTDOWN ) ) return -1; //if the bottom row
		else if ( cmb >= 0 && cmb < 176 ) 
		{
			int cmbs[2];//needs a for loop to ensure that t returns the most valid combo
			
			for ( cmbs[1] = 0; cmbs[1] < dist; cmbs[1]++ ) 
			{
				cmbs[0] = cmb;
				cmb += (combooffsets[dir]);
				if ( cmb < 0 || cmb > 175 ) return -1;
				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] && ( dir == DIR_LEFT || dir == DIR_LEFTUP || dir == DIR_LEFTDOWN || dir == DIR_LEFTUP ) ) return -1; //if the left columb
				if ( combooffsets[10] && ( dir == DIR_RIGHT || dir == DIR_RIGHTUP || dir == DIR_RIGHTDOWN ) ) return -1; //if the right column
				if ( combooffsets[11] && ( dir == DIR_UP || dir == DIR_RIGHTUP || dir == DIR_LEFTUP || dir == DIR_LEFTUP ) ) return -1; //if the top row
				if ( combooffsets[12] && ( dir == DIR_DOWN || dir == DIR_RIGHTDOWN || dir == DIR_LEFTDOWN ) ) return -1; //if the bottom row
				
			}
			return cmb;
		}
		else return -1;
	}
	
	bool LinkAlign(npc ghost){
		int cmb = ComboAt(CenterX(ghost), CenterY(ghost));
		int linkcmb =  ComboAt(CenterLinkX(),CenterLinkY());
		if (ComboX(cmb)!=ComboX(linkcmb) && ComboY(cmb)!=ComboY(linkcmb)) return false;
		int angle = Angle(Ghost_X+Ghost_TileWidth*8-8,Ghost_Y+Ghost_TileHeight*8-8,CenterLinkX(),CenterLinkY());
		angle=AngleDir4(angle);
		return ghost->Dir == angle;
	}
}