Copy to Clipboard Test

Mani's Script Header Code

#include "std.zh"
#include "string.zh"
#include "ffcscript.zh"


namespace Mani
{
    //code here


ffc script Healing_Tile{
	void run(int Type){
		
		bool PlayTheSFX = false;
		
		while(true){
			
			
			if(Link->X <= this->X + 3 && Link->X >= this->X - 3 && Link->Y < this->Y + 3 && Link->Y > this->Y - 3 ){
				
				if(Type == 0 || Type == 2){
					if(Link->HP < Link->MaxHP){
						
						PlayTheSFX = true;
						Link->HP ++;
						
					}
				}
				
				if(Type == 1 || Type == 2){

					if(Link->MP < Link->MaxMP){
						
						PlayTheSFX = true;
						Link->MP ++;
						
					}
					if(Link->MP < Link->MaxMP)Link->MP ++;
					if(Link->MP < Link->MaxMP)Link->MP ++;
					if(Link->MP < Link->MaxMP)Link->MP ++;
				}
					
				
			}
			
			if(PlayTheSFX){
				
				Game->PlaySound(23);
				
				PlayTheSFX = false;
			}
			
			Waitframe();
		}
		
		
		
		
	}
}


// Item secripts //

//Spin attack SFX for the sword
const int MW_SPINATTACK_SFX = 54;

//Spin attack Charge time
const int MW_SWORD_CHARGE = 120;
item script ManiSword{
	void run(int StabType, int Unused2, int Unused3, int S_DMG, int Range, int SFX, int Variable4){
		
		if(!CounterCost(this->CostCounter, this->Cost) && this->Cost > 0) return;
		
		Link->Action = LA_ATTACKING;
		
		Game->PlaySound(SFX);
		
		int DMG = this->Power;
		int Sprite = this->Sprites[0];
		int ItemID = this->ID;
		
		//Check for Stab or Swing based on Input duration
		int AttackType = 0;	// 0 = Default and is Slash. 1 = Stabbing
		if(StabType == 0){
			int Stab = 0;
			while(Link->Dir == DIR_LEFT && Link->InputLeft && Stab < 4
			|| Link->Dir == DIR_RIGHT && Link->InputRight && Stab < 4
			|| Link->Dir == DIR_UP && Link->InputUp && Stab < 4
			|| Link->Dir == DIR_DOWN && Link->InputDown && Stab < 4){
				
				Stab++;
				Waitframe();
			}
			
			if(Stab >= 4) AttackType = 1;	// Stabbing time!
		}
		else if(StabType == 1){
			AttackType = 1;	// Stabbing time!
		}
		else if(StabType == 2){
			AttackType = 0;	// Slash Sword
		}
		
		int BaseImg = 0;
		int BaseCSet = 0;
		int OrgDir = Link->Dir;
		int OrgX = Link->X;
		int OrgY = Link->Y;
		
		lweapon Damage;
		lweapon Sword;
		Sword = Screen->CreateLWeapon(LW_SCRIPT10);
		Sword->UseSprite(Sprite);
		Sword->CollDetection = false;
		Sword->X = Link->X;
		Sword->Y = Link->Y;
		
		
		
		BaseImg = Sword->OriginalTile;
		BaseCSet = Sword->OriginalCSet;
		
		int Sw_Dir = OrgDir;
		
		
		
		
		
		if(AttackType == 1) StabSword(Range * 2 + 2, false, Damage, Sword, Sw_Dir, Range, DMG);
		else{
			SwingSword(2, false, Damage, Sword, Sw_Dir, Range, DMG);
		}
		
		Link->Action = LA_NONE;
		
		
		//cleanup 
		if(Sword->isValid()){
			Sword->DeadState = 0;
			Sword->X = -70000;
			Sword->Y = -70000;
		}
		if(Damage->isValid()){
			Damage->DeadState = 0;
			Damage->X = -70000;
			Damage->Y = -70000;
		}
		
		
		//If the special move damage is set to 0, there is no special move.
		if(S_DMG > 0){
			//This function uses S_DMG for MP cost here, rather than damage value, actually not used at all, lol, needs to be not zero
			
			//Brings the FFC with you:
			//this->Flags[FFCF_CARRYOVER] = true;	//actually waaaaay too cursed to use.
			
			int ChargeUp = 0;
			
			while(((GetEquipmentB() == ItemID) && Link->InputB == true) || ((GetEquipmentA() == ItemID) && Link->InputA == true)
				|| (Link->ItemX == ItemID && Link->InputEx1)
				|| (Link->ItemY == ItemID && Link->InputEx2)){
				
				ChargeUp ++;
				
				//If the special move have any requirements, this is where you put a check for that in order to play the charge complete SFX.
				if(ChargeUp == MW_SWORD_CHARGE){	
					Game->PlaySound(35);
				}
				
				Waitframe();
			}
			
			//this->Flags[FFCF_CARRYOVER] = false;
			
			//This part happens when you have charged long enough and meet the requirements.
			if(ChargeUp >= MW_SWORD_CHARGE){
				
				Game->PlaySound(SFX);
				Link->Action = LA_ATTACKING;
				
				Sword = Screen->CreateLWeapon(LW_SCRIPT10);
				Sword->UseSprite(Sprite);
				Sword->CollDetection = false;
				Sword->X = Link->X;
				Sword->Y = Link->Y;
				
				
				SwingSword(5, true, Damage, Sword, Link->Dir, Range, DMG*2);
				
				Link->Action = LA_NONE;
			}
			
			
			
			
		}
		
		//cleanup 
		if(Sword->isValid()){
			Sword->DeadState = 0;
			Sword->X = -70000;
			Sword->Y = -70000;
		}
		if(Damage->isValid()){
			Damage->DeadState = 0;
			Damage->X = -70000;
			Damage->Y = -70000;
		}
		
		//this->Data = 0;
		//this->X = 0;
		//this->Y = 0;
		
		
	}
	
	void SwingSword(int MakeSwings, bool TurnLink, lweapon Damage, lweapon Sword, int Sw_Dir, int Range, int DMG){
		
		int Swings = 0;
		
		float SwingAngle = 0;
		int SwindDistance = Range;
		int SwingTime = 8;
		
		int Swordtile = Sword->Tile;
		int SwordCSet = Sword->CSet;
		Sword->UseSprite(BLNK_SPRITE);
		
		if(MakeSwings > 2) SwingTime = 6;
		
		while(Swings < MakeSwings){
			
			Link->Action = LA_NONE;
			Link->Action = LA_ATTACKING;
			
			
			
			
			

			for(int i = 0; i < SwingTime; i++){
				
				if(i < 14){
					Link->Action = LA_NONE;
					Link->Action = LA_ATTACKING;
				}
				
				if(Damage->isValid() == false){
					Damage = Screen->CreateLWeapon(LW_SCRIPT10);
					Damage->UseSprite(BLNK_SPRITE);
					Damage->HitWidth = 16;
					Damage->HitHeight = 16;
					Damage->Damage = DMG;
					Damage->Weapon = LW_SWORD;
					Damage->Flags[WFLAG_PICKUP_ITEMS] = true;
					
				}
				
				if(Sw_Dir == DIR_UP){
					SwingAngle = 0; //if(i < SwingTime/2) Damage->Dir = DIR_RIGHT;
				} 
				else if(Sw_Dir == DIR_RIGHT){
					SwingAngle = 90; //if(i < SwingTime/2) Damage->Dir = DIR_DOWN;
				} 
				else if(Sw_Dir == DIR_DOWN){
					SwingAngle = 180; //if(i < SwingTime/2) Damage->Dir = DIR_LEFT;
				} 
				else if(Sw_Dir == DIR_LEFT){
					SwingAngle = 270; //if(i < SwingTime/2) Damage->Dir = DIR_UP;
				} 
				if(TurnLink) Link->Dir = Sw_Dir;
				Damage->Dir = Link->Dir;
				SwingAngle = SwingAngle - (i*(90/SwingTime));
				
				Sword->X = Link->X + VectorX(SwindDistance, SwingAngle);
				Sword->Y = Link->Y + VectorY(SwindDistance, SwingAngle);
				Damage->X = Link->X + VectorX(SwindDistance + 8, SwingAngle);
				Damage->Y = Link->Y + VectorY(SwindDistance + 8, SwingAngle);
				//Screen->PutPixel(6, Sword->X, Sword->Y, 0x44, 0, 0, 0, OP_OPAQUE);
				
				if(Sword->X != 0 && Sword->Y != 0) Screen->DrawTile(2, Sword->X - 8, Sword->Y, Swordtile, 2, 1, SwordCSet, -1, -1, Sword->X - 8, Sword->Y, SwingAngle, 0, true, OP_OPAQUE);
				
				//	ManiCollectItem(Damage);
				
				Waitframe();
			}
			
			Swings++;
			if(Sw_Dir == DIR_UP) Sw_Dir = DIR_LEFT;
			else if(Sw_Dir == DIR_RIGHT) Sw_Dir = DIR_UP;
			else if(Sw_Dir == DIR_DOWN) Sw_Dir = DIR_RIGHT;
			else if(Sw_Dir == DIR_LEFT) Sw_Dir = DIR_DOWN;
		

			if(Damage->isValid()){
				Damage->DeadState = 0;
				//Damage->X = -20000;
				//Damage->Y = -20000;
			}
		}
	}
	
	
	void StabSword(int StabTime, bool TurnLink, lweapon Damage, lweapon Sword, int Sw_Dir, int Range, int DMG){
		
		float SwingAngle = 0;
		int SwingDistance = -2;
		
		int Swordtile = Sword->Tile;
		int SwordCSet = Sword->CSet;
		Sword->UseSprite(BLNK_SPRITE);
		
		
	
		
		Link->Action = LA_NONE;
		Link->Action = LA_ATTACKING;
		
		
		
		
		

		for(int i = 0; i < StabTime; i++){
			
			if(i < 14){
				Link->Action = LA_NONE;
				Link->Action = LA_ATTACKING;
			}
			
			if(Damage->isValid() == false){
				Damage = Screen->CreateLWeapon(LW_SCRIPT10);
				Damage->UseSprite(BLNK_SPRITE);
				Damage->HitWidth = 16;
				Damage->HitHeight = 16;
				Damage->Damage = DMG;
				Damage->Weapon = LW_SWORD;
				Damage->Flags[WFLAG_PICKUP_ITEMS] = true;
				
			}
			
			if(i + (Range/2) + 2 >= StabTime) SwingDistance = SwingDistance - 2;
			else if(SwingDistance < Range){
				SwingDistance = SwingDistance + 2;
				if(SwingDistance > Range) SwingDistance = Range;
			}
			
			if(Sw_Dir == DIR_UP){
				SwingAngle = 270; //if(i < SwingTime/2) Damage->Dir = DIR_RIGHT;
			} 
			else if(Sw_Dir == DIR_RIGHT){
				SwingAngle = 0; //if(i < SwingTime/2) Damage->Dir = DIR_DOWN;
			} 
			else if(Sw_Dir == DIR_DOWN){
				SwingAngle = 90; //if(i < SwingTime/2) Damage->Dir = DIR_LEFT;
			} 
			else if(Sw_Dir == DIR_LEFT){
				SwingAngle = 180; //if(i < SwingTime/2) Damage->Dir = DIR_UP;
			} 
			if(TurnLink) Link->Dir = Sw_Dir;
			Damage->Dir = Link->Dir;
			
			Sword->X = Link->X + VectorX(SwingDistance, SwingAngle);
			Sword->Y = Link->Y + VectorY(SwingDistance, SwingAngle);
			Damage->X = Link->X + VectorX(SwingDistance + 8, SwingAngle);
			Damage->Y = Link->Y + VectorY(SwingDistance + 8, SwingAngle);
			//Screen->PutPixel(6, Sword->X, Sword->Y, 0x44, 0, 0, 0, OP_OPAQUE);
			
			if(Sword->X != 0 && Sword->Y != 0) Screen->DrawTile(2, Sword->X - 8, Sword->Y, Swordtile, 2, 1, SwordCSet, -1, -1, Sword->X - 8, Sword->Y, SwingAngle, 0, true, OP_OPAQUE);
			
			//	ManiCollectItem(Damage);
			
			Waitframe();
		}
		
		if(Sw_Dir == DIR_UP) Sw_Dir = DIR_LEFT;
		else if(Sw_Dir == DIR_RIGHT) Sw_Dir = DIR_UP;
		else if(Sw_Dir == DIR_DOWN) Sw_Dir = DIR_RIGHT;
		else if(Sw_Dir == DIR_LEFT) Sw_Dir = DIR_DOWN;
	

		if(Damage->isValid()){
			Damage->DeadState = 0;
			//Damage->X = -20000;
			//Damage->Y = -20000;
		}
		
	}
		
}



// FFC Scripts	//--------------------------------------//


ffc script TriggerOrb{	// Trigger orbs, hit all on screen on the same time to trigger secrets.
	void run(int WeaponType, int Checker){
		
		int OriginalTile = this->Data;
		lweapon ValidWeapon;
		
		
		int ThisNumb = FFCNum(this);
		
		
		int FFCs[35];
		ffc CheckFFC;
		int TotalFFCs = 0;
		
		//If checker then make array
		if(Checker > 0){
			for(int i = 0; i < 35; i++){
				FFCs[i] = -1;
			}
			
			int ArraySpot = 0;
			
			for(int i=1; i<=32; i++){
				CheckFFC = Screen->LoadFFC(i);
				
				if(CheckFFC->Script == this->Script){
					FFCs[ArraySpot] = FFCNum(CheckFFC);
					ArraySpot ++;
				}
			}
			
			TotalFFCs = ArraySpot;
			
		}
		
		
		
		while(Screen->State[ST_SECRET] == false){
			
			//Check to see if self is hit
			for(int i = 1; i <= Screen->NumLWeapons(); i++){
				
				ValidWeapon = Screen->LoadLWeapon(i);
				
				if(ValidWeapon->Weapon > 0 && ValidWeapon->Weapon == WeaponType && Collision(this, ValidWeapon)) this->Misc[8] = 2;
				else if(ValidWeapon->ID == WeaponType && Collision(this, ValidWeapon)) this->Misc[8] = 2;
				
			}
			
			
			//If checker then check all orbs and trigger secret
			if(Checker > 0){
				int ArraySpot = 0;
				int ActiveOrbs = 0;
				
				for(int i = 0; FFCs[i] != -1; i++){
					
					if(FFCs[i] > -1){
						CheckFFC = Screen->LoadFFC(FFCs[i]);
						if(CheckFFC->Misc[8] > 0) ActiveOrbs ++;
					}
					
					
					if(ActiveOrbs == TotalFFCs){
						Screen->TriggerSecrets();
						Screen->State[ST_SECRET] = true;
						Game->PlaySound(27);
					} 
					
				}
				
				
				//Screen->DrawInteger(6, this->X +8, this->Y - 24,  0, 0x0F, -1,  -1, -1, TotalFFCs, 0, OP_OPAQUE);
				
				//Screen->DrawInteger(6, this->X +8 , this->Y - 16,  0, 0x0F, -1,  -1, -1, ActiveOrbs, 0, OP_OPAQUE);
				
			}
			
			
			
			//Visuals of switch and hit frames decreasing
			if(this->Misc[8] > 0) this->Data = OriginalTile + 1;
			else if(this->Data != OriginalTile) this->Data = OriginalTile;
			
			if(this->Misc[8] > 0) this->Misc[8] --;
			
			
			Waitframe();
			
		}
		
		
		
		
		
		
		
		
		//Setting tile when ending script
		this->Data = OriginalTile + 2;
		
	}
}

ffc script SecretActivater{	// Triggers secrets when run.
	void run(){
		
		SecretTrigger(9);
	}
}

ffc script ItemCheckSecret{	// Secret trigger if Hero has a variable number of items (from 1 to 7)
	void run(int D0, int D1, int D2, int D3, int D4, int D5, int D6, int SFX){
		
		while(Screen->State[ST_SECRET] == false){
		
			if(D1 == 0) D1 = D0;
			if(D2 == 0) D2 = D0;
			if(D3 == 0) D3 = D0;
			if(D4 == 0) D4 = D0;
			if(D5 == 0) D5 = D0;
			if(D6 == 0) D6 = D0;
			if(SFX == 0) SFX = 27;
		
		
		
			if((Link->Item[D0] == true) && (Link->Item[D1] == true) && (Link->Item[D2] == true) && (Link->Item[D3] == true) && (Link->Item[D4] == true) && (Link->Item[D5] == true) && (Link->Item[D6] == true)){
			
				Waitframes(60);
				Game->PlaySound(SFX);
				Screen->TriggerSecrets();
				Screen->State[ST_SECRET] = true;
				
			
			}
		
		Waitframe();
		}
		
	}
}

	
ffc script TenRupeeRoom{	// Oracles style rupee room (very cursed) requires four identical looking rupee items.
	void run(int LowChance, int MidChamce, int HighChance, int BigRupeeID, int Medium, int Small, int OneRupee){
		
		if(Screen->State[ST_ITEM]) return;
		
		int Placed = 1;
		int CreateID = 0;
		item Rupee;
		int X = 16 * 5;
		int Y = 16 * 3;
		int Offset = 0;
		
		
		
		while(Placed <= 34){
			
			// these used: SeedRand() before instead of Rand
			
			if(HighChance != 0 && Rand(HighChance) == 1) CreateID = BigRupeeID;
			else if(MidChamce != 0 && Rand(MidChamce) == 1) CreateID = Medium;
			else if(LowChance != 0 && Rand(LowChance) == 1) CreateID = Small;
			else{
				CreateID = OneRupee;
			}
			
			Rupee = Screen->CreateItem(CreateID);
			Rupee->X = X;
			Rupee->Y = Y;
			Rupee->Pickup = IP_ST_ITEM;
			
			
			X = X + 16;
			if(Placed == 6){
				X = 16*5 - 8;
				Y = Y + 16;
			}
			else if(Placed == 13){
				X = 16*4;
				Y = Y + 16;
			}
			else if(Placed == 21){
				X = 16*5 - 8;
				Y = Y + 16;
			}
			else if(Placed == 28){
				X = 16*5;
				Y = Y + 16;
			}
			
			
			Placed ++;
			
			// Waitframe();
		}
		
		
		return;
		
	}
}


ffc script TransitionFade{	// Fades the screen after a delay, then warps Hero.
	void run(int Timer, int Dmap, int Screen, int Colour, int Speed){
		
		
		while(Timer > 0){
			
			Timer --;
			Waitframe();
		}
		
		for(int i = 0; i < 5; i++){
			
			
			for(int i2 = 0; i < Speed; i++){
				
				FastRectangle(6, 0, -98, 16*17, 16*16, Colour, OP_TRANS);
				if(i >= 1) FastRectangle(6, 0, -98, 16*17, 16*16, Colour, OP_TRANS);
				if(i >= 2) FastRectangle(6, 0, -98, 16*17, 16*16, Colour, OP_TRANS);
				if(i >= 3) FastRectangle(6, 0, -98, 16*17, 16*16, Colour, OP_OPAQUE);
				
				NoActionFull();
				Waitframe();
				
			}
		
		}
		
		Link->Warp(Dmap, Screen);
		
	}
}



// Utility Secripts	//--------------------------------------//
item script Give_MultItem_AND_String{	// Run on pickup to play a string and give more items, a bit obsoloete.
	void run(int PlayString, int Item1, int Item2, int Item3){
		
		Screen->Message(PlayString);
		
		if(Item1 != 0){
			Link->Item[Item1] = true;
		}
		
		if(Item2 != 0){
			Link->Item[Item2] = true;
		}
		
		if(Item3 != 0){
			Link->Item[Item3] = true;
		}
		
	}

}


item script GiveItemS{	//Gives inventory items on all D0-D7 slots. Considering limited item IDs in ZC, this is better than bundel.
	void run(int D0, int D1, int D2, int D3, int D4, int D5, int D6, int D7){
		
		
		if(!Link->Item[D0] && D0 > 0) Link->Item[D0] = true;
		if(!Link->Item[D1] && D0 > 0) Link->Item[D1] = true;
		if(!Link->Item[D2] && D0 > 0) Link->Item[D2] = true;
		if(!Link->Item[D3] && D0 > 0) Link->Item[D3] = true;
		if(!Link->Item[D4] && D0 > 0) Link->Item[D4] = true;
		if(!Link->Item[D5] && D0 > 0) Link->Item[D5] = true;
		if(!Link->Item[D6] && D0 > 0) Link->Item[D6] = true;
		if(!Link->Item[D7] && D0 > 0) Link->Item[D7] = true;
		
	}
}



// Utility Functions	//--------------------------------------//

int FrameCount;	// see function below
void FrameCounter(){	// a simple frame counter for the global scope
	FrameCount += 1;
	
	if(FrameCount >= 60){
		FrameCount = 0;

	}
	
}


void NoActFullWaitframe(){
	
	NoActionFull();
	
	Waitframe();
	
}

void NoActionFull(){
	
	Link->InputUp = false; Link->PressUp = false;
	Link->InputDown = false; Link->PressDown = false;
	Link->InputLeft = false; Link->PressLeft = false;
	Link->InputRight = false; Link->PressRight = false;
	
	Link->InputStart = false; Link->PressStart = false;
	Link->InputMap = false; Link->PressMap = false;

	Link->InputR = false; Link->PressR = false;
	Link->InputL = false; Link->PressL = false;
	Link->InputA = false; Link->PressA = false;
	Link->InputB = false; Link->PressB = false;
	
	Link->InputEx1 = false; Link->PressEx1 = false;
	Link->InputEx2 = false; Link->PressEx2 = false;
	Link->InputEx3 = false; Link->PressEx3 = false;
	Link->InputEx4 = false; Link->PressEx4 = false;
	
	Link->InputAxisUp = false; Link->PressAxisUp = false;
	Link->InputAxisDown = false; Link->PressAxisDown = false;
	Link->InputAxisLeft = false; Link->PressAxisLeft = false;
	Link->InputAxisRight = false; Link->PressAxisRight = false;
	
}


void FasterRupeeDrain(){	// Empties the rupee drain counter faster; Should run every frame from the global scope.
	if(Game->DCounter[CR_RUPEES]<-50){
		Game->DCounter[CR_RUPEES] = Min(0, Game->DCounter[CR_RUPEES]+9);
		Game->Counter[CR_RUPEES] = Max(0, Game->Counter[CR_RUPEES]-9);
	}
}

void FasterCounterDrain(){	// Same as above but for all counters
	
	for(int i = 0; i < 30; i++){
		if(Game->DCounter[i]<-50){
			Game->DCounter[i] = Min(0, Game->DCounter[i]+9);
			Game->Counter[i] = Max(0, Game->Counter[i]-9);
		}
	}
}

void SecretTrigger(int SFX){	// Triggers the screen secret when run.
	Game->PlaySound(SFX);
	Screen->TriggerSecrets();
}


void FastInt(int Layer, int X, int Y, int font, int Colour, int Numb){
	
	Screen->DrawInteger(Layer, X, Y, font, Colour, -1, -1, -1, Numb, 0, OP_OPAQUE);
	
}
void FasterInt(int Layer, int X, int Y, int Numb){
	
	Screen->DrawInteger(Layer, X, Y, FONT_S2, 0x0E, 0x0F, -1, -1, Numb, 0, OP_OPAQUE);
	
}


void FastRectangle(int layer, int x, int y, int x2, int y2, int color, int opacity){
	
	Screen->Rectangle(layer, x, y, x2, y2, color, 1, 0, 0, 0, true, opacity);
	
}


bool isSolid_Water(int x, int y){
	
	if(Screen->ComboT[ComboAt(x, y)] == CT_WATER) return false;
	else{
		if(Screen->isSolid(x, y)) return true;
	}
	
}


bool RestrictUseScrnEdg(){
	if(Hero->Dir == DIR_LEFT && Hero->X < 16) return true;
	else if(Hero->Dir == DIR_RIGHT && Hero->X > 16*14) return true;
	else if(Hero->Dir == DIR_UP && Hero->Y < 16) return true;
	else if(Hero->Dir == DIR_DOWN && Hero->Y > 16*9) return true;
	else{
		return false;
	}
}


bool ChckItmButtonInput(int ItemID){
	if(Hero->ItemA == ItemID && Input->Press[CB_A]) return true;
	else if(Hero->ItemB == ItemID && Input->Press[CB_B]) return true;
	else if(Hero->ItemX == ItemID && Input->Press[CB_X]) return true;
	else if(Hero->ItemY == ItemID && Input->Press[CB_Y]) return true;
	else{
		return false;
	}
}










}	// END OF NAMESPACE