Copy to Clipboard Test

Dead Man's Volley (AKA Tennis) Code

DEFINE LW_TENNIS_HITBOX = LW_SCRIPT10; // Weapon type used for the LWeapon hitbox on a reflected volley

CONFIG SFX_TENNIS_REFLECT_LINK = SFX_CLINK; // Sound when Link hits the weapon
CONFIG SFX_TENNIS_REFLECT_ENEMY = SFX_CLINK; // Sound when the enemy hits the weapon

CONFIG TENNIS_HIT_STOP = 8; // How many frames the weapon holds in place before reflecting

@InitD0("Bounces"),
@InitDHelp0("How many extra times the weapon must be hit before its enemy hitbox goes active. If >0 the enemy can bounce the weapon back at Link."),
@InitD1("Homing"),
@InitDHelp1("Whether or not the weapon homes in on the parent enemy. Useful if the enemy is fast moving and you don't want the volleys to miss.")
eweapon script Tennis
{
	void run(int bounces, bool homing)
	{
		lweapon hitbox = FireLWeaponDegAngle(LW_TENNIS_HITBOX, this->X, this->Y, 0, 0, this->Damage, 0, 0);
		hitbox->NoCollisionTimer = -1;
		hitbox->DrawXOffset = -10000;
		hitbox->HitXOffset = this->HitXOffset;
		hitbox->HitYOffset = this->HitYOffset;
		hitbox->HitWidth = this->HitWidth;
		hitbox->HitHeight = this->HitHeight;

		bool reflected;
		int step = this->Step;
		while(true)
		{
			this->Dir = AngleDir4(WrapDegrees(this->DegAngle));
			if(hitbox->isValid())
			{
				hitbox->X = this->X;
				hitbox->Y = this->Y;
				hitbox->Dir = this->Dir;
			}

			if(!reflected)
			{
				bool hit;
				for(int i=Screen->NumLWeapons; i>0; --i)
				{
					lweapon l = Screen->LoadLWeapon(i);
					if(l->ID==LW_SWORD||l->Weapon==LW_SWORD)
					{
						if(Collided(this, l))
						{
							hit = true;
							break;
						}
						
					}
				}
				if(hit)
				{
					Audio->PlaySound(SFX_TENNIS_REFLECT_LINK);
					this->Step = 0;
					this->NoCollisionTimer = TENNIS_HIT_STOP;
					Waitframes(TENNIS_HIT_STOP);
					this->Step = step;
					this->DegAngle = Angle(CenterLinkX(), CenterLinkY(), CenterX(this), CenterY(this));
					reflected = true;
				}
			}
			else
			{
				this->NoCollisionTimer = 2;
				if(homing)
				{
					if(this->Parent->isValid())
					{
						this->DegAngle = Angle(CenterX(this), CenterY(this), CenterX(this->Parent), CenterY(this->Parent));
					}
				}
				if(bounces<=0)
				{
					if(hitbox->isValid())
						hitbox->NoCollisionTimer = 0;
					else
						this->Remove();
				}
				else
				{
					if(Collided(this, this->Parent))
					{
						Audio->PlaySound(SFX_TENNIS_REFLECT_ENEMY);
						this->Step = 0;
						this->NoCollisionTimer = TENNIS_HIT_STOP;
						Waitframes(TENNIS_HIT_STOP);
						this->Step = step;
						this->DegAngle = Angle(CenterX(this), CenterY(this), CenterLinkX(), CenterLinkY());
						--bounces;
						reflected = false;
					}
				}
			}
			Waitframe();
		}
	}
	bool Collided(eweapon this, sprite s)
	{
		int x1 = s->X+s->HitXOffset;
		int y1 = s->Y+s->HitYOffset;
		int x2 = this->X+this->HitXOffset+4;
		int y2 = this->Y+this->HitYOffset+4;
		return RectCollision(x1, y1, x1+s->HitWidth-1, y1+s->HitHeight-1, x2, y2, x2+this->HitWidth-9, y2+this->HitHeight-9) && (this->Z + this->HitZHeight >= s->Z) && (this->Z <= s->Z + s->HitZHeight);
	}
}