Copy to Clipboard Test

Fixed Positions Wizzrobe Code

const int POS_WIZZROBE_STATE_TELEPORTING_IN = 1;

const int POS_WIZZROBE_STATE_TELEPORTING_OUT = 4;

const int POS_WIZZROBE_STATE_CHARGING = 2;

const int POS_WIZZROBE_STATE_FIRED = 3;

const int POS_WIZZROBE_STATE_NOT_IN_PLANE = 0;



const int SFX_ENEMY_HEAL = 25;//Sound to play, when Wizzrobe`s healing spell hits enemy for healing.

const int SFX_BLACKHOLE_POS_WIZZROBE=13;//Sound to play, when Wizrobe activates black-hole-like suction.

const int SFX_BLACKHOLE_POS_WIZZROBE_LOOP_DELAY = 20;//Delay between loop sound plays during bloack-hole - like suction.



const int SPR_POS_WIZZROBE_ENEMY_HEAL = 96;//Ssprite to display, when Wizzrobe`s healing spell hits enemy for healing.



const int POS_WIZZROBE_MAX_REROLL_COUNT = 64;//Maximum position reroll count. If exceeded Wizzrobe spawn at random position, ignoring minimum distance to Link.



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



const int POS_WIZZROBE_INTRO_DURATION = 90;



//Fix Position teleporting Wizzrobe. Unlike original Wizzrobe, this variant uses up to 10 predetermined positions, picked at random, for defining spawning positions.

// Use enemy placement flags (##37-46) to define possible spawning positions.

//!\ REQUIRES LinkMovement.zh !!



global script FFWizzrobeActive{

	void run(){

		StartGhostZH();

		Tango_Start();

		__classic_zh_InitScreenUpdating();

	    LinkMovement_Init();

		while(true)	{

			LinkMovement_Update1();

			UpdateGhostZH1();

			__classic_zh_UpdateScreenChange1();

			Tango_Update1();

			__classic_zh_do_z2_lantern();

			if ( __classic_zc_internal[__classic_zh_SCREENCHANGED] )

			{

				__classic_zh_CompassBeep();

				__classic_zh_ResetScreenChange();

			}

			Waitdraw();

			LinkMovement_Update2();

			UpdateGhostZH2();

			Tango_Update2();

			Waitframe();

		}

	}

}



ffc script RandPosWizzrobe{

	void run(int enemyID){

		npc ghost = Ghost_InitAutoGhost(this, enemyID);

		

		int MinLinkDistance = 128 - (ghost->Homing)/2;//Minimum distance to Link when teleporting

		int WPND = ghost->WeaponDamage;//Magic damage

		

		int Teledelay = Ghost_GetAttribute(ghost, 0, 120);//Delay between teleporting

		int MagicHealEnemies = Ghost_GetAttribute(ghost, 1, 0);//If magic hits enemy it heals that value

		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, 32);// Weapon fire sound / enemy count		

		int BlackHoleRange = Ghost_GetAttribute(ghost, 5, 0);//Black hole-like suction range, in pixels

		int BlackHoleSpeed = Ghost_GetAttribute(ghost, 6, 0);//Black hole-like suction speed, in 1/100ths of pixel per speed

		int SizeX = Ghost_GetAttribute(ghost, 7, 1);//Enemy Size X

		int SizeY = Ghost_GetAttribute(ghost, 8, 1);//Enemy Size Y

		int IntroCMB = Ghost_GetAttribute(ghost, 9, 0);//comboID drawn during introduction sequence, using enemy`s CSet. 0 for no intro.

		

		ghost->Extend=3;

		Ghost_SetSize(this, ghost, SizeX, SizeY);

		Ghost_SetHitOffsets(ghost, 8, 8, 8, 8);

		

		Ghost_SetFlag(GHF_NORMAL);

		Ghost_SetFlag(GHF_NO_FALL);

		Ghost_UnsetFlag(GHF_KNOCKBACK);

		

		int PosCmb[10];

		int maxoffset = 0;

		for (int i=0;i<10;i++){

			int c = 0;

			while(!ComboFI(c, 37+i)){

				c++;

				if (c>=176)break;

			}

			if (c>=176)continue;

			PosCmb[maxoffset] = c;

			maxoffset++;

			// Trace(OffsetX[i]);

		}

		int curpos=Rand(maxoffset);

		Ghost_X=ComboX(PosCmb[curpos]);

		Ghost_Y=ComboY(PosCmb[curpos]);

		

		int origmidi = Game->GetMIDI();

		int OrigTile = ghost->OriginalTile;

		int State = 0;

		int haltcounter = -1;

		int StateCounter =Teledelay;

		int dir = Ghost_Dir;

		float suckx = Link->X;

		float sucky = Link->Y;

		int soundcounter=SFX_BLACKHOLE_POS_WIZZROBE_LOOP_DELAY;

		if (IntroCMB>0){

			StateCounter+=POS_WIZZROBE_INTRO_DURATION;

			Game->PlayMIDI(0);

		}

		while(true){

			if (State==POS_WIZZROBE_STATE_NOT_IN_PLANE){

				ghost->DrawXOffset = 1000;

				ghost->HitXOffset = 1000;

				if (StateCounter>Teledelay){

					Screen->DrawCombo	(2, Ghost_X, Ghost_Y,IntroCMB,Ghost_TileWidth, Ghost_TileHeight,Ghost_CSet, -1, -1,0,0,0,0,0,true,OP_OPAQUE);

				}

				if (StateCounter == 0){

					if (IntroCMB>0)Game->PlayMIDI(origmidi);

					ghost->DrawXOffset = 0;

					for (int r = 0; r<POS_WIZZROBE_MAX_REROLL_COUNT;r++){

						curpos=Rand(maxoffset);

						Ghost_X=ComboX(PosCmb[curpos]);

						Ghost_Y=ComboY(PosCmb[curpos]);

						if (Distance(CenterX(ghost),CenterY(ghost),CenterLinkX(),CenterLinkY()) <=MinLinkDistance) break;

					}

					State = POS_WIZZROBE_STATE_TELEPORTING_IN;

					StateCounter = 32;

					dir = WizzrobeFaceLink(ghost);

					Ghost_ForceDir(dir);

				}

			}

			if (State==POS_WIZZROBE_STATE_TELEPORTING_IN){

				if(IsOdd(StateCounter))  ghost->DrawXOffset=1000;

				else  ghost->DrawXOffset=0;

				if (StateCounter == 0){

					State = POS_WIZZROBE_STATE_CHARGING;

					ghost->HitXOffset = 0;

					StateCounter = 32;

				}

			}

			if (State==POS_WIZZROBE_STATE_CHARGING){

				if (BlackHoleRange>0){

					soundcounter--;

					if (soundcounter<=0)soundcounter=SFX_BLACKHOLE_POS_WIZZROBE_LOOP_DELAY;			

					float dist = Distance(Ghost_X, Ghost_Y, Link->X, Link->Y);

					if (dist<=BlackHoleRange){

						if (soundcounter==SFX_BLACKHOLE_POS_WIZZROBE_LOOP_DELAY)Game->PlaySound(SFX_BLACKHOLE_POS_WIZZROBE);

						float angle = Angle(this->X, this->Y, Link->X, Link->Y);

						suckx = -BlackHoleSpeed/100*Cos(angle);

						sucky = -BlackHoleSpeed/100*Sin(angle);

						LinkMovement_Push2(suckx, sucky);

						dist = Distance(Ghost_X, Ghost_Y, Link->X, Link->Y);

						// if (dist< (BlackHoleRange/2)&& BlackHoleDrainPower>0){

							// int drawlerp = Randf(1);

							// int drawx = Lerp(Ghost_X, Link->X, drawlerp); 

							// int drawy = Lerp(Ghost_Y, Link->Y, drawlerp);

							// if (BlackHoleCounterTile>0) Screen->FastTile(2, drawx, drawy, BlackHoleCounterTile, ghost->CSet, OP_OPAQUE);

							// if ((StateCounter%POS_WIZZROBE_COUNTER_DRAIN_DELAY)==0){

								// Game->PlaySound(SFX_POS_WIZZROBE_COUNTER_DRAIN);

								// Game->DCounter[BlackHoleCounter] -= BlackHoleDrainPower;

							// }

						// }

					}

				}

				if (StateCounter == 0){

					State = POS_WIZZROBE_STATE_FIRED;

					StateCounter = 32;

					eweapon e;

					if (Wpn == 0){

						e = FireNonAngularEWeapon(ghost->Weapon, Ghost_X, Ghost_Y, ghost->Dir, 300, WPND, EWType,ewSound, EWF_ROTATE);

					}

					if (MagicHealEnemies>0){

						while(e->isValid()){

							for (int i=1; i<=Screen->NumNPCs(); i++){

								npc h = Screen->LoadNPC(i);

								if (h==ghost) continue;

								if (Collision(h,e)){

									h->HP+=MagicHealEnemies;

									Remove(e);

									Game->PlaySound(SFX_ENEMY_HEAL);

									lweapon s = CreateLWeaponAt(LW_SPARKLE, h->X, h->Y);

									s->UseSprite(SPR_POS_WIZZROBE_ENEMY_HEAL);

									s->CollDetection=false; 

								}

							}

							Ghost_Waitframe(this, ghost);

						}

						

					}

					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++){

							eweapon e = FireNonAngularEWeapon(ghost->Weapon, Ghost_X, Ghost_Y, dirs[i], 300, WPND, EWType,0, EWF_ROTATE);

						}

					}

					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], 300, WPND, EWType,0, EWF_ROTATE);

						}

					}

					else if (Wpn == 3){

						Game->PlaySound(SFX_SUMMON);

						for (int i=1; i<=ewSound;i++){

							npc en = CreateNPCAt(Cond(EWType>0,EWType,POS_WIZZROBE_DEFAULT_SUMMON_ID), Ghost_X,Ghost_Y);

						}

					}

					else if (Wpn == 4){

						eweapon 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, 300, WPND, EWType, -1, EWF_ROTATE);

					}

					else if (Wpn == 6){

						e = FireAimedEWeapon(ghost->Weapon, CenterX(ghost)-8, CenterY(ghost)-8, 0, 300, WPND, EWType, -1, EWF_ROTATE);

						e = FireAimedEWeapon(ghost->Weapon, CenterX(ghost)-8, CenterY(ghost)-8, 0.2, 300, WPND, EWType, -1, EWF_ROTATE);

						e = FireAimedEWeapon(ghost->Weapon, CenterX(ghost)-8, CenterY(ghost)-8, -0.2, 300, WPND, EWType, -1, EWF_ROTATE);

					}

				}

			}

			if (State==POS_WIZZROBE_STATE_FIRED){

				if (StateCounter == 0){

					State = POS_WIZZROBE_STATE_TELEPORTING_OUT;

					StateCounter = 32;

				}

			}

			if (State==POS_WIZZROBE_STATE_TELEPORTING_OUT){

				if(IsOdd(StateCounter))  ghost->DrawXOffset=1000;

				else  ghost->DrawXOffset=0;

				if (StateCounter == 0){

					ghost->DrawXOffset = 1000;

					ghost->HitXOffset = 1000;

					State = POS_WIZZROBE_STATE_NOT_IN_PLANE;

					StateCounter = Teledelay;

				}

			}

			StateCounter--;

			Ghost_ForceDir(dir);

			POS_WizzrobeAnimation(ghost, OrigTile, State);

			Ghost_Waitframe(this, ghost);

		}

	}

}



void POS_WizzrobeAnimation(npc ghost, int origtile, int state){

	int offset = 0;

	if (state==POS_WIZZROBE_STATE_CHARGING )offset = 20*ghost->TileHeight;

	if (state==POS_WIZZROBE_STATE_FIRED )offset = 40*ghost->TileHeight;

	ghost->OriginalTile = origtile + offset;

}



int WizzrobeFaceLink(npc ghost){

	int angle = Angle(Ghost_X+Ghost_TileWidth*8-8,Ghost_Y+Ghost_TileHeight*8-8,CenterLinkX(),CenterLinkY());

	return AngleDir4(angle);	

}