tAPI [Tutorial] Custom Bosses - NPC AI and Server Syncing

You can easily take any boss from any mod and look at its codes. TAPI is forcedly open-source for this exact reason.
 
do you maybe know why I get an error with this?
if (Main.netMode != 1)
{
Projectile.NewProjectile(float 1, float 1, float 1, float 1, int 44, 16, 2, Main.myPlayer, float 0, float 0);
}
 
do you maybe know why I get an error with this?
if (Main.netMode != 1)
{
Projectile.NewProjectile(float 1, float 1, float 1, float 1, int 44, 16, 2, Main.myPlayer, float 0, float 0);
}
Replace all of the "float 1" with just "1f", the "int 44" with "44", and all of the "float 0" with just "0f" (without any of the quotes, of course).
Here's some information about passing parameters, although I'm not sure how much it will help:
https://msdn.microsoft.com/en-us/library/9t0za5es.aspx
 
Thanks, I have just started modding using Tapi and I managed to make a colossal sword... Here is a picture! Next I'm trying to make an enemy that swarms around the player and damages him randomly and creates a clone of itself every time it does so. Any help?
 

Attachments

  • 11009464_1565067230402314_1117407408_o.jpg
    11009464_1565067230402314_1117407408_o.jpg
    124.1 KB · Views: 2,982
Thanks, I have just started modding using Tapi and I managed to make a colossal sword... Here is a picture! Next I'm trying to make an enemy that swarms around the player and damages him randomly and creates a clone of itself every time it does so. Any help?
If you're trying to make it so that it works on servers... that will get a bit complicated.
On the other hand, if you don't care about servers for now, you could just add something like this to your ModNPC-extending class:
Code:
public override void DealtPlayer(Player player, int hitDir, int dmgDealt, bool crit)
{
    if(Main.rand.Next(10) == 0) //Change the 10 to whatever you want. The chance of the NPC cloning itself will be 1 divided by the number you choose.
    {
        NPC.NewNPC(/* put whatever here */);
    }
}
 
If you're trying to make it so that it works on servers... that will get a bit complicated.
On the other hand, if you don't care about servers for now, you could just add something like this to your ModNPC-extending class:
Code:
public override void DealtPlayer(Player player, int hitDir, int dmgDealt, bool crit)
{
    if(Main.rand.Next(10) == 0) //Change the 10 to whatever you want. The chance of the NPC cloning itself will be 1 divided by the number you choose.
    {
        NPC.NewNPC(/* put whatever here */);
    }
}
Ummm... Thanks. This isn't everything is it? What about the AI? The generic flying AI doesn't fit, it bounces off the player when it hits, I need an enemy that stays inside the player's hitbox once it has touched the player. Like... A mosquito... Thank you for that anyway! It will help a lot once I manage to stop messing with the example mod and actually start modding... Do you happen to got any editable mods with things to copypaste to new weapons and stuff? I think that is the easiest way to learn modding. Thank you!
[DOUBLEPOST=1424971473][/DOUBLEPOST]What does that fist line do anyway? The thing about voids?
 
Ummm... Thanks. This isn't everything is it? What about the AI? The generic flying AI doesn't fit, it bounces off the player when it hits, I need an enemy that stays inside the player's hitbox once it has touched the player. Like... A mosquito... Thank you for that anyway! It will help a lot once I manage to stop messing with the example mod and actually start modding... Do you happen to got any editable mods with things to copypaste to new weapons and stuff? I think that is the easiest way to learn modding. Thank you!
[DOUBLEPOST=1424971473][/DOUBLEPOST]What does that fist line do anyway? The thing about voids?
The first line is a method declaration; it basically lets Terraria know that it needs to run that code whenever it damages the player.
For the AI, you'll want to set the aiStyle to some negative number. Next, still in the .json file, if you don't want the NPC to take knockback, you'll want to set knockbackResist to 0. (0 knockbackResist means no knockback, higher numbers mean more knockback; it's kind of confusing :confused:)
Then you'll need to override the AI method. In order to have it stay in the player's hitbox, you can look at the movement section of the tutorial. You can either have the enemy teleport to the player (the first code I have in that section), or have it move (the second code in that section) very fast so that the player cannot outrun it.
Finally, optionally, if you want it to move through blocks, then in the .json file set tileCollide to false.
I don't really know any mods that were made to be editable, and the template mod seems like the best thing for copy/paste stuff. However, all .tapi files are actually compressed files that can be extracted; so you can download any mod you want then look at its source code.
 
Thank you so much! How can I Extract files? I have just started modding, I'm kind of a noob... Do you mind if I ask more questions? How can I make a weapon that shoots only in 8 directions? If you find my questions annoying, just tell me and I will stop. Thank you!
 
Thank you so much! How can I Extract files? I have just started modding, I'm kind of a noob... Do you mind if I ask more questions? How can I make a weapon that shoots only in 8 directions? If you find my questions annoying, just tell me and I will stop. Thank you!
Personally, I use this program called 7zip to open .tapi files. It lets you open them, and you're able to copy the contents to a location outside the file.
For that weapon, do you mean it shoots in 8 directions at once, or you can only shoot it in 8 specific directions?
 
Personally, I use this program called 7zip to open .tapi files. It lets you open them, and you're able to copy the contents to a location outside the file.
For that weapon, do you mean it shoots in 8 directions at once, or you can only shoot it in 8 specific directions?
Only in 8 specific directions.
 
Only in 8 specific directions.

I have an idea on how to do that, it would have to be a lot of if statements within the PreShoot() method within the item's .cs. But I have no idea if it would work. This is what I would imagine it to look like. Note: this is just an example.

Code:
public override bool PreShoot(Player player, Vector2 position, Vector2 velocity, int type, int damage, float knockback)
        {
            if(velocity.X > 0 && velocity.Y > 0 && velocity.Y < 4)
            {
                Projectile.newProjectile(velocity.X, 0, position.X, position.Y, type, damage, knockback, Main.myPlayer)
            }
            else if(velocity.X > 0 && velocity.X < 4 && velocity.Y > 0)
            {
                Projectile.newProjectile(0, velocity.Y, position.X, position.Y, type, damage, knockback, Main.myPlayer)
            }
            //etc
            return false;
        }
 
Only in 8 specific directions.
You'd override the item's PreShoot method, like the person above said. This sounds like a fun and short puzzle, so I'll just make this code. I imagine it would go something like this:
Code:
public override bool PreShoot(Player player, Vector2 position, Vector2 velocity, int type, int damage, float knockback)
{
    float magnitude = (float)Math.Sqrt(velocity.X * velocity.X + velocity.Y * velocity.Y); //Pythagorean theorem to get the speed
    float rotation = Math.Atan2(velocity.Y, velocity.X); //gets the theta coordinate of the velocity's polar coordinates, aka angle in radians
    float direction = rotation * 4f / (float)Math.PI; //there are 8 directions, so we want this to range from 0 to 8
    float newRotation = (float)Math.Round(direction) / 4f * (float)Math.PI; //convert to a specific direction
    velocity.X = (float)Math.Cos(newRotation) * magnitude; //converting polar coordinates to Cartesian coordinates
    velocity.Y = (float)Math.Sin(newRotation) * magnitude; //same thing
    Projectile.NewProjectile(position.X, position.Y, velocity.X, velocity.Y, type, damage, knockback, Main.myPlayer); //finally create the projectile
    return false; //we already created the projectile, so the game doesn't need to do it for us
}
 
I have an idea on how to do that, it would have to be a lot of if statements within the PreShoot() method within the item's .cs. But I have no idea if it would work. This is what I would imagine it to look like. Note: this is just an example.

Code:
public override bool PreShoot(Player player, Vector2 position, Vector2 velocity, int type, int damage, float knockback)
        {
            if(velocity.X > 0 && velocity.Y > 0 && velocity.Y < 4)
            {
                Projectile.newProjectile(velocity.X, 0, position.X, position.Y, type, damage, knockback, Main.myPlayer)
            }
            else if(velocity.X > 0 && velocity.X < 4 && velocity.Y > 0)
            {
                Projectile.newProjectile(0, velocity.Y, position.X, position.Y, type, damage, knockback, Main.myPlayer)
            }
            //etc
            return false;
        }
You'd override the item's PreShoot method, like the person above said. This sounds like a fun and short puzzle, so I'll just make this code. I imagine it would go something like this:
Code:
public override bool PreShoot(Player player, Vector2 position, Vector2 velocity, int type, int damage, float knockback)
{
    float magnitude = (float)Math.Sqrt(velocity.X * velocity.X + velocity.Y * velocity.Y); //Pythagorean theorem to get the speed
    float rotation = Math.Atan2(velocity.Y, velocity.X); //gets the theta coordinate of the velocity's polar coordinates, aka angle in radians
    float direction = rotation * 4f / (float)Math.PI; //there are 8 directions, so we want this to range from 0 to 8
    float newRotation = (float)Math.Round(direction) / 4f * (float)Math.PI; //convert to a specific direction
    velocity.X = (float)Math.Cos(newRotation) * magnitude; //converting polar coordinates to Cartesian coordinates
    velocity.Y = (float)Math.Sin(newRotation) * magnitude; //same thing
    Projectile.NewProjectile(position.X, position.Y, velocity.X, velocity.Y, type, damage, knockback, Main.myPlayer); //finally create the projectile
    return false; //we already created the projectile, so the game doesn't need to do it for us
}
[DOUBLEPOST=1425287717][/DOUBLEPOST]
I have an idea on how to do that, it would have to be a lot of if statements within the PreShoot() method within the item's .cs. But I have no idea if it would work. This is what I would imagine it to look like. Note: this is just an example.

Code:
public override bool PreShoot(Player player, Vector2 position, Vector2 velocity, int type, int damage, float knockback)
        {
            if(velocity.X > 0 && velocity.Y > 0 && velocity.Y < 4)
            {
                Projectile.newProjectile(velocity.X, 0, position.X, position.Y, type, damage, knockback, Main.myPlayer)
            }
            else if(velocity.X > 0 && velocity.X < 4 && velocity.Y > 0)
            {
                Projectile.newProjectile(0, velocity.Y, position.X, position.Y, type, damage, knockback, Main.myPlayer)
            }
            //etc
            return false;
        }
Thank you! Can the same thing be done with only allowing shooting forwards?(left or right)
[DOUBLEPOST=1425287816][/DOUBLEPOST]What did I just do? I have no idea who I replied to... I hope I did to both...
 
[DOUBLEPOST=1425287717][/DOUBLEPOST]Thank you! Can the same thing be done with only allowing shooting forwards?(left or right)
[DOUBLEPOST=1425287816][/DOUBLEPOST]What did I just do? I have no idea who I replied to... I hope I did to both...
Shooting only left or right is even easier. Instead of messing with all the angle stuff, just check whether velocity.X is positive or negative, like this:
Code:
public override bool PreShoot(Player player, Vector2 position, Vector2 velocity, int type, int damage, float knockback)
{
    float magnitude = (float)Math.Sqrt(velocity.X * velocity.X + velocity.Y * velocity.Y);
    float direction = 1f; //shoot to the right
    if(velocity.X < 0f)
    {
        direction = -1f; //shoot to the left
    }
    velocity.X = direction * magnitude;
    velocity.Y = 0f; //so it only goes straight to the left or right
    Projectile.NewProjectile(position.X, position.Y, velocity.X, velocity.Y, type, damage, knockback, Main.myPlayer);
    return false;
}
 
Shooting only left or right is even easier. Instead of messing with all the angle stuff, just check whether velocity.X is positive or negative, like this:
Code:
public override bool PreShoot(Player player, Vector2 position, Vector2 velocity, int type, int damage, float knockback)
{
    float magnitude = (float)Math.Sqrt(velocity.X * velocity.X + velocity.Y * velocity.Y);
    float direction = 1f; //shoot to the right
    if(velocity.X < 0f)
    {
        direction = -1f; //shoot to the left
    }
    velocity.X = direction * magnitude;
    velocity.Y = 0f; //so it only goes straight to the left or right
    Projectile.NewProjectile(position.X, position.Y, velocity.X, velocity.Y, type, damage, knockback, Main.myPlayer);
    return false;
}
Thank you! Yeah, it is possible to make the AI of a projectile change when it has traveled enough distance or hits a wall?
 
Thank you! Yeah, it is possible to make the AI of a projectile change when it has traveled enough distance or hits a wall?

Well, yes, you can do that with the PostKill() method and just make another projectile once the main one has "died". But in all seriousness, I highly suggest instead of asking about projectile information here in the tutorial for Custom NPC AI, why not ask in forums like [Tutorial] Projecile Guide and Implementation or Getting Started with Modding?
 
Did you know if it's possible to make ore generate if a boss die or trigger a new mode after hardmode (like the WoF)
 
Back
Top Bottom