Refactor and redo Shattered Prism
This commit is contained in:
@@ -0,0 +1,187 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user