I want to make a sword have a swinging projectile like Arkhalis, I made the projectile with the help of some older post on this forum. It's swinging, but my problem is, that I have no idea what to change in my code to make the "swing speed" lower (kinda like the "Murasama" from Calamity mod works). I have a gif to explain what I mean a little better (it's a little slow but you can see what I mean).
(I only mean "how many times a second" the damage is dealt, I know how to change the animation speed).
Here's the projectile code:
and here's the weapon code:
Is there a way to edit the code to make it work like that, or do I have to rewrite the whole code?
(I only mean "how many times a second" the damage is dealt, I know how to change the animation speed).
Here's the projectile code:
C#:
using System.IO;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Terraria;
using Terraria.ID;
using Terraria.ModLoader;
namespace CthulhuMayCry.Projectiles
{
class Slash : ModProjectile
{
public override void SetStaticDefaults()
{
Main.projFrames[projectile.type] = 13;
}
public override void SetDefaults()
{
projectile.scale = 2f;
projectile.width = 40;
projectile.height = 128;
projectile.aiStyle = -1;
projectile.friendly = true;
projectile.penetrate = -1;
projectile.tileCollide = false;
projectile.hide = true;
projectile.ownerHitCheck = true; //so you can't hit enemies through walls
projectile.melee = true;
}
public override void OnHitNPC(NPC target, int damage, float knockback, bool crit)
{
//3a: target.immune[projectile.owner] = 20;
//3b: target.immune[projectile.owner] = 5;
}
public override void AI()
{
Player player = Main.player[projectile.owner]; // Cache the player that is the owner of this projectile.
float num = 1.57079637f; // Hardcoded floating number (we'll get to this later).
Vector2 vector = player.RotatedRelativePoint(player.MountedCenter, true); // Basically a position that we can use to properly place our projectile.
if(player.direction > 0) {
drawOffsetX = + 0;
drawOriginOffsetX = - 0;
drawOriginOffsetY = - 0;
} else if(player.direction < 0) {
drawOffsetX = - 0;
drawOriginOffsetX = + 0;
drawOriginOffsetY = - 0;
}
// Now the following code was the code you already posted.
num = 0f; // We set the 'num' value to 0 (you can obviously also do this when you set the 'num' for the first time).
if (projectile.spriteDirection == -1) // If the projectile is facing left.
{
num = 3.14159274f; // Hardcode the 'num' value.
}
if (++projectile.frameCounter >= 5) {
projectile.frameCounter = 0;
if (++projectile.frame >= 13) {
projectile.frame = 0;
}
}
projectile.soundDelay--; // Something to do with sound (I'm not exactly sure WHAT this does).
if (projectile.soundDelay <= 0)
{
Main.PlaySound(2, (int)projectile.Center.X, (int)projectile.Center.Y, 1);
projectile.soundDelay = 12; // But it basically plays a sound and sets the sound delay to another value. As you may (or may not) know, every second in Terraria
} // consists of 60 ticks, so setting this value to '12' makes sure that this sound is played 5x every second (if my math skillz have not left me).
if (Main.myPlayer == projectile.owner) // Check if the local player is the owner of this projectile, if it is we update the rest.
{
if (player.channel && !player.noItems && !player.CCed) // So if the player is still using this weapon, since this weapon channels, we update it.
{ // Otherwise we KILL it (mwuahahaha). So basically destroy this projectile if the item is not being used.
float scaleFactor6 = 1f; //
if (player.inventory[player.selectedItem].shoot == projectile.type) // Check if the item that is currently selected in the players' inventory is the one that is
{ // shooting this projectile.
scaleFactor6 = player.inventory[player.selectedItem].shootSpeed * projectile.scale; // Set the 'scaleFactor6' value
}
Vector2 vector13 = Main.MouseWorld - vector; // Get the direction vector between the mouse position and the vector (vector was declared earlier, remember?)
vector13.Normalize(); // Normalize this vector since we're not in need of any large values, we just need to get the direction out of this.
if (vector13.HasNaNs()) // This check is basically used to check if the X value of the direction is 'Not a Number' (or a negative value in this case).
{
vector13 = Vector2.UnitX * (float)player.direction; // If it is, we
}
vector13 *= scaleFactor6;
if (vector13.X != projectile.velocity.X || vector13.Y != projectile.velocity.Y) // If the vector13 value is actually changing something
{ // (so if the mouse or the player have been moved).
projectile.netUpdate = true; // Make sure it gets updated for everyone if you're in multiplayer.
}
projectile.velocity = vector13; // At last, set the velocity of this projectile to the 'vector13'. This is later used to set the rotation of the projectile correctly.
}
else
{
projectile.Kill(); // Yeahh, so we destroy the projectile here if the item is not being used.
}
}
Vector2 vector14 = projectile.Center + projectile.velocity * 3f; // The following few lines are just to make this projectile 'gorgeous'.
// This adds a white/gray-ish light at the given position.
if (Main.rand.Next(3) == 0) // And this function spawns some dusts at the given position without a gravity pull and at the set position (this does not affect the actual
{ // use of this projectile... Like stated earlier: this is just to make things pretty).
int num30 = Dust.NewDust(vector14 - projectile.Size / 2f, projectile.width, projectile.height, 63, projectile.velocity.X, projectile.velocity.Y, 100, default(Color), 2f);
Main.dust[num30].noGravity = true;
Main.dust[num30].position -= projectile.velocity;
}
// Now, you didn't post the next few lines, so I'm not exactly sure if you were aware of the fact that these are also used in the Arkhalis projectile.
// These lines are actually the lines that set the position, rotation AND animation, sooo... very important!
projectile.position = player.RotatedRelativePoint(player.MountedCenter, true) - projectile.Size / 2f; // Set the position of the Arkhalis projectile, based on the 'Scale' vector.
projectile.rotation = projectile.velocity.ToRotation() + num; // As you can see, we apply the rotation of this projectile based on the velocity AND the 'num' variable.
// Now, I'm sure that the 'num' variable is needed here, but since it's hardcoded, I'm not exactly sure WHAT is does.
// You'll just have to fiddle around a bit with setting the 'num' variable untill you achieve the correct rotation.
projectile.spriteDirection = projectile.direction; // Make sure that the visual direction of the projectile is set correctly.
projectile.timeLeft = 2; // Makes sure that if this update does not get called a second time, this projectile is destroyed since it's only able to live for 2 more ticks.
player.ChangeDir(projectile.direction); // Makes sure that the owner of this projectile isfacing the same way that the projectile is (so that you don't get a situation in which
// the projectile is on the left side of the player while the player is still facing the right.
player.heldProj = projectile.whoAmI; // Again, not exactly sure what this is good for (you can test by commenting this line out of course, although my lucky guess is
// that it'll break something for sure.
player.itemTime = 20; // Hmm yeah, not really know what I should explain about this...
player.itemAnimation = 20; // This is actually where we make sure that the player sticks to one animation. If you were to change the animation of your new Arkhalis,
// this is probably where you'd want to do this.
// For this last line you might want to read up what Atan2 actually does, but you might be able to guess what this does based on the 'itemRotation' name.
// This doesn't really do anything for the actual AI of the projectile, but makes sure that the 'item' is facing the correct way (although the player is not actually
// holding anything :p).
}
}
}
and here's the weapon code:
C#:
using CthulhuMayCry.Projectiles;
using Microsoft.Xna.Framework;
using Terraria;
using Terraria.ID;
using Terraria.ModLoader;
namespace CthulhuMayCry.Items.Weapons
{
public class Yamato2 : ModItem
{
public override void SetStaticDefaults()
{
DisplayName.SetDefault("Yamato2");
Tooltip.SetDefault("Dark forged katana, once wielded by a dark slayer...");
}
public override void SetDefaults()
{
item.mana = 0;
item.damage = 333;
item.crit = 100;
item.melee = true;
item.width = 66;
item.height = 70;
item.useTime = 2;
item.useAnimation = 60;
item.channel = true;
item.noMelee = true;
item.useStyle = 6;
item.knockBack = 6;
item.value = Item.buyPrice(0, 22, 50, 0);
item.rare = 9;
item.UseSound = SoundID.Item1;
item.autoReuse = true;
item.shoot = mod.ProjectileType("Slash");
item.shootSpeed = 40f;
item.scale = 0.65f;
item.holdStyle = 3;
}
public override bool AltFunctionUse(Player player)
{
return true;
}
public override bool CanUseItem(Player player)
{
if (player.altFunctionUse == 2)
{
item.mana = 66;
item.scale = 0.65f;
item.damage = 666;
item.crit = 0;
item.melee = false;
item.width = 100;
item.height = 100;
item.useTime = 25;
item.useAnimation = 25;
item.channel = false;
item.noUseGraphic = false;
item.noMelee = true;
item.useStyle = 6;
item.knockBack = 0;
item.value = Item.buyPrice(0, 22, 50, 0);
item.rare = ItemRarityID.Pink;
if (!Main.dedServ){item.UseSound = mod.GetLegacySoundSlot(SoundType.Custom, "Sounds/Custom/JudgementCut").WithVolume(0.3f);}
item.autoReuse = false;
item.shoot = mod.ProjectileType("JudgementCut");
item.shootSpeed = 30f;
item.holdStyle = 3;
}else{
item.mana = 0;
item.damage = 333;
item.crit = 100;
item.melee = true;
item.width = 66;
item.height = 70;
item.useTime = 2;
item.useAnimation = 60;
item.channel = true;
item.noMelee = true;
item.useStyle = 6;
item.knockBack = 6;
item.value = Item.buyPrice(0, 22, 50, 0);
item.rare = 9;
item.UseSound = SoundID.Item1;
item.autoReuse = true;
item.shoot = mod.ProjectileType("Slash");
item.shootSpeed = 40f;
item.scale = 0.65f;
item.holdStyle = 3;
}
return true;
}
public override bool Shoot(Player player, ref Vector2 position, ref float speedX, ref float speedY, ref int type, ref int damage, ref float knockBack)
{
if (player.altFunctionUse == 2){
position.Y = Main.MouseWorld.Y;
position.X = Main.MouseWorld.X;
speedX = 0f;
speedY = 0f;
return true;
}
return true;
}
public static void Channel(Item item) {
item.channel = false;
}
// Help, my gun isn't being held at the handle! Adjust these 2 numbers until it looks right.
public override Vector2? HoldoutOffset()
{
return new Vector2(-5, 5);
}
public override void HoldItem(Player player){
if(player.direction < 0) {
player.itemRotation = 5f;
player.itemLocation.Y = player.Center.Y + 10f;
player.itemLocation.X = player.Center.X + 40f;
} else if(player.direction > 0) {
player.itemRotation = -5f;
player.itemLocation.Y = player.Center.Y + 10f;
player.itemLocation.X = player.Center.X - 40f;
}
}
public virtual void UseStyle(Item item, Player player) {
if (player.HeldItem.handOnSlot < 0) {
player.itemRotation = 5f;
player.itemLocation.Y = player.Center.Y + 10f;
player.itemLocation.X = player.Center.X + 40f;
}
}
public static void OnHitNPC(NPC target, int damage, float knockback, bool crit)
{
target.AddBuff(BuffID.Frozen, 60);
}
}
}
Is there a way to edit the code to make it work like that, or do I have to rewrite the whole code?