Copy to Clipboard Test

FF Z1 styled Line of Sight and constant traps Code

const int SFX_FF_Z1_TRAP_BOUNCE = 57;//Sound to play, when trap hits unwalkable combo or enemy.
const int SFX_FF_Z1_TRAP_LAUNCH = 17;//Sound to play, when trap detects Link and launches.(NEW!!)

//Z1 line of sight trap. Waits until Link is within it`s line of sight (or limited one, depending on settings) and attacks. It takes time for trap to reset after launch attack.

ffc script FF_Z1_LOS_Trap{
	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 HorizRange = Ghost_GetAttribute(ghost, 0, 0);//Range for horizontal sight.		
		int VertRange = Ghost_GetAttribute(ghost, 1, 0);//Range for vertical sight.	
		int DiagSlashRange = Ghost_GetAttribute(ghost, 2, 0);//Range for "/" diagonal sight.	
		int DiagBackslashRange = Ghost_GetAttribute(ghost, 3, 0);//Range for "\" diagonal sight.	
		int walkflags = Ghost_GetAttribute(ghost, 4, 0);//Add together: 1 - can phase through solid combos, 2- can move across water, 4- can move over pits.
		int RechargeStepSpeedModifier = Ghost_GetAttribute(ghost, 5, 50);//Retraction precentage speed modifier.
		int sizex = Ghost_GetAttribute(ghost, 6, 1);//X Size
		int sizey = Ghost_GetAttribute(ghost, 7, 1);//Y size
		int Proximity = Ghost_GetAttribute(ghost, 8, 8);//Proximity margin.
		int enemycollision = Ghost_GetAttribute(ghost, 9, 0);//>0 - collides with enemies.
		
		ghost->Extend=3;
		Ghost_SetSize(this, ghost, sizex, sizey);
		
		Ghost_SetFlag(GHF_NORMAL);
		Ghost_UnsetFlag(GHF_KNOCKBACK);
		Ghost_SetFlag(GHF_NO_FALL);
		
		int OrigTile = ghost->OriginalTile;
		int State = 0;
		int statecounter = 0;
		int haltcounter = -1;
		
		if ((walkflags&1)>0) Ghost_SetFlag(GHF_IGNORE_SOLIDITY);
		if ((walkflags&2)>0) Ghost_SetFlag(GHF_IGNORE_WATER);
		if ((walkflags&4)>0) Ghost_SetFlag(GHF_IGNORE_PITS);
		int offsetX = 0;
		int offsetY = 0;
		int origx = Ghost_X;
		int origy = Ghost_Y;
		int angle = 0;
		int limit = 0;
		int dist = 0;
		int dir =-1;
		
		int defs[18];
		Ghost_StoreDefenses(ghost,defs);
		
		while(true){
			if (State==0){
				angle = Angle(CenterLinkX(), CenterLinkY(), CenterX(ghost), CenterY(ghost));
				dist = Distance(CenterLinkX(), CenterLinkY(), CenterX(ghost), CenterY(ghost));
				if (VertRange>0){
					if ((Abs (CenterLinkX()-CenterX(ghost))<Proximity) && (Abs (CenterLinkY()-CenterY(ghost))<=HorizRange)){
						Game->PlaySound(SFX_FF_Z1_TRAP_LAUNCH);
						if (CenterLinkY() <= CenterY(ghost)){
							Ghost_Vy = -SPD/100;
							limit= VertRange;
							dir=DIR_UP;
							State=1;
						}
						else{
							Ghost_Vy = SPD/100;
							limit= VertRange;
							dir=DIR_DOWN;
							State=1;
						}
					}
				}
				if (HorizRange>0){
					if ((Abs (CenterLinkY()-CenterY(ghost))<Proximity) && (Abs (CenterLinkX()-CenterX(ghost))<=HorizRange)){
						Game->PlaySound(SFX_FF_Z1_TRAP_LAUNCH);
						if (CenterLinkX() >= CenterX(ghost)){
							Ghost_Vx = SPD/100;
							limit= HorizRange;
							dir=DIR_RIGHT;
							State=1;
						}
						else{
							Ghost_Vx = -SPD/100;
							limit= HorizRange;
							dir=DIR_LEFT;
							State=1;
						}
					}
				}				
				if (DiagSlashRange>0){
					if ((CenterLinkX()-CenterX(ghost)<=-CenterLinkY()+CenterY(ghost)+Proximity)&&(CenterLinkX()-CenterX(ghost)>=-CenterLinkY()+CenterY(ghost)-Proximity)){
						Game->PlaySound(SFX_FF_Z1_TRAP_LAUNCH);
						if (CenterLinkX() <= CenterX(ghost)){
							Ghost_Vx = -SPD/100;
							Ghost_Vy = SPD/100;
							limit= DiagSlashRange;
							dir = DIR_LEFTDOWN;
							State=1;
						}
						else{
							Ghost_Vx = SPD/100;
							Ghost_Vy = -SPD/100;
							limit= DiagSlashRange;
							dir = DIR_RIGHTUP;
							State=1;
						}
					}
				}
				if (DiagBackslashRange>0){
					if ((CenterLinkX()-CenterX(ghost)<=CenterLinkY()-CenterY(ghost)+Proximity)&&(CenterLinkX()-CenterX(ghost)>=CenterLinkY()-CenterY(ghost)-Proximity)){
						Game->PlaySound(SFX_FF_Z1_TRAP_LAUNCH);
						if (CenterLinkX() >= CenterX(ghost)){
							Ghost_Vx = SPD/100;
							Ghost_Vy = SPD/100;
							limit= DiagBackslashRange;
							dir = DIR_RIGHTDOWN;
							State=1;
						}
						else{
							Ghost_Vx = -SPD/100;
							Ghost_Vy = -SPD/100;
							limit= DiagBackslashRange;
							dir = DIR_LEFTUP;
							State=1;
						}
					}
				}
			}
			if (State==1){
				offsetX +=Abs(Ghost_Vx);
				offsetY +=Abs(Ghost_Vy);
				if ((offsetX >=limit) || (offsetY>= limit)){
					Ghost_Vx*=(-RechargeStepSpeedModifier/100);
					Ghost_Vy*=(-RechargeStepSpeedModifier/100);
					State=2;
				}
				if (!Ghost_CanMove(dir, 1, 1)){
					Game->PlaySound(SFX_FF_Z1_TRAP_BOUNCE);
					Ghost_Vx*=(-RechargeStepSpeedModifier/100);
					Ghost_Vy*=(-RechargeStepSpeedModifier/100);
					Ghost_SetFlag(GHF_IGNORE_ALL_TERRAIN);
					State=2;
				}
				for (int i=1;i<=Screen->NumNPCs();i++){
					if (enemycollision==0)break;
					npc n = Screen->LoadNPC(i);
					if (n==ghost)continue;
					if (Collision(n,ghost)){
						Game->PlaySound(SFX_FF_Z1_TRAP_BOUNCE);
						Ghost_Vx*=(-RechargeStepSpeedModifier/100);
						Ghost_Vy*=(-RechargeStepSpeedModifier/100);
						State=2;
					}
				}
			}
			if (State==2){
				if (Ghost_Vx!=0)offsetX -=Abs(Ghost_Vx);
				if (Ghost_Vy!=0)offsetY -=Abs(Ghost_Vy);
				if (offsetX<=0 && offsetY<=0){
					Ghost_X=origx;
					Ghost_UnsetFlag(GHF_IGNORE_ALL_TERRAIN);
					if ((walkflags&1)>0) Ghost_SetFlag(GHF_IGNORE_SOLIDITY);
					if ((walkflags&2)>0) Ghost_SetFlag(GHF_IGNORE_WATER);
					if ((walkflags&4)>0) Ghost_SetFlag(GHF_IGNORE_PITS);
					Ghost_Y=origy;
					Ghost_Vx=0;
					Ghost_Vy=0;
					offsetX=0;
					offsetY=0;
					dir=-1;
					State=0;
				}
			}
			Ghost_Waitframe(this, ghost);
		}
	}
}

//Moves back and forth, turning 180 degrees on collision with obstacles and enemies.
ffc script FF_Constant_Trap{
	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 Dir = Ghost_GetAttribute(ghost, 0, 0);//Starting direction (0-7).		
		int sizex = Ghost_GetAttribute(ghost, 1, 1);//X Size
		int sizey = Ghost_GetAttribute(ghost, 2, 1);//Y size	
		int walkflags = Ghost_GetAttribute(ghost, 3, 0);//Add together: 1 - can phase through solid combos, 2- can move across water, 4- can move over pits.
		int enemycollision = Ghost_GetAttribute(ghost, 4, 0);//>0 - collides with enemies.
		
		ghost->Extend=3;
		Ghost_SetSize(this, ghost, sizex, sizey);
		
		Ghost_SetFlag(GHF_NORMAL);
		Ghost_UnsetFlag(GHF_KNOCKBACK);
		Ghost_SetFlag(GHF_NO_FALL);
		
		int OrigTile = ghost->OriginalTile;
		int State = 0;
		int statecounter = 0;
		int haltcounter = -1;
		
		if ((walkflags&1)>0) Ghost_SetFlag(GHF_IGNORE_SOLIDITY);
		if ((walkflags&2)>0) Ghost_SetFlag(GHF_IGNORE_WATER);
		if ((walkflags&4)>0) Ghost_SetFlag(GHF_IGNORE_PITS);
		int defs[18];
		Ghost_StoreDefenses(ghost,defs);
		
		while(true){
			Ghost_Move(Dir,SPD/100, 1);
			if (!Ghost_CanMove(Dir, SPD/100, 1)){
				Game->PlaySound(SFX_FF_Z1_TRAP_BOUNCE);
				Dir = OppositeDir(Dir);
			}
			for (int i=1;i<=Screen->NumNPCs();i++){
				if (enemycollision==0)break;
				npc n = Screen->LoadNPC(i);
				if (n==ghost)continue;
				if (Collision(n,ghost)){
					Game->PlaySound(SFX_FF_Z1_TRAP_BOUNCE);
					Dir = OppositeDir(Dir);
				}
			}
			Ghost_Waitframe(this, ghost);
		}
	}
}

const int SFX_CCIRCULUM_TRAP_BOUNCE = 57;//Sound to play, when trap hits unwalkable combo or enemy.
const int SFX_CCIRCULUM_TRAP_LAUNCH = 17;//Sound to play, when trap detects Link and launches.(NEW!!)

//Circulum Line of Sight Trap. Waits until Link is inside his line of sight - arc of specific radius, length and width - and attacks by moving in circular pattern. AFter hitting it`s limits, unwalkable combo or enemy, it returns to original position, again moving in circle.

ffc script Circulum_LOS_Trap{
	void run(int enemyID){
		npc ghost = Ghost_InitAutoGhost(this, enemyID);
		int SPD = ghost->Step;
		
		int Radius = Ghost_GetAttribute(ghost, 0, 48);//Circle radius.
		int angle = Ghost_GetAttribute(ghost, 1, 0)+360;//Starting angle.
		int anglerange = Ghost_GetAttribute(ghost, 2, 180);//Proximity arc length.
		int CCW = Ghost_GetAttribute(ghost, 3, 0);//0 - clockwise movement, 1- anti-clockwise movement, 2 - depending on Link`s positon, chosing shortest circular route.
		int walkflags = Ghost_GetAttribute(ghost, 4, 0);//Add together: 1 - can phase through solid combos, 2- can move across water, 4- can move over pits.
		int RechargeStepSpeedModifier = Ghost_GetAttribute(ghost, 5, 50);//Retraction precentage speed modifier.
		int sizex = Ghost_GetAttribute(ghost, 6, 1);//X Size
		int sizey = Ghost_GetAttribute(ghost, 7, 1);//Y size
		int Proximity = Ghost_GetAttribute(ghost, 8, 8);//Proximity margin.
		int enemycollision = Ghost_GetAttribute(ghost, 9, 0);//>0 - collides with enemies.
		
		ghost->Extend=3;
		Ghost_SetSize(this, ghost, sizex, sizey);
		
		Ghost_SetFlag(GHF_NORMAL);
		Ghost_UnsetFlag(GHF_KNOCKBACK);
		Ghost_SetFlag(GHF_NO_FALL);
		
		int OrigTile = ghost->OriginalTile;
		int State = 0;
		int statecounter = 0;
		int haltcounter = -1;
		int anglebound = 0;
		
		
		if ((walkflags&1)>0) Ghost_SetFlag(GHF_IGNORE_SOLIDITY);
		if ((walkflags&2)>0) Ghost_SetFlag(GHF_IGNORE_WATER);
		if ((walkflags&4)>0) Ghost_SetFlag(GHF_IGNORE_PITS);
		
		int angleoffset = 0;
		int linkangle = 0;
		int limit = 0;
		int anglespeed = 0;
		int dist=0;
		int startangle=angle;
		int origX = Ghost_X;
		int origY = Ghost_Y;
		Ghost_X = Ghost_X+Radius*Cos(angle);
		Ghost_Y = Ghost_Y+Radius*Sin(angle);
		int CollX = 0;
		int CollY = 0;
		int leftangle = angle;
		int rightangle = angle;
		if (CCW==0||CCW==2)leftangle=angle-anglerange;
		if (CCW==1||CCW==2)rightangle=angle-anglerange;
		
		
		int defs[18];
		Ghost_StoreDefenses(ghost,defs);
		
		while(true){
			if (State==0){
				linkangle = Angle(CenterLinkX(), CenterLinkY(), origX+Ghost_TileWidth*8, origY+Ghost_TileHeight*8)+540;
				dist = Distance(CenterLinkX(), CenterLinkY(), origX+Ghost_TileWidth*8, origY+Ghost_TileHeight*8);
				if ((dist>=(Radius-Proximity)) && (dist<=(Radius+Proximity))){
					if ((Abs(linkangle-angle))<=anglerange){
						Game->PlaySound(SFX_CCIRCULUM_TRAP_LAUNCH);
						if (CCW==2){
							if (linkangle>angle) anglespeed = SPD/100;
							else anglespeed = -SPD/100;
						}
						else anglespeed = Cond(CCW>0,-SPD/100, SPD/100);
						State=1;
					}
				}
			}
			if (State==1){
				angleoffset += Abs(anglespeed);
				angle+=anglespeed;
				Ghost_X = origX+Radius*Cos(angle);
				Ghost_Y = origY+Radius*Sin(angle);
				if (angleoffset>=anglerange){
					anglespeed*=(-RechargeStepSpeedModifier/100);
					while(angleoffset>360)angleoffset-=360;
					State=2;
				}
				if (anglespeed<0){
					CollX = CenterX(ghost)+sizex*8*Cos(angle-90);
					CollY = CenterY(ghost)+sizey*8*Sin(angle-90);
				}
				else{
					CollX = CenterX(ghost)+sizex*8*Cos(angle+90);
					CollY = CenterY(ghost)+sizey*8*Sin(angle+90);
				}
				if (!Ghost_CanMovePixel(CollX, CollY)){
					Game->PlaySound(SFX_CCIRCULUM_TRAP_BOUNCE);
					while(angleoffset>360)angleoffset-=360;
					anglespeed*=(-RechargeStepSpeedModifier/100);
					State=2;
				}
				for (int i=1;i<=Screen->NumNPCs();i++){
					if (enemycollision==0)break;
					npc n = Screen->LoadNPC(i);
					if (n==ghost)continue;
					dist = Distance(CenterX(ghost), CenterY(ghost), CenterX(n), CenterY(n));
					if (dist<=Min(sizex,sizey)+Min(n->TileWidth, n->TileHeight)){
						Game->PlaySound(SFX_CCIRCULUM_TRAP_BOUNCE);
						while(angleoffset>360)angleoffset-=360;
						anglespeed*=(-RechargeStepSpeedModifier/100);
						State=2;
					}
				}
			}
			if (State==2){
				angleoffset -= Abs(anglespeed);
				angle+=anglespeed;
				Ghost_X = origX+Radius*Cos(angle);
				Ghost_Y = origY+Radius*Sin(angle);
				if (angleoffset<=0){
					angle = startangle;
					angleoffset=0;
					Ghost_X = origX+Radius*Cos(angle);
					Ghost_Y = origY+Radius*Sin(angle);
					State=0;
				}
			}
			Ghost_Waitframe(this, ghost);
		}
	}
}

//Moves in circles, turning 180 degrees on collision with obstacles and enemies.
ffc script Circulum_Constant_Trap{
	void run(int enemyID){
		npc ghost = Ghost_InitAutoGhost(this, enemyID);
		
		int SPD = ghost->Step;
		
		int Radius = Ghost_GetAttribute(ghost, 0, 48);//Circle radius.
		int angle = Ghost_GetAttribute(ghost, 1, 0);	//Starting angle.
		int CCW = Ghost_GetAttribute(ghost, 2, 0);//0 - clockwise movement, 1- anti-clockwise movement, 2 - depending on Link`s positon, chosing shortest circular route.
		int sizex = Ghost_GetAttribute(ghost, 3, 1);//X Size
		int sizey = Ghost_GetAttribute(ghost, 4, 1);//Y size	
		int walkflags = Ghost_GetAttribute(ghost, 5, 0);//Add together: 1 - can phase through solid combos, 2- can move across water, 4- can move over pits.
		int enemycollision = Ghost_GetAttribute(ghost, 6, 0);//>0 - collides with enemies.
		
		ghost->Extend=3;
		Ghost_SetSize(this, ghost, sizex, sizey);
		
		Ghost_SetFlag(GHF_NORMAL);
		Ghost_UnsetFlag(GHF_KNOCKBACK);
		Ghost_SetFlag(GHF_NO_FALL);
		
		int OrigTile = ghost->OriginalTile;
		int State = 0;
		int statecounter = 0;
		int haltcounter = -1;
		
		if ((walkflags&1)>0) Ghost_SetFlag(GHF_IGNORE_SOLIDITY);
		if ((walkflags&2)>0) Ghost_SetFlag(GHF_IGNORE_WATER);
		if ((walkflags&4)>0) Ghost_SetFlag(GHF_IGNORE_PITS);
		int defs[18];
		Ghost_StoreDefenses(ghost,defs);
		
		int anglespeed = SPD/100;
		int startangle=angle;
		int origX = Ghost_X;
		int origY = Ghost_Y;
		Ghost_X = Ghost_X+Radius*Cos(angle);
		Ghost_Y = Ghost_Y+Radius*Sin(angle);
		int CollX = 0;
		int CollY = 0;
		if (CCW)anglespeed*=-1;
		int dist=0;
		
		while(true){
			angle+=anglespeed;
			Ghost_X = origX+Radius*Cos(angle);
			Ghost_Y = origY+Radius*Sin(angle);
			if (anglespeed<0){
				CollX = CenterX(ghost)+sizex*8*Cos(angle-90);
				CollY = CenterY(ghost)+sizey*8*Sin(angle-90);
			}
			else{
				CollX = CenterX(ghost)+sizex*8*Cos(angle+90);
				CollY = CenterY(ghost)+sizey*8*Sin(angle+90);
			}
			if (!Ghost_CanMovePixel(CollX, CollY)){
				Game->PlaySound(SFX_CCIRCULUM_TRAP_BOUNCE);
				anglespeed*=-1;
			}
			for (int i=1;i<=Screen->NumNPCs();i++){
				if (enemycollision==0)break;
				npc n = Screen->LoadNPC(i);
				if (n==ghost)continue;
				dist = Distance(CenterX(ghost), CenterY(ghost), CenterX(n), CenterY(n));
				if (dist<=Min(sizex,sizey)+Min(n->TileWidth, n->TileHeight)){
					Game->PlaySound(SFX_CCIRCULUM_TRAP_BOUNCE);
					anglespeed*=-1;
				}
			}
			if (angle>360)angle-=360;
			if (angle<0) angle+=360;
			Ghost_Waitframe(this, ghost);
		}
	}
}