Copy to Clipboard Test

Face Shifter Code

//Cycling Shapeshifter

//Moves in 4 directions. Vulnerable only during specific frame of animation.
//E.Anim - None, 2-frame, 3-frame or 4-frame, one row every 4 states.

ffc script FaceShifter{
	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 delay = Ghost_GetAttribute(ghost, 0, 60);//Delay between changing frames.
		int numstates = Ghost_GetAttribute(ghost, 1, 4);//Number of frames in animation
		int sizex = Ghost_GetAttribute(ghost, 2, 1);//Tile Width
		int sizey = Ghost_GetAttribute(ghost, 3, 1);//Tile Height
		int targetstate = Ghost_GetAttribute(ghost, 4, 0);//Target frame.
		int numframes = Ghost_GetAttribute(ghost, 5, 2);//number of frames per step.
		int dirshift = Ghost_GetAttribute(ghost, 6, 0);//>0 - switch face every time enemy turns, ignoring timing.
		int faceswitchanim = Ghost_GetAttribute(ghost, 7, 0);//>0 - use animation when switching faces, uses the same stup right below original animation
		
		ghost->Extend=3;
		Ghost_SetSize(this, ghost, sizex, sizey);
		if (sizex>2 && sizey>2)Ghost_SetHitOffsets(ghost, 8, 8, 8, 8);
		
		Ghost_SetFlag(GHF_NORMAL);
		
		int OrigTile = ghost->OriginalTile;
		int State = 0;
		int haltcounter = -1;
		int pos =0;
		int statecounter=delay;
		int olddir = Ghost_Dir;
		int faceanim=0;
		
		int defs[18];
		Ghost_StoreDefenses(ghost,defs);
		if (pos!=targetstate)Ghost_SetAllDefenses(ghost, NPCDT_BLOCK);
		
		
		while(true){
			if (State==0){
				if (statecounter>45 || faceswitchanim==0)haltcounter = Ghost_ConstantWalk4(haltcounter, SPD, RR, HF, HNG);
				if (faceanim>0 || dirshift==0)statecounter--;
				if (statecounter<=45){
					faceanim=1;
				}
				if (statecounter==0){
					pos++;
					if (pos>=numstates)pos=0;						
					if (pos!=targetstate)Ghost_SetAllDefenses(ghost, NPCDT_BLOCK);
					else Ghost_SetDefenses(ghost, defs);
					statecounter=delay;
					faceanim=0;
					olddir=Ghost_Dir;
				}
			}
			if (dirshift>0 && Ghost_Dir!=olddir&& faceanim==0){
				statecounter=45;
				faceanim=1;
				olddir=Ghost_Dir;
			}
			FSAnimation(ghost, OrigTile, numstates, pos, numframes, faceanim);
			Ghost_Waitframe(this, ghost);
		}		
	}
}	

void FSAnimation(npc ghost, int origtile, int numstates, int State, int numframes, int faceanim){
	int offset = 0;
	int faceoffset = 1;	
	while (State>=4){
		offset+=20*ghost->TileHeight;
		State-=4;
	}
	while(numstates>4){
		faceoffset++;
		numstates-=4;
	}
	if (faceanim>0)	offset+=20*ghost->TileHeight*faceoffset;
	offset +=numframes * ghost->TileWidth*State;
	// if (ghost->CSet==6)debugValue(1,offset);
	ghost->OriginalTile = origtile + offset;
}

const int CMB_FACE_SHIFTER_BOSS_SWITCH_ANIM = 1044;//Combo to use for alternate face shifting animation
const int FACE_SHIFTER_BOSS_JUMP_SPEED = 3.2;//Boss jumping speed

//Cycling Shapeshifter - Boss variant

//Moves in 4 directions. Vulnerable only during specific frame of animation.
//When it changes faces, it jumps and fires eweapon on landing.
//E.Anim - None, 2-frame, 3-frame or 4-frame, one row every 4 states.

ffc script BossFaceShifter{
	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 delay = Ghost_GetAttribute(ghost, 0, 60);//Delay between changing frames.
		int numstates = Ghost_GetAttribute(ghost, 1, 4);//Number of frames in animation
		int sizex = Ghost_GetAttribute(ghost, 2, 1);//Tile Width
		int sizey = Ghost_GetAttribute(ghost, 3, 1);//Tile Height
		int targetstate = Ghost_GetAttribute(ghost, 4, 0);//Target frame.
		int numframes = Ghost_GetAttribute(ghost, 5, 2);//number of frames per step.
		int dirshift = Ghost_GetAttribute(ghost, 6, 0);//>0 - switch face every time enemy turns, ignoring timing.
		int faceswitchanim = Ghost_GetAttribute(ghost, 7, 0);//>0 - use animation when switching faces, uses the same stup right below original animation
		int ewsprite = Ghost_GetAttribute(ghost, 8, -1);//Sprite used for eweapons.
		int ewspeed = Ghost_GetAttribute(ghost, 9, 300);//Eweapon speed
		
		ghost->Extend=3;
		Ghost_SetSize(this, ghost, sizex, sizey);
		if (sizex>2 && sizey>2)Ghost_SetHitOffsets(ghost, 8, 8, 8, 8);
		
		Ghost_SetFlag(GHF_NORMAL);
		Ghost_UnsetFlag(GHF_KNOCKBACK);
		
		int OrigTile = ghost->OriginalTile;
		int State = 1;
		int haltcounter = -1;
		int pos =0;
		int statecounter=delay;
		int olddir = Ghost_Dir;
		int faceanim=0;
		Ghost_Z=256;
		int origmidi = Game->GetMIDI();
				Game->PlayMIDI(0);
		Game->PlaySound(SFX_FALL);
		
		int defs[18];
		Ghost_StoreDefenses(ghost,defs);
		if (pos!=targetstate)Ghost_SetAllDefenses(ghost, NPCDT_BLOCK);
		
		
		while(true){
			if (State==1){
				if (Ghost_Z==0){
					Game->PlaySound(3);
					Screen->Quake=48;
					if (Game->GetMIDI()<=0)Game->PlayMIDI(origmidi);
					State=0;
				}
			}
			if (State==0){
				if (statecounter>48 || faceswitchanim==0)haltcounter = Ghost_ConstantWalk4(haltcounter, SPD, RR, HF, HNG);
				if (faceanim>0 || dirshift==0)statecounter--;
				if (statecounter<=48){
					if (faceanim==0)Ghost_Jump=FACE_SHIFTER_BOSS_JUMP_SPEED;
					faceanim=1;
				}
				if (statecounter==0){
					if (WPND>0){
						eweapon e =  FireAimedEWeapon(ghost->Weapon, CenterX(ghost), CenterY(ghost),0, ewspeed, WPND, ewsprite, -1, 0);
					}
					pos++;
					if (pos>=numstates)pos=0;						
					if (pos!=targetstate)Ghost_SetAllDefenses(ghost, NPCDT_BLOCK);
					else Ghost_SetDefenses(ghost, defs);
					statecounter=delay;
					faceanim=0;
					//Game->PlaySound(3);
					//Screen->Quake=48;
					olddir=Ghost_Dir;
				}
			}
			if (dirshift>0 && Ghost_Dir!=olddir&& faceanim==0){
				statecounter=48;
				faceanim=1;
				olddir=Ghost_Dir;
			}
			//debugValue(1,Ghost_Data);
			FSBAnimation(ghost, OrigTile, numstates, pos, numframes, faceanim);
			if (!Ghost_Waitframe(this, ghost, false, false)){
				Ghost_DeathAnimation(this, ghost, GHD_EXPLODE);
				Quit();
			}
		}		
	}
}	

void FSBAnimation(npc ghost, int origtile, int numstates, int State, int numframes, int faceanim){
	if (CMB_FACE_SHIFTER_BOSS_SWITCH_ANIM>0 && faceanim>0){
		Screen->DrawCombo	(3, Ghost_X, Ghost_Y-Ghost_Z, 
		CMB_FACE_SHIFTER_BOSS_SWITCH_ANIM, Ghost_TileWidth, Ghost_TileHeight, 
		Ghost_CSet, -1, -1, 
		0, 0, 0, 
		0, 0, 
		true, OP_OPAQUE);
		ghost->DrawXOffset=1000;
		return;
	}
	ghost->DrawXOffset=0;
	int offset = 0;
	int faceoffset = 1;	
	while (State>=4){
		offset+=20*ghost->TileHeight;
		State-=4;
	}
	while(numstates>4){
		faceoffset++;
		numstates-=4;
	}
	if (faceanim>0)	offset+=20*ghost->TileHeight*faceoffset;
	offset +=numframes * ghost->TileWidth*State;
	ghost->OriginalTile = origtile + offset;
}