Copy to Clipboard Test

Homing fireball shooter (AutoGhost) Code

// import "std.zh"
// import "string.zh"
// import "ghost.zh"

const int HFS_DEFAULT_STEP = 100;
const int HFS_DEFAULT_HOMING_TIME = 180;
const int HFS_DEFAULT_SPRITE = 17;
const int HFS_MIN_FIRE_TIME = 120;
const int HFS_MAX_FIRE_TIME = 480;
const int HFS_MIN_DISTANCE = 32;
const int HFS_DEFAULT_GRANULARITY = 0;
const int HFS_IC_SHIELD = 12; // Shield item class; you'll probably need to
							  // change this if using a GB-style shield

// npc->Misc[] indices
const int HFS_ATTR_STEP = 0;
const int HFS_ATTR_TURN_SPEED = 1;
const int HFS_ATTR_HOMING_TIME = 2;
const int HFS_ATTR_SHIELD_LEVEL = 3;
const int HFS_ATTR_SPRITE = 4;
const int HFS_ATTR_ROTATE = 5;
const int HFS_ATTR_SOUND = 6;
const int HFS_ATTR_MIN_DISTANCE = 7;
const int HFS_ATTR_GRANULARITY = 8;

ffc script HomingFireballShooter
{
	void run(int enemyID)
	{
		npc ghost;
		eweapon fireball;
		int damage;
		int step;
		float turnSpeed;
		int homingTime;
		int sprite;
		int sound;
		int distance;
		int granularity;
		int flags=0;
		int angle;

		
		// Initialize
		ghost=Ghost_InitAutoGhost(this, enemyID);
		ghost->CollDetection = false; // So Link won't get knocked back from touching it
		
		// Get enemy settings
		damage=ghost->WeaponDamage;
		
		step=Ghost_GetAttribute(ghost, HFS_ATTR_STEP, HFS_DEFAULT_STEP);
		turnSpeed=Ghost_GetAttribute(ghost, HFS_ATTR_TURN_SPEED, 0)/1000;
		homingTime=Ghost_GetAttribute(ghost, HFS_ATTR_HOMING_TIME, HFS_DEFAULT_HOMING_TIME);
		sprite=Ghost_GetAttribute(ghost, HFS_ATTR_SPRITE, HFS_DEFAULT_SPRITE, 0, 255);
		sound=Ghost_GetAttribute(ghost, HFS_ATTR_SOUND, 0, 0, 255);
		distance=Ghost_GetAttribute(ghost, HFS_ATTR_MIN_DISTANCE, 0, 0, 1024);
		granularity=Ghost_GetAttribute(ghost, HFS_ATTR_GRANULARITY, HFS_DEFAULT_GRANULARITY);
		
		if(ghost->Attributes[HFS_ATTR_SHIELD_LEVEL]<0)
			flags|=EWF_UNBLOCKABLE;
		else if(CurrentShieldLevel()<ghost->Attributes[HFS_ATTR_SHIELD_LEVEL])
			flags|=EWF_UNBLOCKABLE;
		
		if(ghost->Attributes[HFS_ATTR_ROTATE]>0)
			flags|=EWF_ROTATE;
		
		while(true)
		{
			Ghost_Waitframes(this, ghost, true, true, Rand(HFS_MIN_FIRE_TIME, HFS_MAX_FIRE_TIME));
			
			if(granularity<=0) // 0 granularity allows it to fire at any angle toward Link
				angle=RadtoDeg(ArcTan(Link->X-Ghost_X, Link->Y-Ghost_Y));
			else // 4 is 4-directional, 8 is 8-directional, 16 is 16-directional, etc. Yes, odd values work fine too.
				angle=Round(RadtoDeg(ArcTan(Link->X-Ghost_X, Link->Y-Ghost_Y))*granularity/360)*(360/granularity);


			if(Distance(Ghost_X, Ghost_Y, Link->X, Link->Y)>=distance)
			{
				fireball=FireEWeapon(EW_FIREBALL, Ghost_X, Ghost_Y, DegtoRad(angle), step, damage, sprite, sound, flags);
				if(turnSpeed!=0)
					SetEWeaponmovement(fireball, EWM_HOMING, turnSpeed);
				SetEWeaponLifespan(fireball, EWL_TIMER, homingTime);
			}
		}
		
	}
	
	// Get the level of Link's current shield
	int CurrentShieldLevel()
	{
		itemdata id;
		int maxLevel=0;
		
		for(int i=0; i<256; i++)
		{
			if(!Link->Item[i])
				continue;
			
			id=Game->LoadItemData(i);
			if(id->Family!=HFS_IC_SHIELD)
				continue;
			
			if(id->Level>maxLevel)
				maxLevel=id->Level;
		}
		
		return maxLevel;
	}
}