Standalone [1.3] tModLoader - A Modding API

Hey @TheTerrarianJS, please use the Edit button when you have more to say; double posting is against the rules here, and results in ugly merged posts. You can just edit in the additional thoughts as many times as you like. :)
 
My projectile being shot by an enemy after it gets hurt goes only in a certain direction. How can I make it aim at the player?
@bluemagic123
Well, the method signature is:
Code:
public static int NewProjectile(float X, float Y, float SpeedX, float SpeedY, int Type, int Damage, float KnockBack, int Owner = 255, float ai0 = 0f, float ai1 = 0f)
so you need to set SpeedX and SpeedY appropriately in order to have the projectile aim towards the player.
Here is how it is done in one instance:
Code:
Vector2 playerCenter = Main.player[npc.target].Center;
Vector2 npcCenter = npc.Center;
Vector2 vectorFromNPCtoPlayer = playerCenter - npcCenter;
vectorFromNPCtoPlayer.Normalize();
if (float.IsNaN(vectorFromNPCtoPlayer.X) || float.IsNaN(vectorFromNPCtoPlayer.Y))
{
     vectorFromNPCtoPlayer = -Vector2.UnitY;
}
vectorFromNPCtoPlayer *= 7f;
Projectile.NewProjectile(npcCenter.X, npcCenter.Y, vectorFromNPCtoPlayer.X, vectorFromNPCtoPlayer.Y, projectileType, projectileDamage, 0f, Main.myPlayer, 0f, 0f);
If you are interested in actually acquiring the player target, use "npc.TargetClosest(true);"
 
I need it to split into smaller projectiles and be homing. Like the scourge of the corrupter's projectile
Splitting is easy. Note that you need two projectiles. In the Kill method of ProjectileA, loop a few times and spawn a number of ProjectileBs, like so:
Code:
                for (int i = 0; i < 4; i++)
                {
                    Projectile.NewProjectile(projectile.position.X, projectile.position.Y, (float)Main.rand.Next(-35, 36) * 0.2f, (float)Main.rand.Next(-35, 36) * 0.2f, mod.ProjectileType("VampireScourgeProjectileB")/*307*/, (int)((double)projectile.damage * 0.7), (float)((int)((double)projectile.knockBack * 0.35)), Main.myPlayer, 0f, 0f);
                }
Homing is a bit harder. Basically you iterate over all 200 NPC slots in Main.npc[], find the closest one, and nudge the particle in that direction. The code is pretty complicated.....I've attached an item that is an exact replica of Scourge of the Corrupter except for an added Vampireheal ability. Look at VampireScourgeProjectileB.cs to see how the homing is done.
 

Attachments

  • VampireScourge.zip
    6 KB · Views: 262
Alright - this is complicated, so I need your help @bluemagic123 or @jopojelly .

I am designing a boss called the Void Hydra. I wanted the 3 heads to act like a Man Eater, but attached to the body instead of a block. They would fire projectiles at different times. As for the base, it would look like a hand, crawling around but jumping to reach the player. It can go through blocks, and when you kill all 3 heads, a middle head spawns on top of the boss and fires projectiles in a practical beam in short intervals.

...You can see why I need some help.


EDIT: @jopojelly (or anybody else) You seem to have the AI code for many vanilla NPCs... Do you have the code for The Hungry?
 
Last edited:
Alright - this is complicated, so I need your help @bluemagic123 or @jopojelly .

I am designing a boss called the Void Hydra. I wanted the 3 heads to act like a Man Eater, but attached to the body instead of a block. They would fire projectiles at different times. As for the base, it would look like a hand, crawling around but jumping to reach the player. It can go through blocks, and when you kill all 3 heads, a middle head spawns on top of the boss and fires projectiles in a practical beam in short intervals.

...You can see why I need some help.
AI number 29: The Hungry AI - Similar to the Plant AI, but attached to an entity.

You might start looking from there on in the AI of the vanilla monsters? Just a suggestion, though.
 
AI number 29: The Hungry AI - Similar to the Plant AI, but attached to an entity.

You might start looking from there on in the AI of the vanilla monsters? Just a suggestion, though.
Yes - but the AI of the Hungry automatically connects itself to the Wall of Flesh. I tried that and it caused a massive lag due to the world long texture.
 
Alright - this is complicated, so I need your help @bluemagic123 or @jopojelly .

I am designing a boss called the Void Hydra. I wanted the 3 heads to act like a Man Eater, but attached to the body instead of a block. They would fire projectiles at different times. As for the base, it would look like a hand, crawling around but jumping to reach the player. It can go through blocks, and when you kill all 3 heads, a middle head spawns on top of the boss and fires projectiles in a practical beam in short intervals.

...You can see why I need some help.
And that is why it is highly recommended to be familiar with programming in order to mod :p
 
Ok - tried to spawn it - nothing happened. Ai style was 29.
That won't work because it will die if WOF isn't around.

If you are trying to make something as ambitious as a boss, I would definitely recommend decompiling Terraria on your computer and using it as reference. (use ILSpy I guess) I've never done any bosses and I wouldn't even dare unless I had the decompiled code to glean from. Also, Visual Studios is a must. I'm not sure about how much programming experience you have, but if you make the sprites and create a design document detailing how it behaves and such, I'd bet you might be able to recruit some help from someone on this forum if you posted here in the WIP section. Maybe.

In the meantime, here is some hungry AI, I'll leave it to you to figure it out, but I bet if you modified this you could have this npc move along with the body/hand npc. (look at the mounted NPC code i posted earlier maybe?) Note that there is undoubtedly more code needed for drawing the chain texture or some other stuff, but that is nothing to worry about yet.

If you make more progress and get stuck, I could help, but decompiling Terraria yourself is the best option. Best learning experience too.

Code:
else if (this.aiStyle == 29)
                    {
                        if (this.justHit)
                        {
                            this.ai[1] = 10f;
                        }
                        if (Main.wof < 0)
                        {
                            this.active = false;
                            return;
                        }
                        this.TargetClosest(true);
                        float num790 = 0.1f;
                        float num791 = 300f;
                        if ((double)Main.npc[Main.wof].life < (double)Main.npc[Main.wof].lifeMax * 0.25)
                        {
                            this.damage = (int)(75f * Main.damageMultiplier);
                            this.defense = 40;
                            if (!Main.expertMode)
                            {
                                num791 = 900f;
                            }
                            else
                            {
                                num790 += 0.1f;
                            }
                        }
                        else if ((double)Main.npc[Main.wof].life < (double)Main.npc[Main.wof].lifeMax * 0.5)
                        {
                            this.damage = (int)(60f * Main.damageMultiplier);
                            this.defense = 30;
                            if (!Main.expertMode)
                            {
                                num791 = 700f;
                            }
                            else
                            {
                                num790 += 0.066f;
                            }
                        }
                        else if ((double)Main.npc[Main.wof].life < (double)Main.npc[Main.wof].lifeMax * 0.75)
                        {
                            this.damage = (int)(45f * Main.damageMultiplier);
                            this.defense = 20;
                            if (!Main.expertMode)
                            {
                                num791 = 500f;
                            }
                            else
                            {
                                num790 += 0.033f;
                            }
                        }
                        if (Main.expertMode)
                        {
                            this.defense = this.defDefense;
                            if (this.whoAmI % 4 == 0)
                            {
                                num791 *= 1.75f;
                            }
                            if (this.whoAmI % 4 == 1)
                            {
                                num791 *= 1.5f;
                            }
                            if (this.whoAmI % 4 == 2)
                            {
                                num791 *= 1.25f;
                            }
                            if (this.whoAmI % 3 == 0)
                            {
                                num791 *= 1.5f;
                            }
                            if (this.whoAmI % 3 == 1)
                            {
                                num791 *= 1.25f;
                            }
                            num791 *= 0.75f;
                        }
                        float num792 = Main.npc[Main.wof].position.X + (float)(Main.npc[Main.wof].width / 2);
                        float num793 = Main.npc[Main.wof].position.Y;
                        float num794 = (float)(Main.wofB - Main.wofT);
                        num793 = (float)Main.wofT + num794 * this.ai[0];
                        this.ai[2] += 1f;
                        if (this.ai[2] > 100f)
                        {
                            num791 = (float)((int)(num791 * 1.3f));
                            if (this.ai[2] > 200f)
                            {
                                this.ai[2] = 0f;
                            }
                        }
                        Vector2 vector79 = new Vector2(num792, num793);
                        float num795 = Main.player[this.target].position.X + (float)(Main.player[this.target].width / 2) - (float)(this.width / 2) - vector79.X;
                        float num796 = Main.player[this.target].position.Y + (float)(Main.player[this.target].height / 2) - (float)(this.height / 2) - vector79.Y;
                        float num797 = (float)Math.Sqrt((double)(num795 * num795 + num796 * num796));
                        if (this.ai[1] == 0f)
                        {
                            if (num797 > num791)
                            {
                                num797 = num791 / num797;
                                num795 *= num797;
                                num796 *= num797;
                            }
                            if (this.position.X < num792 + num795)
                            {
                                this.velocity.X = this.velocity.X + num790;
                                if (this.velocity.X < 0f && num795 > 0f)
                                {
                                    this.velocity.X = this.velocity.X + num790 * 2.5f;
                                }
                            }
                            else if (this.position.X > num792 + num795)
                            {
                                this.velocity.X = this.velocity.X - num790;
                                if (this.velocity.X > 0f && num795 < 0f)
                                {
                                    this.velocity.X = this.velocity.X - num790 * 2.5f;
                                }
                            }
                            if (this.position.Y < num793 + num796)
                            {
                                this.velocity.Y = this.velocity.Y + num790;
                                if (this.velocity.Y < 0f && num796 > 0f)
                                {
                                    this.velocity.Y = this.velocity.Y + num790 * 2.5f;
                                }
                            }
                            else if (this.position.Y > num793 + num796)
                            {
                                this.velocity.Y = this.velocity.Y - num790;
                                if (this.velocity.Y > 0f && num796 < 0f)
                                {
                                    this.velocity.Y = this.velocity.Y - num790 * 2.5f;
                                }
                            }
                            float num798 = 4f;
                            if (Main.expertMode && Main.wof >= 0)
                            {
                                float num799 = 1.5f;
                                float num800 = (float)(Main.npc[Main.wof].life / Main.npc[Main.wof].lifeMax);
                                if ((double)num800 < 0.75)
                                {
                                    num799 += 0.7f;
                                }
                                if ((double)num800 < 0.5)
                                {
                                    num799 += 0.7f;
                                }
                                if ((double)num800 < 0.25)
                                {
                                    num799 += 0.9f;
                                }
                                if ((double)num800 < 0.1)
                                {
                                    num799 += 0.9f;
                                }
                                num799 *= 1.25f;
                                num799 += 0.3f;
                                num798 += num799 * 0.35f;
                                if (base.Center.X < Main.npc[Main.wof].Center.X && Main.npc[Main.wof].velocity.X > 0f)
                                {
                                    num798 += 6f;
                                }
                                if (base.Center.X > Main.npc[Main.wof].Center.X && Main.npc[Main.wof].velocity.X < 0f)
                                {
                                    num798 += 6f;
                                }
                            }
                            if (this.velocity.X > num798)
                            {
                                this.velocity.X = num798;
                            }
                            if (this.velocity.X < -num798)
                            {
                                this.velocity.X = -num798;
                            }
                            if (this.velocity.Y > num798)
                            {
                                this.velocity.Y = num798;
                            }
                            if (this.velocity.Y < -num798)
                            {
                                this.velocity.Y = -num798;
                            }
                        }
                        else if (this.ai[1] > 0f)
                        {
                            this.ai[1] -= 1f;
                        }
                        else
                        {
                            this.ai[1] = 0f;
                        }
                        if (num795 > 0f)
                        {
                            this.spriteDirection = 1;
                            this.rotation = (float)Math.Atan2((double)num796, (double)num795);
                        }
                        if (num795 < 0f)
                        {
                            this.spriteDirection = -1;
                            this.rotation = (float)Math.Atan2((double)num796, (double)num795) + 3.14f;
                        }
                        Lighting.AddLight((int)(this.position.X + (float)(this.width / 2)) / 16, (int)(this.position.Y + (float)(this.height / 2)) / 16, 0.3f, 0.2f, 0.1f);
                        return;
                    }
 
Guys it works

mpSa5hn.png

How do I add extra items to a vanilla NPC's shop?
https://github.com/bluemagic123/tMo...setupshopint-type-chest-shop-ref-int-nextslot
 
Allright, I've got a question... Hope someone can help. I'm making a custom boss, which shoots projectiles at the player. There is a bug, though. The boss has some sort of blindspot.

EDIT: (removed the picture and code so less room is taken)
Allright, so it seems the bug was not in my piece of code, but in the projectile that was fired... Strange, cause it was a vanilla projectile... Anyway, I know the problem so fixed it!
 
Last edited:
I dont know which file im supposed to copy into the Vanilla folder so i did the one in documents and my local disk. Which one was i supposed to use?
[DOUBLEPOST=1442454218,1442454179][/DOUBLEPOST]I dont know which file im supposed to copy into the Vanilla folder so i did the one in documents and my local disk. Which one was i supposed to use?
 
I dont know which file im supposed to copy into the Vanilla folder so i did the one in documents and my local disk. Which one was i supposed to use?
[DOUBLEPOST=1442454218,1442454179][/DOUBLEPOST]I dont know which file im supposed to copy into the Vanilla folder so i did the one in documents and my local disk. Which one was i supposed to use?
Go to your steam library then right click steam then you will click properties and find the "open file location" button and press it. You will find it there.
 
Dang... im not able to open the batch file. I need help, every time i open it the window closes immediently
[DOUBLEPOST=1442455427,1442455390][/DOUBLEPOST]How do i fix this?
 
Back
Top Bottom