Files
ForgottenWawiTech/Content/Projectiles/FragmentedPrism/FragmentedPrismShard.cs
T

188 lines
6.4 KiB
C#

using Microsoft.Xna.Framework;
using Terraria;
using Terraria.Audio;
using Terraria.ID;
using Terraria.ModLoader;
namespace ForgottenWawiTech.Content.Projectiles.FragmentedPrism
{
public class FragmentedPrismShard : ModProjectile
{
private const float OrbitRadius = 72f;
private const float BaseOrbitSpeed = 0.04f;
private const int FireInterval = 1;
private const int VisualSpawnInterval = 18;
private ref float ShardIndex => ref Projectile.ai[0];
private ref float OrbitAngleOffset => ref Projectile.ai[1];
private ref float FireTimer => ref Projectile.localAI[0];
private ref float VisualTimer => ref Projectile.localAI[1];
public override void SetStaticDefaults()
{
Main.projFrames[Type] = 5;
}
public override void SetDefaults()
{
Projectile.width = 22;
Projectile.height = 22;
Projectile.friendly = false;
Projectile.hostile = false;
Projectile.penetrate = -1;
Projectile.tileCollide = false;
Projectile.ignoreWater = true;
Projectile.timeLeft = 2;
Projectile.hide = false;
}
public override bool? CanDamage() => false;
public override void AI()
{
Player player = Main.player[Projectile.owner];
if (!player.active || player.dead)
{
Projectile.Kill();
return;
}
int itemType = ModContent.ItemType<Items.Weapons.Magic.FragmentedPrism>();
if (player.HeldItem.type != itemType)
{
Projectile.Kill();
return;
}
if (OrbitAngleOffset == 0f && ShardIndex >= 0f)
{
OrbitAngleOffset = MathHelper.TwoPi * (ShardIndex / FragmentedPrismController.ShardCount);
}
if (!TryGetController(player, out Projectile controller))
{
Projectile.Kill();
return;
}
float chargeTimer = controller.ai[1];
float chargeProgress = FragmentedPrismController.MaxChargeTime > 0f
? MathHelper.Clamp(chargeTimer / FragmentedPrismController.MaxChargeTime, 0f, 1f)
: 0f;
int firingShardCount = (int)MathHelper.Clamp(chargeTimer / FragmentedPrismController.ChargeTimePerShard, 0f, FragmentedPrismController.ShardCount);
bool canFire = ShardIndex < firingShardCount;
float orbitSpeed = BaseOrbitSpeed + chargeProgress * 0.06f;
float orbitRadius = OrbitRadius + chargeProgress * 12f;
float rotation = (float)(Main.GameUpdateCount * orbitSpeed) + OrbitAngleOffset;
Vector2 desiredPosition = player.Center + rotation.ToRotationVector2() * orbitRadius;
Projectile.Center = desiredPosition;
Vector2 aim = Main.MouseWorld - Projectile.Center;
if (aim.LengthSquared() < 0.001f)
{
aim = Vector2.UnitX * player.direction;
}
Projectile.rotation = aim.ToRotation() + MathHelper.PiOver2;
Projectile.spriteDirection = -1;
if (canFire && Main.netMode != NetmodeID.Server)
{
VisualTimer++;
if (VisualTimer >= VisualSpawnInterval)
{
VisualTimer = 0f;
SpawnBlackHoleVisual(player);
}
}
else
{
VisualTimer = 0f;
}
Animate();
if (Projectile.owner != Main.myPlayer)
{
Projectile.timeLeft = 10;
return;
}
if (canFire)
{
FireTimer++;
if (FireTimer >= FireInterval)
{
FireTimer = 0f;
FireBeam(player);
}
}
else
{
FireTimer = 0f;
}
Projectile.timeLeft = 10;
}
private void Animate()
{
Projectile.frameCounter++;
if (Projectile.frameCounter >= 6)
{
Projectile.frameCounter = 0;
Projectile.frame = (Projectile.frame + 1) % Main.projFrames[Type];
}
}
private void FireBeam(Player player)
{
Vector2 aimDirection = Main.MouseWorld - Projectile.Center;
if (aimDirection.LengthSquared() < 4f)
{
aimDirection = Vector2.UnitX * player.direction;
}
aimDirection.Normalize();
Vector2 velocity = aimDirection * 30f;
int beamType = ModContent.ProjectileType<FragmentedPrismBeam>();
int damage = Projectile.originalDamage > 0 ? Projectile.originalDamage : player.GetWeaponDamage(player.HeldItem);
float knockBack = player.GetWeaponKnockback(player.HeldItem, player.HeldItem.knockBack);
Projectile.NewProjectile(Projectile.GetSource_FromThis(), Projectile.Center, velocity, beamType, damage, knockBack, player.whoAmI);
SoundEngine.PlaySound(SoundID.Item91 with { Volume = 0.2f, Pitch = 0.55f }, Projectile.Center);
}
private void SpawnBlackHoleVisual(Player player)
{
if (Projectile.owner != Main.myPlayer)
{
return;
}
int visualType = ModContent.ProjectileType<FragmentedPrismSingularity>();
Vector2 toMouse = Main.MouseWorld - Projectile.Center;
Vector2 offset = toMouse.SafeNormalize(Vector2.UnitY) * -16f;
Projectile.NewProjectile(Projectile.GetSource_FromThis(), Projectile.Center + offset, Vector2.Zero, visualType, 0, 0f, Projectile.owner);
}
private bool TryGetController(Player player, out Projectile controller)
{
int controllerType = ModContent.ProjectileType<FragmentedPrismController>();
for (int i = 0; i < Main.maxProjectiles; i++)
{
Projectile proj = Main.projectile[i];
if (proj.active && proj.owner == player.whoAmI && proj.type == controllerType)
{
controller = proj;
return true;
}
}
controller = null;
return false;
}
}
}