tAPI [Tutorial] Summoner Weapon (Programming knowledge required)

float moveToX = projectile.position.X;
float moveToY = projectile.position.Y;
float moveDist = 100000f; //This is basically the view range of your minion; you might want to make it slightly larger than this.
int attacking = -1;
for(int k = 0; k < 200; k++)
{
if(Main.npc[k].active && !Main.npc[k].dontTakeDamage && !Main.npc[k].friendly && Main.npc[k].lifeMax > 5)
{
float monsterX = Main.npc[k].position.X + (float)(Main.npc[k].width / 2);
float monsterY = Main.npc[k].position.Y + (float)(Main.npc[k].height / 2);
float monsterDist = System.Math.Abs(projectile.position.X + (float)(projectile.width / 2) - monsterX) + System.Math.Abs(projectile.position.Y + (float)(projectile.height / 2) - monsterY);
if(monsterDist < moveDist)
{
if(monsterDist < moveDist && Collision.CanHit(projectile.position, projectile.width, projectile.height, Main.npc[k].position, Main.npc[k].width, Main.npc[k].height))
{
moveDist = monsterDist;
moveToX = monsterX;
moveToY = monsterY;
attacking = k;
}
}
}
}
moveDist is the distance from the distance from the nearest monster your projectile can see; moveToX and moveToY specify the location of this monster; and attacking is the index location of the monster in Main.npc.
Where do i put this piece of code?
also, you haven't really said where any of these should be so it's kind of hard to figure out :guidestraightface:
 
Where do i put this piece of code?
also, you haven't really said where any of these should be so it's kind of hard to figure out :guidestraightface:
You'd put that in the AI method, where the comment says to do what the minion what normally do (attacking enemies or following the player).
 
Does anyone know how to give a buff to the player when they have a helmet equipped and also (at a different time) have a full armor set on?
 
Now that r15 for tAPI has finally been released, I've updated my tutorial. Basically, a bug was fixed so that we don't need to manually despawn minions anymore. This means that we don't need a ModItem class anymore, so that's less source code we need to copy! :guidegrin:
Now to wait for the same bug to be fixed with Damage...
Also, I recognized that the AI part (ModProjectile) of the tutorial was a bit lacking, so I included a link to my NPC AI tutorial, since NPCs and projectiles are very similar.

Also I finally get to use the thread changelog I had at the end of the post, lol
 
Now that r15 for tAPI has finally been released, I've updated my tutorial. Basically, a bug was fixed so that we don't need to manually despawn minions anymore. This means that we don't need a ModItem class anymore, so that's less source code we need to copy! :guidegrin:
Now to wait for the same bug to be fixed with Damage...
Also, I recognized that the AI part (ModProjectile) of the tutorial was a bit lacking, so I included a link to my NPC AI tutorial, since NPCs and projectiles are very similar.

Also I finally get to use the thread changelog I had at the end of the post, lol

Less hard code?
 
To be honest, the code doesn't really become any easier; we just don't need to copy over a bunch of source code anymore to free minion slots.

Question: If I want it to be that when you crit, you get 1 of 5 buffs, will this code work?
Code:
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

using TAPI;
using Terraria;

namespace Terra.Items
{
    public class MonadoShield : ModItem
    {
    public override void DamageNPC(Player p, NPC n, int hitDir, ref int damage, ref float knockback, ref bool crit, ref float critMult)
    {
        if (crit)
            {
            if (Main.rand.Next(5) == 0)
            {
                p.AddBuff("Terra:MonadoJump",420,true)
            }

            else
            {
                p.AddBuff("Terra:MonadoSpeed",420,true)
            }

            else
            {
                p.AddBuff("Terra:MonadoShield",420,true)
            }

            else
            {
                p.AddBuff("Terra:MonadoBuster",420,true)
            }

            else
            {
                p.AddBuff("Terra:MonadoSmash",420,true)
            }
            }
    }
    }
}
 
Question: If I want it to be that when you crit, you get 1 of 5 buffs, will this code work?
Code:
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

using TAPI;
using Terraria;

namespace Terra.Items
{
    public class MonadoShield : ModItem
    {
    public override void DamageNPC(Player p, NPC n, int hitDir, ref int damage, ref float knockback, ref bool crit, ref float critMult)
    {
        if (crit)
            {
            if (Main.rand.Next(5) == 0)
            {
                p.AddBuff("Terra:MonadoJump",420,true)
            }

            else
            {
                p.AddBuff("Terra:MonadoSpeed",420,true)
            }

            else
            {
                p.AddBuff("Terra:MonadoShield",420,true)
            }

            else
            {
                p.AddBuff("Terra:MonadoBuster",420,true)
            }

            else
            {
                p.AddBuff("Terra:MonadoSmash",420,true)
            }
            }
    }
    }
}
It looks like you have the right idea; it's just the syntax that's incorrect. Specifically, this part of the code:
Code:
if (Main.rand.Next(5) == 0)
            {
                p.AddBuff("Terra:MonadoJump",420,true)
            }

            else
            {
                p.AddBuff("Terra:MonadoSpeed",420,true)
            }

            else
            {
                p.AddBuff("Terra:MonadoShield",420,true)
            }

            else
            {
                p.AddBuff("Terra:MonadoBuster",420,true)
            }

            else
            {
                p.AddBuff("Terra:MonadoSmash",420,true)
            }
What you want to do is assign the random number to a variable, then use that variable either in an if/else chain or a switch statement, like this:
Code:
int choice = Main.rand.Next(5);
if(choice == 0)
{
    //add your buff
}
else if(choice == 1)
{
    //add a different buff
}
else if(choice == 2)
{
    //etc.
}
All the way to if(choice == 4). If you want to use a switch statement instead, then it would work something like this:
Code:
int choice = Main.rand.Next(5);
switch(choice)
{
    case 0:
        //add your buff
        break;
    case 1:
        //add a different buff
        break;
    case 2:
        //etc.
        break;
    case 3:
        //etc.
        break;
    default:
        //this is the last choice
        break;
}
 
It looks like you have the right idea; it's just the syntax that's incorrect. Specifically, this part of the code:
Code:
if (Main.rand.Next(5) == 0)
            {
                p.AddBuff("Terra:MonadoJump",420,true)
            }

            else
            {
                p.AddBuff("Terra:MonadoSpeed",420,true)
            }

            else
            {
                p.AddBuff("Terra:MonadoShield",420,true)
            }

            else
            {
                p.AddBuff("Terra:MonadoBuster",420,true)
            }

            else
            {
                p.AddBuff("Terra:MonadoSmash",420,true)
            }
What you want to do is assign the random number to a variable, then use that variable either in an if/else chain or a switch statement, like this:
Code:
int choice = Main.rand.Next(5);
if(choice == 0)
{
    //add your buff
}
else if(choice == 1)
{
    //add a different buff
}
else if(choice == 2)
{
    //etc.
}
All the way to if(choice == 4). If you want to use a switch statement instead, then it would work something like this:
Code:
int choice = Main.rand.Next(5);
switch(choice)
{
    case 0:
        //add your buff
        break;
    case 1:
        //add a different buff
        break;
    case 2:
        //etc.
        break;
    case 3:
        //etc.
        break;
    default:
        //this is the last choice
        break;
}

Testing it right now. Hope it works!
 
Sweet Ill definitly use this in my new mod, been wanting a summoner weapon for awhile and this is very helpful.
 
FOR THE LIFE OF ME, WHY ISN'T MY PROJECTILE DOING DAMAGE (MINION)?

Code:
{
    "displayName": "Piranha Minion",
    "tip": "This is a Piranha Minion. Yay, a Summoner Weapon.",
    "noTimer": true
}
Code:
using System;
using Terraria;
using TAPI;

namespace Terra.Buffs {
public class Piranhaminion : ModBuff
{
    public override void Start(Player player, int index)
    {
        player.buffTime[index] = 3600;
    }

    public override void MidUpdate(Player player)
    {
        bool flag = false;
        for(int k = 0; k < 1000; k++)
        {
            if(Main.projectile[k].active && Main.projectile[k].owner == player.whoAmI && Main.projectile[k].type == ProjDef.byName["Terra:Piranhasummon"].type)
            {
                flag = true;
                break;
            }
        }
        MPlayer modPlayer = player.GetSubClass<MPlayer>();
        if(flag)
        {
            modPlayer.ModMinion = true;
        }
        int type = BuffDef.byName["Terra:Piranhaminion"];
        int index = -1;
        for(int k = 0; k < player.maxBuffs; k++)
        {
            if(player.buffType[k] == type)
            {
                index = k;
                break;
            }
        }
        if(index < 0)
        {
            return;
        }
        if(!modPlayer.ModMinion)
        {
            player.DelBuff(index);
        }
        else
        {
            player.buffTime[index] = 18000;
        }
    }
}}
Code:
{
    "displayName": "Piranha Summon",
    "size": [28, 22],
    "aiStyle": 54, //This is the Raven AI. List of different summon AIs below.
    "timeLeft": 99999999999999999999999999, //Just to make sure the projectile doesn't despawn.
    "friendly": true,
    "hostile": false,
    "tileCollide": false, //So it can return to you with no trouble.
    "damage": 13,//Damage projectiles from this summon do.
    "minion": true, //Receives summoner bonuses
    "minionSlots": 1, //Takes up 1 minion slot
    "penetrate": -1 //Lasts forever
}
Code:
using System;
using Microsoft.Xna.Framework;
using Terraria;
using TAPI;

namespace Terra.Projectiles {

public class Piranhasummon : ModProjectile
{
    //If you want to store information, place fields here.

    public override void AI()
    {
    Player owner = Main.player[projectile.owner];
    if (owner == null || !owner.active || owner.dead)
    {
        projectile.Kill();
        return;
    }
    if (Main.myPlayer == owner.whoAmI)
    {
        int id = owner.HasBuff("Terra:Piranhaminion");
        if(id == -1)
        {
        projectile.Kill();
        return;
        }
    }
    }  

    private void UpdateFrame()
    {
        //Set projectile.frame here based on your projectile's state. I'll explain what this is later. To keep track of animation time, you can use projectile.frameCounter.
        //projectile.frameCounter++; //Only if you are using projectile.frameCounter.
        //projectile.frameCounter %= 10; //Or however long you want one cycle of animation to last.
    }
}}
Code:
{
    "displayName": "Piranha Staff",
    "size": [84, 84],
    "maxStack": 1,
    "value": [0, 3, 0, 0],
    "rare": 2,
    "useStyle": 1,
    "useAnimation": 18,
    "tooltip": "Spawns a Piranha that hopefully isn't buggy",
    "useTime": 18,
    "useSound": 44,
    "damage": 8,
    "knockback": 6,
    "autoReuse": false,
    "noMelee": true,
    "buff": "Terra:Piranhaminion",
    "buffTime": 99999999999999999999999,
    "shoot": "Terra:Piranhasummon",
    "shootSpeed": 3,
    "summon": true,
    "mana": 10
}
It builds fine, but it won't do any damage.
 
FOR THE LIFE OF ME, WHY ISN'T MY PROJECTILE DOING DAMAGE (MINION)?

Code:
{
    "displayName": "Piranha Minion",
    "tip": "This is a Piranha Minion. Yay, a Summoner Weapon.",
    "noTimer": true
}
Code:
using System;
using Terraria;
using TAPI;

namespace Terra.Buffs {
public class Piranhaminion : ModBuff
{
    public override void Start(Player player, int index)
    {
        player.buffTime[index] = 3600;
    }

    public override void MidUpdate(Player player)
    {
        bool flag = false;
        for(int k = 0; k < 1000; k++)
        {
            if(Main.projectile[k].active && Main.projectile[k].owner == player.whoAmI && Main.projectile[k].type == ProjDef.byName["Terra:Piranhasummon"].type)
            {
                flag = true;
                break;
            }
        }
        MPlayer modPlayer = player.GetSubClass<MPlayer>();
        if(flag)
        {
            modPlayer.ModMinion = true;
        }
        int type = BuffDef.byName["Terra:Piranhaminion"];
        int index = -1;
        for(int k = 0; k < player.maxBuffs; k++)
        {
            if(player.buffType[k] == type)
            {
                index = k;
                break;
            }
        }
        if(index < 0)
        {
            return;
        }
        if(!modPlayer.ModMinion)
        {
            player.DelBuff(index);
        }
        else
        {
            player.buffTime[index] = 18000;
        }
    }
}}
Code:
{
    "displayName": "Piranha Summon",
    "size": [28, 22],
    "aiStyle": 54, //This is the Raven AI. List of different summon AIs below.
    "timeLeft": 99999999999999999999999999, //Just to make sure the projectile doesn't despawn.
    "friendly": true,
    "hostile": false,
    "tileCollide": false, //So it can return to you with no trouble.
    "damage": 13,//Damage projectiles from this summon do.
    "minion": true, //Receives summoner bonuses
    "minionSlots": 1, //Takes up 1 minion slot
    "penetrate": -1 //Lasts forever
}
Code:
using System;
using Microsoft.Xna.Framework;
using Terraria;
using TAPI;

namespace Terra.Projectiles {

public class Piranhasummon : ModProjectile
{
    //If you want to store information, place fields here.

    public override void AI()
    {
    Player owner = Main.player[projectile.owner];
    if (owner == null || !owner.active || owner.dead)
    {
        projectile.Kill();
        return;
    }
    if (Main.myPlayer == owner.whoAmI)
    {
        int id = owner.HasBuff("Terra:Piranhaminion");
        if(id == -1)
        {
        projectile.Kill();
        return;
        }
    }
    }

    private void UpdateFrame()
    {
        //Set projectile.frame here based on your projectile's state. I'll explain what this is later. To keep track of animation time, you can use projectile.frameCounter.
        //projectile.frameCounter++; //Only if you are using projectile.frameCounter.
        //projectile.frameCounter %= 10; //Or however long you want one cycle of animation to last.
    }
}}
Code:
{
    "displayName": "Piranha Staff",
    "size": [84, 84],
    "maxStack": 1,
    "value": [0, 3, 0, 0],
    "rare": 2,
    "useStyle": 1,
    "useAnimation": 18,
    "tooltip": "Spawns a Piranha that hopefully isn't buggy",
    "useTime": 18,
    "useSound": 44,
    "damage": 8,
    "knockback": 6,
    "autoReuse": false,
    "noMelee": true,
    "buff": "Terra:Piranhaminion",
    "buffTime": 99999999999999999999999,
    "shoot": "Terra:Piranhasummon",
    "shootSpeed": 3,
    "summon": true,
    "mana": 10
}
It builds fine, but it won't do any damage.
Hm, it's hard to tell. Did you try copying over the Damage() source code and removing the first two if statements? Also, did you try making sure projectile.friendly is true when it is attacking?
 
using System;
using Microsoft.Xna.Framework;
using Terraria;

namespace Hypaxi.Projectiles.Minions
{
public abstract class Mancer : Minion
{
protected float idleAccel = 0.05f;
protected float spacingMult = 1f;
protected float viewDist = 400f;
protected float chaseDist = 200f;
protected float chaseAccel = 6f;
protected float inertia = 40f;
protected float shootCool = 90f;
protected float shootSpeed;
protected int shoot;

public virtual void CreateDust()
{
}

public virtual void SelectFrame()
{
}

public override void Behavior()
{
Player player = Main.player[projectile.owner];
float spacing = (float)projectile.width * spacingMult;
for (int k = 0; k < 1000; k++)
{
Projectile otherProj = Main.projectile[k];
if (k != projectile.whoAmI && otherProj.active && otherProj.owner == projectile.owner && otherProj.type == projectile.type && System.Math.Abs(projectile.position.X - otherProj.position.X) + System.Math.Abs(projectile.position.Y - otherProj.position.Y) < spacing)
{
if (projectile.position.X < Main.projectile[k].position.X)
{
projectile.velocity.X -= idleAccel;
}
else
{
projectile.velocity.X += idleAccel;
}
if (projectile.position.Y < Main.projectile[k].position.Y)
{
projectile.velocity.Y -= idleAccel;
}
else
{
projectile.velocity.Y += idleAccel;
}
}
}
Vector2 targetPos = projectile.position;
float targetDist = viewDist;
bool target = false;
projectile.tileCollide = true;
for (int k = 0; k < 200; k++)
{
NPC npc = Main.npc[k];
if (npc.CanBeChasedBy(this, false))
{
float distance = Vector2.Distance(npc.Center, projectile.Center);
if ((distance < targetDist || !target) && Collision.CanHitLine(projectile.position, projectile.width, projectile.height, npc.position, npc.width, npc.height))
{
targetDist = distance;
targetPos = npc.Center;
target = true;
}
}
}
if (Vector2.Distance(player.Center, projectile.Center) > (target ? 1000f : 500f))
{
projectile.ai[0] = 1f;
projectile.netUpdate = true;
}
if (projectile.ai[0] == 1f)
{
projectile.tileCollide = false;
}
if (target && projectile.ai[0] == 0f)
{
Vector2 direction = targetPos - projectile.Center;
if (direction.Length() > chaseDist)
{
direction.Normalize();
projectile.velocity = (projectile.velocity * inertia + direction * chaseAccel) / (inertia + 1);
}
else
{
projectile.velocity *= (float)Math.Pow(0.97, 40.0 / inertia);
}
}
else
{
if (!Collision.CanHitLine(projectile.Center, 1, 1, player.Center, 1, 1))
{
projectile.ai[0] = 1f;
}
float speed = 6f;
if (projectile.ai[0] == 1f)
{
speed = 15f;
}
Vector2 center = projectile.Center;
Vector2 direction = player.Center - center;
projectile.ai[1] = 3600f;
projectile.netUpdate = true;
int num = 1;
for (int k = 0; k < projectile.whoAmI; k++)
{
if (Main.projectile[k].active && Main.projectile[k].owner == projectile.owner && Main.projectile[k].type == projectile.type)
{
num++;
}
}
direction.X -= (float)((10 + num * 40) * player.direction);
direction.Y -= 70f;
float distanceTo = direction.Length();
if (distanceTo > 200f && speed < 9f)
{
speed = 9f;
}
if (distanceTo < 100f && projectile.ai[0] == 1f && !Collision.SolidCollision(projectile.position, projectile.width, projectile.height))
{
projectile.ai[0] = 0f;
projectile.netUpdate = true;
}
if (distanceTo > 2000f)
{
projectile.Center = player.Center;
}
if (distanceTo > 48f)
{
direction.Normalize();
direction *= speed;
float temp = inertia / 2f;
projectile.velocity = (projectile.velocity * temp + direction) / (temp + 1);
}
else
{
projectile.direction = Main.player[projectile.owner].direction;
projectile.velocity *= (float)Math.Pow(0.9, 40.0 / inertia);
}
}
projectile.rotation = projectile.velocity.X * 0.05f;
SelectFrame();
CreateDust();
if (projectile.velocity.X > 0f)
{
projectile.spriteDirection = (projectile.direction = -1);
}
else if (projectile.velocity.X < 0f)
{
projectile.spriteDirection = (projectile.direction = 1);
}
if (projectile.ai[1] > 0f)
{
projectile.ai[1] += 1f;
if (Main.rand.Next(3) == 0)
{
projectile.ai[1] += 1f;
}
}
if (projectile.ai[1] > shootCool)
{
projectile.ai[1] = 0f;
projectile.netUpdate = true;
}
if (projectile.ai[0] == 0f)
{
if (target)
{
if ((targetPos - projectile.Center).X > 0f)
{
projectile.spriteDirection = (projectile.direction = -1);
}
else if ((targetPos - projectile.Center).X < 0f)
{
projectile.spriteDirection = (projectile.direction = 1);
}
if (projectile.ai[1] == 0f)
{
projectile.ai[1] = 1f;
if (Main.myPlayer == projectile.owner)
{
Vector2 shootVel = targetPos - projectile.Center;
if (shootVel == Vector2.Zero)
{
shootVel = new Vector2(0f, 1f);
}
shootVel.Normalize();
shootVel *= shootSpeed;
int proj = Projectile.NewProjectile(projectile.Center.X, projectile.Center.Y, shootVel.X, shootVel.Y, shoot, projectile.damage, projectile.knockBack, Main.myPlayer, 0f, 0f);
Main.projectile[proj].timeLeft = 300;
Main.projectile[proj].netUpdate = true;
projectile.netUpdate = true;
}
}
}
}
}

public override void TileCollideStyle(ref int width, ref int height, ref bool fallThrough)
{
fallThrough = true;
}
}
}





I had someone help me out with this and I'm a little bad at C so can someone explain to me why my minions sprite is flapping like a bird.
 
using System;
using Microsoft.Xna.Framework;
using Terraria;

namespace Hypaxi.Projectiles.Minions
{
public abstract class Mancer : Minion
{
protected float idleAccel = 0.05f;
protected float spacingMult = 1f;
protected float viewDist = 400f;
protected float chaseDist = 200f;
protected float chaseAccel = 6f;
protected float inertia = 40f;
protected float shootCool = 90f;
protected float shootSpeed;
protected int shoot;

public virtual void CreateDust()
{
}

public virtual void SelectFrame()
{
}

public override void Behavior()
{
Player player = Main.player[projectile.owner];
float spacing = (float)projectile.width * spacingMult;
for (int k = 0; k < 1000; k++)
{
Projectile otherProj = Main.projectile[k];
if (k != projectile.whoAmI && otherProj.active && otherProj.owner == projectile.owner && otherProj.type == projectile.type && System.Math.Abs(projectile.position.X - otherProj.position.X) + System.Math.Abs(projectile.position.Y - otherProj.position.Y) < spacing)
{
if (projectile.position.X < Main.projectile[k].position.X)
{
projectile.velocity.X -= idleAccel;
}
else
{
projectile.velocity.X += idleAccel;
}
if (projectile.position.Y < Main.projectile[k].position.Y)
{
projectile.velocity.Y -= idleAccel;
}
else
{
projectile.velocity.Y += idleAccel;
}
}
}
Vector2 targetPos = projectile.position;
float targetDist = viewDist;
bool target = false;
projectile.tileCollide = true;
for (int k = 0; k < 200; k++)
{
NPC npc = Main.npc[k];
if (npc.CanBeChasedBy(this, false))
{
float distance = Vector2.Distance(npc.Center, projectile.Center);
if ((distance < targetDist || !target) && Collision.CanHitLine(projectile.position, projectile.width, projectile.height, npc.position, npc.width, npc.height))
{
targetDist = distance;
targetPos = npc.Center;
target = true;
}
}
}
if (Vector2.Distance(player.Center, projectile.Center) > (target ? 1000f : 500f))
{
projectile.ai[0] = 1f;
projectile.netUpdate = true;
}
if (projectile.ai[0] == 1f)
{
projectile.tileCollide = false;
}
if (target && projectile.ai[0] == 0f)
{
Vector2 direction = targetPos - projectile.Center;
if (direction.Length() > chaseDist)
{
direction.Normalize();
projectile.velocity = (projectile.velocity * inertia + direction * chaseAccel) / (inertia + 1);
}
else
{
projectile.velocity *= (float)Math.Pow(0.97, 40.0 / inertia);
}
}
else
{
if (!Collision.CanHitLine(projectile.Center, 1, 1, player.Center, 1, 1))
{
projectile.ai[0] = 1f;
}
float speed = 6f;
if (projectile.ai[0] == 1f)
{
speed = 15f;
}
Vector2 center = projectile.Center;
Vector2 direction = player.Center - center;
projectile.ai[1] = 3600f;
projectile.netUpdate = true;
int num = 1;
for (int k = 0; k < projectile.whoAmI; k++)
{
if (Main.projectile[k].active && Main.projectile[k].owner == projectile.owner && Main.projectile[k].type == projectile.type)
{
num++;
}
}
direction.X -= (float)((10 + num * 40) * player.direction);
direction.Y -= 70f;
float distanceTo = direction.Length();
if (distanceTo > 200f && speed < 9f)
{
speed = 9f;
}
if (distanceTo < 100f && projectile.ai[0] == 1f && !Collision.SolidCollision(projectile.position, projectile.width, projectile.height))
{
projectile.ai[0] = 0f;
projectile.netUpdate = true;
}
if (distanceTo > 2000f)
{
projectile.Center = player.Center;
}
if (distanceTo > 48f)
{
direction.Normalize();
direction *= speed;
float temp = inertia / 2f;
projectile.velocity = (projectile.velocity * temp + direction) / (temp + 1);
}
else
{
projectile.direction = Main.player[projectile.owner].direction;
projectile.velocity *= (float)Math.Pow(0.9, 40.0 / inertia);
}
}
projectile.rotation = projectile.velocity.X * 0.05f;
SelectFrame();
CreateDust();
if (projectile.velocity.X > 0f)
{
projectile.spriteDirection = (projectile.direction = -1);
}
else if (projectile.velocity.X < 0f)
{
projectile.spriteDirection = (projectile.direction = 1);
}
if (projectile.ai[1] > 0f)
{
projectile.ai[1] += 1f;
if (Main.rand.Next(3) == 0)
{
projectile.ai[1] += 1f;
}
}
if (projectile.ai[1] > shootCool)
{
projectile.ai[1] = 0f;
projectile.netUpdate = true;
}
if (projectile.ai[0] == 0f)
{
if (target)
{
if ((targetPos - projectile.Center).X > 0f)
{
projectile.spriteDirection = (projectile.direction = -1);
}
else if ((targetPos - projectile.Center).X < 0f)
{
projectile.spriteDirection = (projectile.direction = 1);
}
if (projectile.ai[1] == 0f)
{
projectile.ai[1] = 1f;
if (Main.myPlayer == projectile.owner)
{
Vector2 shootVel = targetPos - projectile.Center;
if (shootVel == Vector2.Zero)
{
shootVel = new Vector2(0f, 1f);
}
shootVel.Normalize();
shootVel *= shootSpeed;
int proj = Projectile.NewProjectile(projectile.Center.X, projectile.Center.Y, shootVel.X, shootVel.Y, shoot, projectile.damage, projectile.knockBack, Main.myPlayer, 0f, 0f);
Main.projectile[proj].timeLeft = 300;
Main.projectile[proj].netUpdate = true;
projectile.netUpdate = true;
}
}
}
}
}

public override void TileCollideStyle(ref int width, ref int height, ref bool fallThrough)
{
fallThrough = true;
}
}
}





I had someone help me out with this and I'm a little bad at C so can someone explain to me why my minions sprite is flapping like a bird.

I forgot to make multiple sprite parts for it oops.
 
Back
Top Bottom