Jump to content

Photo

Buggy 8-way movement + stun combination

ghost.zh

  • Please log in to reply
2 replies to this topic

#1 Alucard648

Alucard648

    Wizard

  • Members
  • Location:castle Dracula

Posted 08 June 2023 - 07:00 PM

1. Set 8-way movement flag

Ghost_SetFlag(GHF_8WAY);

2. Stun moving enemy using any method.

3. Random tiles are drawn under enemy, using enemy`s CSet.

const int SFX_BLIND_BERSERK = 31;//Sound to play,when boss goes berserk

//Blind the Thief from Link to the Past

//Moves around, firing eweapons at Link. whehen damaged high rnough, spawns one loose head enemy, when all loose head enemies are spawned, he will move faster.
//Uses 2 rows of tiles, 1 for normal movement and for stunned state (4 frames.)

ffc script Blind_the_Thief{
	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 sizex = Ghost_GetAttribute(ghost, 0, 4);//Tile Width
		int sizey = Ghost_GetAttribute(ghost, 1, 2);//Tile Height
		int looseheadID = Ghost_GetAttribute(ghost, 2, ghost->ID+1);//ID of loose heads enemy
		int numheads = Ghost_GetAttribute(ghost, 3, 3);//Number of heads hidden inside
		int berserkSPD = Ghost_GetAttribute(ghost, 4, 100);//Speed of enemy, when it went berserk
		int shotspeed = Ghost_GetAttribute(ghost, 5, 120);//Delay between shooting, in frames.
		int WPNS = Ghost_GetAttribute(ghost, 6, -1);//Eweapon sprite.
		int knockdown = Ghost_GetAttribute(ghost, 7, 180);//Knockdown duration, un frames. Used when spawning head
		int xOffset = Ghost_GetAttribute(ghost, 8, 32);//Offset used for head spawning and shooting.
		int yOffset = Ghost_GetAttribute(ghost, 9, 0);
		
		ghost->Extend=3;
		Ghost_SetSize(this, ghost, sizex, sizey);
		if (sizex>2)Ghost_SetHitOffsets(ghost, 4, 4, 8, 8);
		
		int State = 0;
		
		int haltcounter = -1;
		float angle=Rand(360);
		int statecounter = 0;
		eweapon e;
		int heads = 0;
		int shootcounter=shotspeed;
		int shoottimer =0;
		int Ghost_MaxHP = Ghost_HP;
		int hpthreshold = Lerp(0, Ghost_MaxHP,1-((heads+1)/(numheads+1)));
		int origtile = ghost->OriginalTile;
		int offset = 0;
		int facedir = 0;
		npc head = Screen->CreateNPC(looseheadID);
		int headtile=head->OriginalTile;
		Remove(head);
		bool berserk=false;
		
		Ghost_SetFlag(GHF_NORMAL);
		Ghost_SetFlag(GHF_IGNORE_WATER);
		Ghost_SetFlag(GHF_IGNORE_PITS);
		Ghost_SetFlag(GHF_NO_FALL);
		Ghost_SetFlag(GHF_8WAY);
		Ghost_UnsetFlag(GHF_KNOCKBACK);
		Ghost_SetFlag(GHF_FLYING_ENEMY);
		
		while(true){
			if (State==0){
				haltcounter = Ghost_ConstantWalk8(haltcounter, SPD, RR, HF, HNG);
				facedir = AngleDir4(Angle(ghost->X+xOffset, ghost->Y+yOffset, Link->X, Link->Y));
				if (!berserk)Screen->FastTile	(3,ghost->X+xOffset, ghost->Y+yOffset, headtile+facedir, Ghost_CSet,OP_OPAQUE);
				shootcounter--;
				if (shootcounter<=0){
					e = FireAimedEWeapon(ghost->Weapon, ghost->X+xOffset, ghost->Y+yOffset, 0, 180, WPND, WPNS, -1, 0);
					shootcounter=shotspeed;
				}
				if (Ghost_HP>0 && Ghost_HP<=hpthreshold){
					head = CreateNPCAt(looseheadID, Ghost_X+xOffset, Ghost_Y+yOffset);
					ghost->CollDetection =false;
					ghost->OriginalTile = GH_BLANK_TILE;
					heads++;
					hpthreshold = Lerp(0, Ghost_MaxHP,1-((heads+1)/(numheads+1)));
					if (heads>=numheads){
						SPD = berserkSPD;
						berserk=true;
						
					}
					statecounter=knockdown;
					State=1;
				}
			}
			else if (State==1){
				for (int i=0;i<=3;i++){
					if (i==4){
						offset = 3*Ghost_TileWidth+20*Ghost_TileHeight;
						break;
					}
					if (statecounter<=(ghost->ASpeed*i)||(knockdown-statecounter)<(ghost->ASpeed*i)){
						offset = i*Ghost_TileWidth+20*Ghost_TileHeight;
						break;
					}
				}
				Screen->DrawTile	(2, ghost->X, ghost->Y,origtile+offset, Ghost_TileWidth, Ghost_TileHeight,Ghost_CSet, -1, -1,0, 0, 0,0,true, OP_OPAQUE);
				statecounter--;
				if (statecounter<=0){
					ghost->CollDetection=true;
					ghost->OriginalTile=origtile;
					State=0;
					if (heads==numheads)Game->PlaySound(SFX_BLIND_BERSERK);
				}
			}
			// debugValue(1, hpthreshold);
			// debugValue(2, heads);
			if(!Ghost_Waitframe(this, ghost, false, false)){
				for (int i=1;i<=Screen->NumNPCs();i++){
					npc n=Screen->LoadNPC(i);
					if (n->ID!=looseheadID) continue;
					SetEnemyProperty(n, ENPROP_HP, 0);
				}
				Ghost_DeathAnimation(this, ghost, 2);
				Quit();
			}
		}
	}
} 

ffc script BlindLooseHead{
	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 firenum = Ghost_GetAttribute(ghost, 0, 1);//Number of eweapons to fire per burst
		int shotspeed = Ghost_GetAttribute(ghost, 1, 60);//Delay between shots, in frames. Enemy won`t fire , if Weapon Damage is 0.
		int ewsprite = Ghost_GetAttribute(ghost, 2, -1);//Eweapon sprite
		int firerate =  Ghost_GetAttribute(ghost, 3, 4);
		
		
		
		Ghost_SetFlag(GHF_NORMAL);
		Ghost_SetFlag(GHF_IGNORE_WATER);
		Ghost_SetFlag(GHF_IGNORE_PITS);
		Ghost_SetFlag(GHF_NO_FALL);
		Ghost_SetFlag(GHF_8WAY);
		Ghost_UnsetFlag(GHF_KNOCKBACK);
		Ghost_SetFlag(GHF_FLYING_ENEMY);
		
		int State = 0;
		int shotcounter=shotspeed;
		int shoottimer =0;
		int haltcounter = -1;
		eweapon e;
		
		int defs[18];
		Ghost_StoreDefenses(ghost,defs);
		
		while(true){
			if (State==0){
				haltcounter = Ghost_ConstantWalk8(haltcounter, SPD, RR, HF, HNG);
				shotcounter--;
				if (shotcounter==0 && WPND>0){
					shoottimer = firerate*firenum;
					shotcounter=shotspeed;
				}
				if (shoottimer>0){
					if ((shoottimer%firerate)==0){
						e = FireAimedEWeapon(ghost->Weapon, Ghost_X, Ghost_Y, 0, 200, WPND, ewsprite, -1, 0);
					}
					shoottimer--;
				}
			}
			if (!Ghost_Waitframe(this, ghost, false, false)){
				Quit();
			}
		}
	}	
} 

https://drive.google...iew?usp=sharing

 



#2 Twilight Knight

Twilight Knight

    Tell all with glee, Argon's on PureZC

  • Members
  • Real Name:Sven
  • Location:Rotterdam, NL

Posted 09 June 2023 - 08:20 AM

I'm guessing this is because you are using the NPC itself for drawing the ghosted enemy while it's supposed to use the FFC to draw the enemy sprites.

At least when I use Ghost_Transform to change the enemy sprite this works fine. Have you tried that yet instead of changing ghost->originalTile?



#3 Alucard648

Alucard648

    Wizard

  • Members
  • Location:castle Dracula

Posted 09 June 2023 - 01:02 PM

IAt least when I use Ghost_Transform to change the enemy sprite this works fine. Have you tried that yet instead of changing ghost->originalTile?

Ditched editing ghost->originalTile for debug purposes, same effect. Switched to 4-way movement, bug is gone. And editing ghost->OriginalTile worked surprisingly fine in all other cases. (LsiCV, stdWeapons.zh) 


Edited by Alucard648, 09 June 2023 - 01:03 PM.




Also tagged with one or more of these keywords: ghost.zh

2 user(s) are reading this topic

0 members, 2 guests, 0 anonymous users