Help With Custom Town NPCs

Try to copy the entire source code of the mod you want to port and then use tModPorter, and fix the remaining errors manually
I'm just going to make a brand-new mod with the textures from the old mod and start making the npc with the exampleperson.cs
Can you help me with code errors still?
 
Here's the errors:
1660150440942.png

1660150462800.png

1660150484990.png

1660150515796.png

I'm pretty sure I messed up something before this for the shop and it caused this but i don't know how to fix this.
 
can you post the whole code as text?
This is the .cs of the town npc's code:

using Microsoft.Xna.Framework;
using System;
using System.Linq;
using Terraria;
using Terraria.Audio;
using Terraria.ID;
using Terraria.Localization;
using Terraria.ModLoader;
using Terraria.Utilities;
using Terraria.GameContent.Bestiary;
using Terraria.GameContent.ItemDropRules;
using Microsoft.Xna.Framework.Graphics;
using Terraria.GameContent;
using Terraria.GameContent.Personalities;
using Terraria.DataStructures;
using System.Collections.Generic;
using ReLogic.Content;
using Terraria.ModLoader.IO;

namespace ExampleMod.Content.NPCs
{
// [AutoloadHead] and NPC.townNPC are extremely important and absolutely both necessary for any Town NPC to work at all.
[AutoloadHead]
public class ExamplePerson : ModNPC
{
public int NumberOfTimesTalkedTo = 0;

public override void SetStaticDefaults()
{
// DisplayName automatically assigned from localization files, but the commented line below is the normal approach.
// DisplayName.SetDefault("Example Person");
Main.npcFrameCount[Type] = 25; // The amount of frames the NPC has

NPCID.Sets.ExtraFramesCount[Type] = 9; // Generally for Town NPCs, but this is how the NPC does extra things such as sitting in a chair and talking to other NPCs.
NPCID.Sets.AttackFrameCount[Type] = 4;
NPCID.Sets.DangerDetectRange[Type] = 700; // The amount of pixels away from the center of the npc that it tries to attack enemies.
NPCID.Sets.AttackType[Type] = 0;
NPCID.Sets.AttackTime[Type] = 90; // The amount of time it takes for the NPC's attack animation to be over once it starts.
NPCID.Sets.AttackAverageChance[Type] = 30;
NPCID.Sets.HatOffsetY[Type] = 4; // For when a party is active, the party hat spawns at a Y offset.

// Influences how the NPC looks in the Bestiary
NPCID.Sets.NPCBestiaryDrawModifiers drawModifiers = new NPCID.Sets.NPCBestiaryDrawModifiers(0)
{
Velocity = 1f, // Draws the NPC in the bestiary as if its walking +1 tiles in the x direction
Direction = -1 // -1 is left and 1 is right. NPCs are drawn facing the left by default but ExamplePerson will be drawn facing the right
// Rotation = MathHelper.ToRadians(180) // You can also change the rotation of an NPC. Rotation is measured in radians
// If you want to see an example of manually modifying these when the NPC is drawn, see PreDraw
};

NPCID.Sets.NPCBestiaryDrawOffset.Add(Type, drawModifiers);

// Set Example Person's biome and neighbor preferences with the NPCHappiness hook. You can add happiness text and remarks with localization (See an example in ExampleMod/Localization/en-US.lang).
// NOTE: The following code uses chaining - a style that works due to the fact that the SetXAffection methods return the same NPCHappiness instance they're called on.
NPC.Happiness
.SetBiomeAffection<HallowBiome>(AffectionLevel.Love) // Example Person prefers the forest.
.SetBiomeAffection<ForestBiome>(AffectionLevel.Love)
.SetBiomeAffection<DesertBiome>(AffectionLevel.Like)
.SetBiomeAffection<SnowBiome>(AffectionLevel.Like)
.SetBiomeAffection<UndergroundBiome>(AffectionLevel.Dislike) // Example Person likes the snow.
.SetNPCAffection(NPCID.Truffle, AffectionLevel.Like) // Loves living near the dryad.
.SetNPCAffection(NPCID.Guide, AffectionLevel.Like) // Likes living near the guide.
.SetNPCAffection(NPCID.Wizard, AffectionLevel.Like) // Dislikes living near the merchant.
.SetNPCAffection(NPCID.PartyGirl, AffectionLevel.Like) // Dislikes living near the merchant.
.SetNPCAffection(NPCID.GoblinTinkerer, AffectionLevel.Dislike) // Dislikes living near the merchant.
.SetNPCAffection(NPCID.TaxCollector, AffectionLevel.Hate) // Hates living near the demolitionist.
; // < Mind the semicolon!
}

public override void SetDefaults()
{
NPC.townNPC = true; // Sets NPC to be a Town NPC
NPC.friendly = true; // NPC Will not attack player
NPC.width = 18;
NPC.height = 40;
NPC.aiStyle = 7;
NPC.damage = 10;
NPC.defense = 15;
NPC.lifeMax = 250;
NPC.HitSound = SoundID.NPCHit1;
NPC.DeathSound = SoundID.NPCDeath1;
NPC.knockBackResist = 0.5f;

AnimationType = NPCID.Guide;
}

public override void SetBestiary(BestiaryDatabase database, BestiaryEntry bestiaryEntry)
{
// We can use AddRange instead of calling Add multiple times in order to add multiple items at once
bestiaryEntry.Info.AddRange(new IBestiaryInfoElement[] {
// Sets the preferred biomes of this town NPC listed in the bestiary.
// With Town NPCs, you usually set this to what biome it likes the most in regards to NPC happiness.
BestiaryDatabaseNPCsPopulator.CommonTags.SpawnConditions.Biomes.TheHallow,

// Sets your NPC's flavor text in the bestiary.
new FlavorTextBestiaryInfoElement("Did you want some lamp- I mean torches? Rope? Bombs? It's all your's, my friend, because this guy has it."),

// You can add multiple elements if you really wanted to
// You can also use localization keys (see Localization/en-US.lang)
new FlavorTextBestiaryInfoElement("Mods.NPCMorshu.Bestiary.RubyMerchant")
});
}

// The PreDraw hook is useful for drawing things before our sprite is drawn or running code before the sprite is drawn
// Returning false will allow you to manually draw your NPC
public override bool PreDraw(SpriteBatch spriteBatch, Vector2 screenPos, Color drawColor)
{
// This code slowly rotates the NPC in the bestiary
// (simply checking NPC.IsABestiaryIconDummy and incrementing NPC.Rotation won't work here as it gets overridden by drawModifiers.Rotation each tick)
if (NPCID.Sets.NPCBestiaryDrawOffset.TryGetValue(Type, out NPCID.Sets.NPCBestiaryDrawModifiers drawModifiers))
{
drawModifiers.Rotation += 0.001f;

// Replace the existing NPCBestiaryDrawModifiers with our new one with an adjusted rotation
NPCID.Sets.NPCBestiaryDrawOffset.Remove(Type);
NPCID.Sets.NPCBestiaryDrawOffset.Add(Type, drawModifiers);
}

return true;
}

public override void HitEffect(int hitDirection, double damage)
{
int num = NPC.life > 0 ? 1 : 5;

for (int k = 0; k < num; k++)
{
Dust.NewDust(NPC.position, NPC.width, NPC.height, (DustID.Blood));
}
}

public override bool CanTownNPCSpawn(int numTownNPCs, int money)
{ // Requirements for the town NPC to spawn.
for (int k = 0; k < 255; k++)
{
Player player = Main.player[k];
if (!player.active)
{
continue;
}

// Player has to have either an ExampleItem or an ExampleBlock in order for the NPC to spawn
if (player.inventory.Any(item => item.type == (ItemID.Ruby) || item.type == (ItemID.LargeRuby)))
{
return true;
}
}

return false;
}


public override ITownNPCProfile TownNPCProfile()
{
return new ExamplePersonProfile();
}

public override List<string> SetNPCNameList()
{
return new List<string>() {
"Morshu"
};
}

public override void FindFrame(int frameHeight)
{
/*npc.frame.Width = 40;
if (((int)Main.time / 10) % 2 == 0)
{
npc.frame.X = 40;
}
else
{
npc.frame.X = 0;
}*/
}

public override string GetChat()
{
WeightedRandom<string> chat = new WeightedRandom<string>();

int partyGirl = NPC.FindFirstNPC(NPCID.PartyGirl);
if (partyGirl >= 0 && Main.rand.NextBool(4))
{
chat.Add(Language.GetTextValue("Mods.ExampleMod.Dialogue.ExamplePerson.PartyGirlDialogue", Main.npc[partyGirl].GivenName));
}
// These are things that the NPC has a chance of telling you when you talk to it.
chat.Add(Language.GetTextValue("Mods.ExampleMod.Dialogue.ExamplePerson.StandardDialogue1"));
chat.Add(Language.GetTextValue("Mods.ExampleMod.Dialogue.ExamplePerson.StandardDialogue2"));
chat.Add(Language.GetTextValue("Mods.ExampleMod.Dialogue.ExamplePerson.StandardDialogue3"));
chat.Add(Language.GetTextValue("Mods.ExampleMod.Dialogue.ExamplePerson.CommonDialogue"), 5.0);
chat.Add(Language.GetTextValue("Mods.ExampleMod.Dialogue.ExamplePerson.RareDialogue"), 0.1);

NumberOfTimesTalkedTo++;
if (NumberOfTimesTalkedTo >= 10)
{
//This counter is linked to a single instance of the NPC, so if ExamplePerson is killed, the counter will reset.
chat.Add(Language.GetTextValue("Mods.ExampleMod.Dialogue.ExamplePerson.TalkALot"));
}

return chat; // chat is implicitly cast to a string.
}

public override void SetChatButtons(ref string button, ref string button2)
{ // What the chat buttons are when you open up the chat UI
button = Language.GetTextValue("LegacyInterface.28");

}
}


// Not completely finished, but below is what the NPC will sell

public override void SetupShop(Chest shop, ref int nextSlot)
{
shop.item[nextSlot++].SetDefaults(ItemID.Torch);
shop.item[nextSlot++].SetDefaults(ItemID.Rope);
shop.item[nextSlot++].SetDefaults(ItemID.Bomb);
shop.item[nextSlot++].SetDefaults(ItemID.RopeCoil);
shop.item[nextSlot++].SetDefaults(ItemID.DirtBomb);
shop.item[nextSlot++].SetDefaults(ItemID.Ruby);
shop.item[nextSlot++].SetDefaults(ItemID.Topaz);
shop.item[nextSlot++].SetDefaults(ItemID.Diamond);
shop.item[nextSlot++].SetDefaults(ItemID.Amethyst);
shop.item[nextSlot++].SetDefaults(ItemID.Emerald);
shop.item[nextSlot++].SetDefaults(ItemID.Amber);
shop.item[nextSlot++].SetDefaults(ItemID.Sapphire);
shop.item[nextSlot++].SetDefaults(ItemID.LargeRuby);
}
//
// if (Main.LocalPlayer.HasBuff(BuffID.Lifeforce)) {
// shop.item[nextSlot++].SetDefaults(ItemType<ExampleHealingPotion>());
// }
//
// // if (Main.LocalPlayer.GetModPlayer<ExamplePlayer>().ZoneExample && !GetInstance<ExampleConfigServer>().DisableExampleWings) {
// // shop.item[nextSlot].SetDefaults(ItemType<ExampleWings>());
// // nextSlot++;
// // }
//
// if (Main.moonPhase < 2) {
// shop.item[nextSlot++].SetDefaults(ItemType<ExampleSword>());
// }
// else if (Main.moonPhase < 4) {
// // shop.item[nextSlot++].SetDefaults(ItemType<ExampleGun>());
// shop.item[nextSlot].SetDefaults(ItemType<ExampleBullet>());
// }
// else if (Main.moonPhase < 6) {
// // shop.item[nextSlot++].SetDefaults(ItemType<ExampleStaff>());
// }
//
// // todo: Here is an example of how your npc can sell items from other mods.
// // var modSummonersAssociation = ModLoader.TryGetMod("SummonersAssociation");
// // if (ModLoader.TryGetMod("SummonersAssociation", out Mod modSummonersAssociation)) {
// // shop.item[nextSlot].SetDefaults(modSummonersAssociation.ItemType("BloodTalisman"));
// // nextSlot++;
// // }
//
// // if (!Main.LocalPlayer.GetModPlayer<ExamplePlayer>().examplePersonGiftReceived && GetInstance<ExampleConfigServer>().ExamplePersonFreeGiftList != null) {
// // foreach (var item in GetInstance<ExampleConfigServer>().ExamplePersonFreeGiftList) {
// // if (Item.IsUnloaded) continue;
// // shop.item[nextSlot].SetDefaults(Item.Type);
// // shop.item[nextSlot].shopCustomPrice = 0;
// // shop.item[nextSlot].GetGlobalItem<ExampleInstancedGlobalItem>().examplePersonFreeGift = true;
// // nextSlot++;
// // //TODO: Have tModLoader handle index issues.
// // }
// // }
// }

public override void ModifyNPCLoot(NPCLoot npcLoot)
{
npcLoot.Add(ItemDropRule.Common(ItemID.BombFish));
}

// Make this Town NPC teleport to the King and/or Queen statue when triggered.
public override bool CanGoToStatue(bool toKingStatue) => true;

// Make something happen when the npc teleports to a statue. Since this method only runs server side, any visual effects like dusts or gores have to be synced across all clients manually.
public override void OnGoToStatue(bool toKingStatue)
{
if (Main.netMode == NetmodeID.Server)
{
ModPacket packet = Mod.GetPacket();
packet.Write((byte)ExampleMod.MessageType.ExampleTeleportToStatue);
packet.Write((byte)NPC.whoAmI);
packet.Send();
}
else
{
StatueTeleport();
}
}

// Create a square of pixels around the NPC on teleport.
public void StatueTeleport()
{
for (int i = 0; i < 30; i++)
{
Vector2 position = Main.rand.NextVector2Square(-20, 21);
if (Math.Abs(position.X) > Math.Abs(position.Y))
{
position.X = Math.Sign(position.X) * 20;
}
else
{
position.Y = Math.Sign(position.Y) * 20;
}

Dust.NewDustPerfect(NPC.Center + position, (DustID.ManaRegeneration), Vector2.Zero).noGravity = true;
}
}

public override void TownNPCAttackStrength(ref int damage, ref float knockback)
{
damage = 20;
knockback = 6f;
}

public override void TownNPCAttackCooldown(ref int cooldown, ref int randExtraCooldown)
{
cooldown = 30;
randExtraCooldown = 30;
}

// todo: implement
// public override void TownNPCAttackProj(ref int projType, ref int attackDelay) {
// projType = ProjectileType<SparklingBall>();
// attackDelay = 1;
// }

public override void TownNPCAttackProjSpeed(ref float multiplier, ref float gravityCorrection, ref float randomOffset)
{
multiplier = 12f;
randomOffset = 2f;
}

public override void LoadData(TagCompound tag)
{
NumberOfTimesTalkedTo = tag.GetInt("numberOfTimesTalkedTo");
}

public override void SaveData(TagCompound tag)
{
tag["numberOfTimesTalkedTo"] = NumberOfTimesTalkedTo;
}
}

public class ExamplePersonProfile : ITownNPCProfile
{
public int RollVariation() => 0;
public string GetNameForVariant(NPC npc) => npc.getNewNPCName();

public Asset<Texture2D> GetTextureNPCShouldUse(NPC npc)
{
if (npc.IsABestiaryIconDummy && !npc.ForcePartyHatOn)
return ModContent.Request<Texture2D>("NPCMorshu/Content/NPCs/RubyMerchant");

if (npc.altTexture == 1)
return ModContent.Request<Texture2D>("NPCMorshu/Content/NPCs/RubyMerchant_Party");

return ModContent.Request<Texture2D>("NPCMorshu/Content/NPCs/RubyMerchant");
}

public int GetHeadTextureIndex(NPC npc) => ModContent.GetModHeadSlot("NPCMorshu/Content/NPCs/RubyMerchant_Head");
}
}
 
C#:
using Microsoft.Xna.Framework;
using System;
using System.Linq;
using Terraria;
using Terraria.Audio;
using Terraria.ID;
using Terraria.Localization;
using Terraria.ModLoader;
using Terraria.Utilities;
using Terraria.GameContent.Bestiary;
using Terraria.GameContent.ItemDropRules;
using Microsoft.Xna.Framework.Graphics;
using Terraria.GameContent;
using Terraria.GameContent.Personalities;
using Terraria.DataStructures;
using System.Collections.Generic;
using ReLogic.Content;
using Terraria.ModLoader.IO;

namespace ExampleMod.Content.NPCs
{
    // [AutoloadHead] and NPC.townNPC are extremely important and absolutely both necessary for any Town NPC to work at all.
    [AutoloadHead]
    public class ExamplePerson : ModNPC
    {
        public int NumberOfTimesTalkedTo = 0;

        public override void SetStaticDefaults()
        {
            // DisplayName automatically assigned from localization files, but the commented line below is the normal approach.
            // DisplayName.SetDefault("Example Person");
            Main.npcFrameCount[Type] = 25; // The amount of frames the NPC has

            NPCID.Sets.ExtraFramesCount[Type] = 9; // Generally for Town NPCs, but this is how the NPC does extra things such as sitting in a chair and talking to other NPCs.
            NPCID.Sets.AttackFrameCount[Type] = 4;
            NPCID.Sets.DangerDetectRange[Type] = 700; // The amount of pixels away from the center of the npc that it tries to attack enemies.
            NPCID.Sets.AttackType[Type] = 0;
            NPCID.Sets.AttackTime[Type] = 90; // The amount of time it takes for the NPC's attack animation to be over once it starts.
            NPCID.Sets.AttackAverageChance[Type] = 30;
            NPCID.Sets.HatOffsetY[Type] = 4; // For when a party is active, the party hat spawns at a Y offset.

            // Influences how the NPC looks in the Bestiary
            NPCID.Sets.NPCBestiaryDrawModifiers drawModifiers = new NPCID.Sets.NPCBestiaryDrawModifiers(0)
            {
                Velocity = 1f, // Draws the NPC in the bestiary as if its walking +1 tiles in the x direction
                Direction = -1 // -1 is left and 1 is right. NPCs are drawn facing the left by default but ExamplePerson will be drawn facing the right
                               // Rotation = MathHelper.ToRadians(180) // You can also change the rotation of an NPC. Rotation is measured in radians
                               // If you want to see an example of manually modifying these when the NPC is drawn, see PreDraw
            };

            NPCID.Sets.NPCBestiaryDrawOffset.Add(Type, drawModifiers);

            // Set Example Person's biome and neighbor preferences with the NPCHappiness hook. You can add happiness text and remarks with localization (See an example in ExampleMod/Localization/en-US.lang).
            // NOTE: The following code uses chaining - a style that works due to the fact that the SetXAffection methods return the same NPCHappiness instance they're called on.
            NPC.Happiness
            .SetBiomeAffection<HallowBiome>(AffectionLevel.Love) // Example Person prefers the forest.
            .SetBiomeAffection<ForestBiome>(AffectionLevel.Love)
            .SetBiomeAffection<DesertBiome>(AffectionLevel.Like)
            .SetBiomeAffection<SnowBiome>(AffectionLevel.Like)
            .SetBiomeAffection<UndergroundBiome>(AffectionLevel.Dislike) // Example Person likes the snow.
            .SetNPCAffection(NPCID.Truffle, AffectionLevel.Like) // Loves living near the dryad.
            .SetNPCAffection(NPCID.Guide, AffectionLevel.Like) // Likes living near the guide.
            .SetNPCAffection(NPCID.Wizard, AffectionLevel.Like) // Dislikes living near the merchant.
            .SetNPCAffection(NPCID.PartyGirl, AffectionLevel.Like) // Dislikes living near the merchant.
            .SetNPCAffection(NPCID.GoblinTinkerer, AffectionLevel.Dislike) // Dislikes living near the merchant.
            .SetNPCAffection(NPCID.TaxCollector, AffectionLevel.Hate) // Hates living near the demolitionist.
            ; // < Mind the semicolon!
        }

        public override void SetDefaults()
        {
            NPC.townNPC = true; // Sets NPC to be a Town NPC
            NPC.friendly = true; // NPC Will not attack player
            NPC.width = 18;
            NPC.height = 40;
            NPC.aiStyle = 7;
            NPC.damage = 10;
            NPC.defense = 15;
            NPC.lifeMax = 250;
            NPC.HitSound = SoundID.NPCHit1;
            NPC.DeathSound = SoundID.NPCDeath1;
            NPC.knockBackResist = 0.5f;

            AnimationType = NPCID.Guide;
        }

        public override void SetBestiary(BestiaryDatabase database, BestiaryEntry bestiaryEntry)
        {
            // We can use AddRange instead of calling Add multiple times in order to add multiple items at once
            bestiaryEntry.Info.AddRange(new IBestiaryInfoElement[] {
// Sets the preferred biomes of this town NPC listed in the bestiary.
// With Town NPCs, you usually set this to what biome it likes the most in regards to NPC happiness.
BestiaryDatabaseNPCsPopulator.CommonTags.SpawnConditions.Biomes.TheHallow,

// Sets your NPC's flavor text in the bestiary.
new FlavorTextBestiaryInfoElement("Did you want some lamp- I mean torches? Rope? Bombs? It's all your's, my friend, because this guy has it."),

// You can add multiple elements if you really wanted to
// You can also use localization keys (see Localization/en-US.lang)
new FlavorTextBestiaryInfoElement("Mods.NPCMorshu.Bestiary.RubyMerchant")
});
        }

        // The PreDraw hook is useful for drawing things before our sprite is drawn or running code before the sprite is drawn
        // Returning false will allow you to manually draw your NPC
        public override bool PreDraw(SpriteBatch spriteBatch, Vector2 screenPos, Color drawColor)
        {
            // This code slowly rotates the NPC in the bestiary
            // (simply checking NPC.IsABestiaryIconDummy and incrementing NPC.Rotation won't work here as it gets overridden by drawModifiers.Rotation each tick)
            if (NPCID.Sets.NPCBestiaryDrawOffset.TryGetValue(Type, out NPCID.Sets.NPCBestiaryDrawModifiers drawModifiers))
            {
                drawModifiers.Rotation += 0.001f;

                // Replace the existing NPCBestiaryDrawModifiers with our new one with an adjusted rotation
                NPCID.Sets.NPCBestiaryDrawOffset.Remove(Type);
                NPCID.Sets.NPCBestiaryDrawOffset.Add(Type, drawModifiers);
            }

            return true;
        }

        public override void HitEffect(int hitDirection, double damage)
        {
            int num = NPC.life > 0 ? 1 : 5;

            for (int k = 0; k < num; k++)
            {
                Dust.NewDust(NPC.position, NPC.width, NPC.height, (DustID.Blood));
            }
        }

        public override bool CanTownNPCSpawn(int numTownNPCs, int money)
        { // Requirements for the town NPC to spawn.
            for (int k = 0; k < 255; k++)
            {
                Player player = Main.player[k];
                if (!player.active)
                {
                    continue;
                }

                // Player has to have either an ExampleItem or an ExampleBlock in order for the NPC to spawn
                if (player.inventory.Any(item => item.type == (ItemID.Ruby) || item.type == (ItemID.LargeRuby)))
                {
                    return true;
                }
            }

            return false;
        }


        public override ITownNPCProfile TownNPCProfile()
        {
            return new ExamplePersonProfile();
        }

        public override List<string> SetNPCNameList()
        {
            return new List<string>() {
"Morshu"
};
        }

        public override void FindFrame(int frameHeight)
        {
            /*npc.frame.Width = 40;
            if (((int)Main.time / 10) % 2 == 0)
            {
            npc.frame.X = 40;
            }
            else
            {
            npc.frame.X = 0;
            }*/
        }

        public override string GetChat()
        {
            WeightedRandom<string> chat = new WeightedRandom<string>();

            int partyGirl = NPC.FindFirstNPC(NPCID.PartyGirl);
            if (partyGirl >= 0 && Main.rand.NextBool(4))
            {
                chat.Add(Language.GetTextValue("Mods.ExampleMod.Dialogue.ExamplePerson.PartyGirlDialogue", Main.npc[partyGirl].GivenName));
            }
            // These are things that the NPC has a chance of telling you when you talk to it.
            chat.Add(Language.GetTextValue("Mods.ExampleMod.Dialogue.ExamplePerson.StandardDialogue1"));
            chat.Add(Language.GetTextValue("Mods.ExampleMod.Dialogue.ExamplePerson.StandardDialogue2"));
            chat.Add(Language.GetTextValue("Mods.ExampleMod.Dialogue.ExamplePerson.StandardDialogue3"));
            chat.Add(Language.GetTextValue("Mods.ExampleMod.Dialogue.ExamplePerson.CommonDialogue"), 5.0);
            chat.Add(Language.GetTextValue("Mods.ExampleMod.Dialogue.ExamplePerson.RareDialogue"), 0.1);

            NumberOfTimesTalkedTo++;
            if (NumberOfTimesTalkedTo >= 10)
            {
                //This counter is linked to a single instance of the NPC, so if ExamplePerson is killed, the counter will reset.
                chat.Add(Language.GetTextValue("Mods.ExampleMod.Dialogue.ExamplePerson.TalkALot"));
            }

            return chat; // chat is implicitly cast to a string.
        }

        public override void SetChatButtons(ref string button, ref string button2)
        { // What the chat buttons are when you open up the chat UI
            button = Language.GetTextValue("LegacyInterface.28");

        }
        // Not completely finished, but below is what the NPC will sell

        public override void SetupShop(Chest shop, ref int nextSlot)
        {
            shop.item[nextSlot++].SetDefaults(ItemID.Torch);
            shop.item[nextSlot++].SetDefaults(ItemID.Rope);
            shop.item[nextSlot++].SetDefaults(ItemID.Bomb);
            shop.item[nextSlot++].SetDefaults(ItemID.RopeCoil);
            shop.item[nextSlot++].SetDefaults(ItemID.DirtBomb);
            shop.item[nextSlot++].SetDefaults(ItemID.Ruby);
            shop.item[nextSlot++].SetDefaults(ItemID.Topaz);
            shop.item[nextSlot++].SetDefaults(ItemID.Diamond);
            shop.item[nextSlot++].SetDefaults(ItemID.Amethyst);
            shop.item[nextSlot++].SetDefaults(ItemID.Emerald);
            shop.item[nextSlot++].SetDefaults(ItemID.Amber);
            shop.item[nextSlot++].SetDefaults(ItemID.Sapphire);
            shop.item[nextSlot++].SetDefaults(ItemID.LargeRuby);
        }
        //
        // if (Main.LocalPlayer.HasBuff(BuffID.Lifeforce)) {
        // shop.item[nextSlot++].SetDefaults(ItemType<ExampleHealingPotion>());
        // }
        //
        // // if (Main.LocalPlayer.GetModPlayer<ExamplePlayer>().ZoneExample && !GetInstance<ExampleConfigServer>().DisableExampleWings) {
        // // shop.item[nextSlot].SetDefaults(ItemType<ExampleWings>());
        // // nextSlot++;
        // // }
        //
        // if (Main.moonPhase < 2) {
        // shop.item[nextSlot++].SetDefaults(ItemType<ExampleSword>());
        // }
        // else if (Main.moonPhase < 4) {
        // // shop.item[nextSlot++].SetDefaults(ItemType<ExampleGun>());
        // shop.item[nextSlot].SetDefaults(ItemType<ExampleBullet>());
        // }
        // else if (Main.moonPhase < 6) {
        // // shop.item[nextSlot++].SetDefaults(ItemType<ExampleStaff>());
        // }
        //
        // // todo: Here is an example of how your npc can sell items from other mods.
        // // var modSummonersAssociation = ModLoader.TryGetMod("SummonersAssociation");
        // // if (ModLoader.TryGetMod("SummonersAssociation", out Mod modSummonersAssociation)) {
        // // shop.item[nextSlot].SetDefaults(modSummonersAssociation.ItemType("BloodTalisman"));
        // // nextSlot++;
        // // }
        //
        // // if (!Main.LocalPlayer.GetModPlayer<ExamplePlayer>().examplePersonGiftReceived && GetInstance<ExampleConfigServer>().ExamplePersonFreeGiftList != null) {
        // // foreach (var item in GetInstance<ExampleConfigServer>().ExamplePersonFreeGiftList) {
        // // if (Item.IsUnloaded) continue;
        // // shop.item[nextSlot].SetDefaults(Item.Type);
        // // shop.item[nextSlot].shopCustomPrice = 0;
        // // shop.item[nextSlot].GetGlobalItem<ExampleInstancedGlobalItem>().examplePersonFreeGift = true;
        // // nextSlot++;
        // // //TODO: Have tModLoader handle index issues.
        // // }
        // // }
        // }

        public override void ModifyNPCLoot(NPCLoot npcLoot)
        {
            npcLoot.Add(ItemDropRule.Common(ItemID.BombFish));
        }

        // Make this Town NPC teleport to the King and/or Queen statue when triggered.
        public override bool CanGoToStatue(bool toKingStatue) => true;
        // Create a square of pixels around the NPC on teleport.
        public void StatueTeleport()
        {
            for (int i = 0; i < 30; i++)
            {
                Vector2 position = Main.rand.NextVector2Square(-20, 21);
                if (Math.Abs(position.X) > Math.Abs(position.Y))
                {
                    position.X = Math.Sign(position.X) * 20;
                }
                else
                {
                    position.Y = Math.Sign(position.Y) * 20;
                }

                Dust.NewDustPerfect(NPC.Center + position, (DustID.ManaRegeneration), Vector2.Zero).noGravity = true;
            }
        }

        public override void TownNPCAttackStrength(ref int damage, ref float knockback)
        {
            damage = 20;
            knockback = 6f;
        }

        public override void TownNPCAttackCooldown(ref int cooldown, ref int randExtraCooldown)
        {
            cooldown = 30;
            randExtraCooldown = 30;
        }

        // todo: implement
        // public override void TownNPCAttackProj(ref int projType, ref int attackDelay) {
        // projType = ProjectileType<SparklingBall>();
        // attackDelay = 1;
        // }

        public override void TownNPCAttackProjSpeed(ref float multiplier, ref float gravityCorrection, ref float randomOffset)
        {
            multiplier = 12f;
            randomOffset = 2f;
        }

        public override void LoadData(TagCompound tag)
        {
            NumberOfTimesTalkedTo = tag.GetInt("numberOfTimesTalkedTo");
        }

        public override void SaveData(TagCompound tag)
        {
            tag["numberOfTimesTalkedTo"] = NumberOfTimesTalkedTo;
        }
        public class ExamplePersonProfile : ITownNPCProfile
        {
            public int RollVariation() => 0;
            public string GetNameForVariant(NPC npc) => npc.getNewNPCName();

            public Asset<Texture2D> GetTextureNPCShouldUse(NPC npc)
            {
                if (npc.IsABestiaryIconDummy && !npc.ForcePartyHatOn)
                    return ModContent.Request<Texture2D>("NPCMorshu/Content/NPCs/RubyMerchant");

                if (npc.altTexture == 1)
                    return ModContent.Request<Texture2D>("NPCMorshu/Content/NPCs/RubyMerchant_Party");

                return ModContent.Request<Texture2D>("NPCMorshu/Content/NPCs/RubyMerchant");
            }

            public int GetHeadTextureIndex(NPC npc) => ModContent.GetModHeadSlot("NPCMorshu/Content/NPCs/RubyMerchant_Head");
        }
    }
}
Try to copy the code more carefully
 
C#:
using Microsoft.Xna.Framework;
using System;
using System.Linq;
using Terraria;
using Terraria.Audio;
using Terraria.ID;
using Terraria.Localization;
using Terraria.ModLoader;
using Terraria.Utilities;
using Terraria.GameContent.Bestiary;
using Terraria.GameContent.ItemDropRules;
using Microsoft.Xna.Framework.Graphics;
using Terraria.GameContent;
using Terraria.GameContent.Personalities;
using Terraria.DataStructures;
using System.Collections.Generic;
using ReLogic.Content;
using Terraria.ModLoader.IO;

namespace ExampleMod.Content.NPCs
{
    // [AutoloadHead] and NPC.townNPC are extremely important and absolutely both necessary for any Town NPC to work at all.
    [AutoloadHead]
    public class ExamplePerson : ModNPC
    {
        public int NumberOfTimesTalkedTo = 0;

        public override void SetStaticDefaults()
        {
            // DisplayName automatically assigned from localization files, but the commented line below is the normal approach.
            // DisplayName.SetDefault("Example Person");
            Main.npcFrameCount[Type] = 25; // The amount of frames the NPC has

            NPCID.Sets.ExtraFramesCount[Type] = 9; // Generally for Town NPCs, but this is how the NPC does extra things such as sitting in a chair and talking to other NPCs.
            NPCID.Sets.AttackFrameCount[Type] = 4;
            NPCID.Sets.DangerDetectRange[Type] = 700; // The amount of pixels away from the center of the npc that it tries to attack enemies.
            NPCID.Sets.AttackType[Type] = 0;
            NPCID.Sets.AttackTime[Type] = 90; // The amount of time it takes for the NPC's attack animation to be over once it starts.
            NPCID.Sets.AttackAverageChance[Type] = 30;
            NPCID.Sets.HatOffsetY[Type] = 4; // For when a party is active, the party hat spawns at a Y offset.

            // Influences how the NPC looks in the Bestiary
            NPCID.Sets.NPCBestiaryDrawModifiers drawModifiers = new NPCID.Sets.NPCBestiaryDrawModifiers(0)
            {
                Velocity = 1f, // Draws the NPC in the bestiary as if its walking +1 tiles in the x direction
                Direction = -1 // -1 is left and 1 is right. NPCs are drawn facing the left by default but ExamplePerson will be drawn facing the right
                               // Rotation = MathHelper.ToRadians(180) // You can also change the rotation of an NPC. Rotation is measured in radians
                               // If you want to see an example of manually modifying these when the NPC is drawn, see PreDraw
            };

            NPCID.Sets.NPCBestiaryDrawOffset.Add(Type, drawModifiers);

            // Set Example Person's biome and neighbor preferences with the NPCHappiness hook. You can add happiness text and remarks with localization (See an example in ExampleMod/Localization/en-US.lang).
            // NOTE: The following code uses chaining - a style that works due to the fact that the SetXAffection methods return the same NPCHappiness instance they're called on.
            NPC.Happiness
            .SetBiomeAffection<HallowBiome>(AffectionLevel.Love) // Example Person prefers the forest.
            .SetBiomeAffection<ForestBiome>(AffectionLevel.Love)
            .SetBiomeAffection<DesertBiome>(AffectionLevel.Like)
            .SetBiomeAffection<SnowBiome>(AffectionLevel.Like)
            .SetBiomeAffection<UndergroundBiome>(AffectionLevel.Dislike) // Example Person likes the snow.
            .SetNPCAffection(NPCID.Truffle, AffectionLevel.Like) // Loves living near the dryad.
            .SetNPCAffection(NPCID.Guide, AffectionLevel.Like) // Likes living near the guide.
            .SetNPCAffection(NPCID.Wizard, AffectionLevel.Like) // Dislikes living near the merchant.
            .SetNPCAffection(NPCID.PartyGirl, AffectionLevel.Like) // Dislikes living near the merchant.
            .SetNPCAffection(NPCID.GoblinTinkerer, AffectionLevel.Dislike) // Dislikes living near the merchant.
            .SetNPCAffection(NPCID.TaxCollector, AffectionLevel.Hate) // Hates living near the demolitionist.
            ; // < Mind the semicolon!
        }

        public override void SetDefaults()
        {
            NPC.townNPC = true; // Sets NPC to be a Town NPC
            NPC.friendly = true; // NPC Will not attack player
            NPC.width = 18;
            NPC.height = 40;
            NPC.aiStyle = 7;
            NPC.damage = 10;
            NPC.defense = 15;
            NPC.lifeMax = 250;
            NPC.HitSound = SoundID.NPCHit1;
            NPC.DeathSound = SoundID.NPCDeath1;
            NPC.knockBackResist = 0.5f;

            AnimationType = NPCID.Guide;
        }

        public override void SetBestiary(BestiaryDatabase database, BestiaryEntry bestiaryEntry)
        {
            // We can use AddRange instead of calling Add multiple times in order to add multiple items at once
            bestiaryEntry.Info.AddRange(new IBestiaryInfoElement[] {
// Sets the preferred biomes of this town NPC listed in the bestiary.
// With Town NPCs, you usually set this to what biome it likes the most in regards to NPC happiness.
BestiaryDatabaseNPCsPopulator.CommonTags.SpawnConditions.Biomes.TheHallow,

// Sets your NPC's flavor text in the bestiary.
new FlavorTextBestiaryInfoElement("Did you want some lamp- I mean torches? Rope? Bombs? It's all your's, my friend, because this guy has it."),

// You can add multiple elements if you really wanted to
// You can also use localization keys (see Localization/en-US.lang)
new FlavorTextBestiaryInfoElement("Mods.NPCMorshu.Bestiary.RubyMerchant")
});
        }

        // The PreDraw hook is useful for drawing things before our sprite is drawn or running code before the sprite is drawn
        // Returning false will allow you to manually draw your NPC
        public override bool PreDraw(SpriteBatch spriteBatch, Vector2 screenPos, Color drawColor)
        {
            // This code slowly rotates the NPC in the bestiary
            // (simply checking NPC.IsABestiaryIconDummy and incrementing NPC.Rotation won't work here as it gets overridden by drawModifiers.Rotation each tick)
            if (NPCID.Sets.NPCBestiaryDrawOffset.TryGetValue(Type, out NPCID.Sets.NPCBestiaryDrawModifiers drawModifiers))
            {
                drawModifiers.Rotation += 0.001f;

                // Replace the existing NPCBestiaryDrawModifiers with our new one with an adjusted rotation
                NPCID.Sets.NPCBestiaryDrawOffset.Remove(Type);
                NPCID.Sets.NPCBestiaryDrawOffset.Add(Type, drawModifiers);
            }

            return true;
        }

        public override void HitEffect(int hitDirection, double damage)
        {
            int num = NPC.life > 0 ? 1 : 5;

            for (int k = 0; k < num; k++)
            {
                Dust.NewDust(NPC.position, NPC.width, NPC.height, (DustID.Blood));
            }
        }

        public override bool CanTownNPCSpawn(int numTownNPCs, int money)
        { // Requirements for the town NPC to spawn.
            for (int k = 0; k < 255; k++)
            {
                Player player = Main.player[k];
                if (!player.active)
                {
                    continue;
                }

                // Player has to have either an ExampleItem or an ExampleBlock in order for the NPC to spawn
                if (player.inventory.Any(item => item.type == (ItemID.Ruby) || item.type == (ItemID.LargeRuby)))
                {
                    return true;
                }
            }

            return false;
        }


        public override ITownNPCProfile TownNPCProfile()
        {
            return new ExamplePersonProfile();
        }

        public override List<string> SetNPCNameList()
        {
            return new List<string>() {
"Morshu"
};
        }

        public override void FindFrame(int frameHeight)
        {
            /*npc.frame.Width = 40;
            if (((int)Main.time / 10) % 2 == 0)
            {
            npc.frame.X = 40;
            }
            else
            {
            npc.frame.X = 0;
            }*/
        }

        public override string GetChat()
        {
            WeightedRandom<string> chat = new WeightedRandom<string>();

            int partyGirl = NPC.FindFirstNPC(NPCID.PartyGirl);
            if (partyGirl >= 0 && Main.rand.NextBool(4))
            {
                chat.Add(Language.GetTextValue("Mods.ExampleMod.Dialogue.ExamplePerson.PartyGirlDialogue", Main.npc[partyGirl].GivenName));
            }
            // These are things that the NPC has a chance of telling you when you talk to it.
            chat.Add(Language.GetTextValue("Mods.ExampleMod.Dialogue.ExamplePerson.StandardDialogue1"));
            chat.Add(Language.GetTextValue("Mods.ExampleMod.Dialogue.ExamplePerson.StandardDialogue2"));
            chat.Add(Language.GetTextValue("Mods.ExampleMod.Dialogue.ExamplePerson.StandardDialogue3"));
            chat.Add(Language.GetTextValue("Mods.ExampleMod.Dialogue.ExamplePerson.CommonDialogue"), 5.0);
            chat.Add(Language.GetTextValue("Mods.ExampleMod.Dialogue.ExamplePerson.RareDialogue"), 0.1);

            NumberOfTimesTalkedTo++;
            if (NumberOfTimesTalkedTo >= 10)
            {
                //This counter is linked to a single instance of the NPC, so if ExamplePerson is killed, the counter will reset.
                chat.Add(Language.GetTextValue("Mods.ExampleMod.Dialogue.ExamplePerson.TalkALot"));
            }

            return chat; // chat is implicitly cast to a string.
        }

        public override void SetChatButtons(ref string button, ref string button2)
        { // What the chat buttons are when you open up the chat UI
            button = Language.GetTextValue("LegacyInterface.28");

        }
        // Not completely finished, but below is what the NPC will sell

        public override void SetupShop(Chest shop, ref int nextSlot)
        {
            shop.item[nextSlot++].SetDefaults(ItemID.Torch);
            shop.item[nextSlot++].SetDefaults(ItemID.Rope);
            shop.item[nextSlot++].SetDefaults(ItemID.Bomb);
            shop.item[nextSlot++].SetDefaults(ItemID.RopeCoil);
            shop.item[nextSlot++].SetDefaults(ItemID.DirtBomb);
            shop.item[nextSlot++].SetDefaults(ItemID.Ruby);
            shop.item[nextSlot++].SetDefaults(ItemID.Topaz);
            shop.item[nextSlot++].SetDefaults(ItemID.Diamond);
            shop.item[nextSlot++].SetDefaults(ItemID.Amethyst);
            shop.item[nextSlot++].SetDefaults(ItemID.Emerald);
            shop.item[nextSlot++].SetDefaults(ItemID.Amber);
            shop.item[nextSlot++].SetDefaults(ItemID.Sapphire);
            shop.item[nextSlot++].SetDefaults(ItemID.LargeRuby);
        }
        //
        // if (Main.LocalPlayer.HasBuff(BuffID.Lifeforce)) {
        // shop.item[nextSlot++].SetDefaults(ItemType<ExampleHealingPotion>());
        // }
        //
        // // if (Main.LocalPlayer.GetModPlayer<ExamplePlayer>().ZoneExample && !GetInstance<ExampleConfigServer>().DisableExampleWings) {
        // // shop.item[nextSlot].SetDefaults(ItemType<ExampleWings>());
        // // nextSlot++;
        // // }
        //
        // if (Main.moonPhase < 2) {
        // shop.item[nextSlot++].SetDefaults(ItemType<ExampleSword>());
        // }
        // else if (Main.moonPhase < 4) {
        // // shop.item[nextSlot++].SetDefaults(ItemType<ExampleGun>());
        // shop.item[nextSlot].SetDefaults(ItemType<ExampleBullet>());
        // }
        // else if (Main.moonPhase < 6) {
        // // shop.item[nextSlot++].SetDefaults(ItemType<ExampleStaff>());
        // }
        //
        // // todo: Here is an example of how your npc can sell items from other mods.
        // // var modSummonersAssociation = ModLoader.TryGetMod("SummonersAssociation");
        // // if (ModLoader.TryGetMod("SummonersAssociation", out Mod modSummonersAssociation)) {
        // // shop.item[nextSlot].SetDefaults(modSummonersAssociation.ItemType("BloodTalisman"));
        // // nextSlot++;
        // // }
        //
        // // if (!Main.LocalPlayer.GetModPlayer<ExamplePlayer>().examplePersonGiftReceived && GetInstance<ExampleConfigServer>().ExamplePersonFreeGiftList != null) {
        // // foreach (var item in GetInstance<ExampleConfigServer>().ExamplePersonFreeGiftList) {
        // // if (Item.IsUnloaded) continue;
        // // shop.item[nextSlot].SetDefaults(Item.Type);
        // // shop.item[nextSlot].shopCustomPrice = 0;
        // // shop.item[nextSlot].GetGlobalItem<ExampleInstancedGlobalItem>().examplePersonFreeGift = true;
        // // nextSlot++;
        // // //TODO: Have tModLoader handle index issues.
        // // }
        // // }
        // }

        public override void ModifyNPCLoot(NPCLoot npcLoot)
        {
            npcLoot.Add(ItemDropRule.Common(ItemID.BombFish));
        }

        // Make this Town NPC teleport to the King and/or Queen statue when triggered.
        public override bool CanGoToStatue(bool toKingStatue) => true;
        // Create a square of pixels around the NPC on teleport.
        public void StatueTeleport()
        {
            for (int i = 0; i < 30; i++)
            {
                Vector2 position = Main.rand.NextVector2Square(-20, 21);
                if (Math.Abs(position.X) > Math.Abs(position.Y))
                {
                    position.X = Math.Sign(position.X) * 20;
                }
                else
                {
                    position.Y = Math.Sign(position.Y) * 20;
                }

                Dust.NewDustPerfect(NPC.Center + position, (DustID.ManaRegeneration), Vector2.Zero).noGravity = true;
            }
        }

        public override void TownNPCAttackStrength(ref int damage, ref float knockback)
        {
            damage = 20;
            knockback = 6f;
        }

        public override void TownNPCAttackCooldown(ref int cooldown, ref int randExtraCooldown)
        {
            cooldown = 30;
            randExtraCooldown = 30;
        }

        // todo: implement
        // public override void TownNPCAttackProj(ref int projType, ref int attackDelay) {
        // projType = ProjectileType<SparklingBall>();
        // attackDelay = 1;
        // }

        public override void TownNPCAttackProjSpeed(ref float multiplier, ref float gravityCorrection, ref float randomOffset)
        {
            multiplier = 12f;
            randomOffset = 2f;
        }

        public override void LoadData(TagCompound tag)
        {
            NumberOfTimesTalkedTo = tag.GetInt("numberOfTimesTalkedTo");
        }

        public override void SaveData(TagCompound tag)
        {
            tag["numberOfTimesTalkedTo"] = NumberOfTimesTalkedTo;
        }
        public class ExamplePersonProfile : ITownNPCProfile
        {
            public int RollVariation() => 0;
            public string GetNameForVariant(NPC npc) => npc.getNewNPCName();

            public Asset<Texture2D> GetTextureNPCShouldUse(NPC npc)
            {
                if (npc.IsABestiaryIconDummy && !npc.ForcePartyHatOn)
                    return ModContent.Request<Texture2D>("NPCMorshu/Content/NPCs/RubyMerchant");

                if (npc.altTexture == 1)
                    return ModContent.Request<Texture2D>("NPCMorshu/Content/NPCs/RubyMerchant_Party");

                return ModContent.Request<Texture2D>("NPCMorshu/Content/NPCs/RubyMerchant");
            }

            public int GetHeadTextureIndex(NPC npc) => ModContent.GetModHeadSlot("NPCMorshu/Content/NPCs/RubyMerchant_Head");
        }
    }
}
Try to copy the code more carefully
what do you mean by that?
 
C#:
using Microsoft.Xna.Framework;
using System;
using System.Linq;
using Terraria;
using Terraria.Audio;
using Terraria.ID;
using Terraria.Localization;
using Terraria.ModLoader;
using Terraria.Utilities;
using Terraria.GameContent.Bestiary;
using Terraria.GameContent.ItemDropRules;
using Microsoft.Xna.Framework.Graphics;
using Terraria.GameContent;
using Terraria.GameContent.Personalities;
using Terraria.DataStructures;
using System.Collections.Generic;
using ReLogic.Content;
using Terraria.ModLoader.IO;

namespace ExampleMod.Content.NPCs
{
    // [AutoloadHead] and NPC.townNPC are extremely important and absolutely both necessary for any Town NPC to work at all.
    [AutoloadHead]
    public class ExamplePerson : ModNPC
    {
        public int NumberOfTimesTalkedTo = 0;

        public override void SetStaticDefaults()
        {
            // DisplayName automatically assigned from localization files, but the commented line below is the normal approach.
            // DisplayName.SetDefault("Example Person");
            Main.npcFrameCount[Type] = 25; // The amount of frames the NPC has

            NPCID.Sets.ExtraFramesCount[Type] = 9; // Generally for Town NPCs, but this is how the NPC does extra things such as sitting in a chair and talking to other NPCs.
            NPCID.Sets.AttackFrameCount[Type] = 4;
            NPCID.Sets.DangerDetectRange[Type] = 700; // The amount of pixels away from the center of the npc that it tries to attack enemies.
            NPCID.Sets.AttackType[Type] = 0;
            NPCID.Sets.AttackTime[Type] = 90; // The amount of time it takes for the NPC's attack animation to be over once it starts.
            NPCID.Sets.AttackAverageChance[Type] = 30;
            NPCID.Sets.HatOffsetY[Type] = 4; // For when a party is active, the party hat spawns at a Y offset.

            // Influences how the NPC looks in the Bestiary
            NPCID.Sets.NPCBestiaryDrawModifiers drawModifiers = new NPCID.Sets.NPCBestiaryDrawModifiers(0)
            {
                Velocity = 1f, // Draws the NPC in the bestiary as if its walking +1 tiles in the x direction
                Direction = -1 // -1 is left and 1 is right. NPCs are drawn facing the left by default but ExamplePerson will be drawn facing the right
                               // Rotation = MathHelper.ToRadians(180) // You can also change the rotation of an NPC. Rotation is measured in radians
                               // If you want to see an example of manually modifying these when the NPC is drawn, see PreDraw
            };

            NPCID.Sets.NPCBestiaryDrawOffset.Add(Type, drawModifiers);

            // Set Example Person's biome and neighbor preferences with the NPCHappiness hook. You can add happiness text and remarks with localization (See an example in ExampleMod/Localization/en-US.lang).
            // NOTE: The following code uses chaining - a style that works due to the fact that the SetXAffection methods return the same NPCHappiness instance they're called on.
            NPC.Happiness
            .SetBiomeAffection<HallowBiome>(AffectionLevel.Love) // Example Person prefers the forest.
            .SetBiomeAffection<ForestBiome>(AffectionLevel.Love)
            .SetBiomeAffection<DesertBiome>(AffectionLevel.Like)
            .SetBiomeAffection<SnowBiome>(AffectionLevel.Like)
            .SetBiomeAffection<UndergroundBiome>(AffectionLevel.Dislike) // Example Person likes the snow.
            .SetNPCAffection(NPCID.Truffle, AffectionLevel.Like) // Loves living near the dryad.
            .SetNPCAffection(NPCID.Guide, AffectionLevel.Like) // Likes living near the guide.
            .SetNPCAffection(NPCID.Wizard, AffectionLevel.Like) // Dislikes living near the merchant.
            .SetNPCAffection(NPCID.PartyGirl, AffectionLevel.Like) // Dislikes living near the merchant.
            .SetNPCAffection(NPCID.GoblinTinkerer, AffectionLevel.Dislike) // Dislikes living near the merchant.
            .SetNPCAffection(NPCID.TaxCollector, AffectionLevel.Hate) // Hates living near the demolitionist.
            ; // < Mind the semicolon!
        }

        public override void SetDefaults()
        {
            NPC.townNPC = true; // Sets NPC to be a Town NPC
            NPC.friendly = true; // NPC Will not attack player
            NPC.width = 18;
            NPC.height = 40;
            NPC.aiStyle = 7;
            NPC.damage = 10;
            NPC.defense = 15;
            NPC.lifeMax = 250;
            NPC.HitSound = SoundID.NPCHit1;
            NPC.DeathSound = SoundID.NPCDeath1;
            NPC.knockBackResist = 0.5f;

            AnimationType = NPCID.Guide;
        }

        public override void SetBestiary(BestiaryDatabase database, BestiaryEntry bestiaryEntry)
        {
            // We can use AddRange instead of calling Add multiple times in order to add multiple items at once
            bestiaryEntry.Info.AddRange(new IBestiaryInfoElement[] {
// Sets the preferred biomes of this town NPC listed in the bestiary.
// With Town NPCs, you usually set this to what biome it likes the most in regards to NPC happiness.
BestiaryDatabaseNPCsPopulator.CommonTags.SpawnConditions.Biomes.TheHallow,

// Sets your NPC's flavor text in the bestiary.
new FlavorTextBestiaryInfoElement("Did you want some lamp- I mean torches? Rope? Bombs? It's all your's, my friend, because this guy has it."),

// You can add multiple elements if you really wanted to
// You can also use localization keys (see Localization/en-US.lang)
new FlavorTextBestiaryInfoElement("Mods.NPCMorshu.Bestiary.RubyMerchant")
});
        }

        // The PreDraw hook is useful for drawing things before our sprite is drawn or running code before the sprite is drawn
        // Returning false will allow you to manually draw your NPC
        public override bool PreDraw(SpriteBatch spriteBatch, Vector2 screenPos, Color drawColor)
        {
            // This code slowly rotates the NPC in the bestiary
            // (simply checking NPC.IsABestiaryIconDummy and incrementing NPC.Rotation won't work here as it gets overridden by drawModifiers.Rotation each tick)
            if (NPCID.Sets.NPCBestiaryDrawOffset.TryGetValue(Type, out NPCID.Sets.NPCBestiaryDrawModifiers drawModifiers))
            {
                drawModifiers.Rotation += 0.001f;

                // Replace the existing NPCBestiaryDrawModifiers with our new one with an adjusted rotation
                NPCID.Sets.NPCBestiaryDrawOffset.Remove(Type);
                NPCID.Sets.NPCBestiaryDrawOffset.Add(Type, drawModifiers);
            }

            return true;
        }

        public override void HitEffect(int hitDirection, double damage)
        {
            int num = NPC.life > 0 ? 1 : 5;

            for (int k = 0; k < num; k++)
            {
                Dust.NewDust(NPC.position, NPC.width, NPC.height, (DustID.Blood));
            }
        }

        public override bool CanTownNPCSpawn(int numTownNPCs, int money)
        { // Requirements for the town NPC to spawn.
            for (int k = 0; k < 255; k++)
            {
                Player player = Main.player[k];
                if (!player.active)
                {
                    continue;
                }

                // Player has to have either an ExampleItem or an ExampleBlock in order for the NPC to spawn
                if (player.inventory.Any(item => item.type == (ItemID.Ruby) || item.type == (ItemID.LargeRuby)))
                {
                    return true;
                }
            }

            return false;
        }


        public override ITownNPCProfile TownNPCProfile()
        {
            return new ExamplePersonProfile();
        }

        public override List<string> SetNPCNameList()
        {
            return new List<string>() {
"Morshu"
};
        }

        public override void FindFrame(int frameHeight)
        {
            /*npc.frame.Width = 40;
            if (((int)Main.time / 10) % 2 == 0)
            {
            npc.frame.X = 40;
            }
            else
            {
            npc.frame.X = 0;
            }*/
        }

        public override string GetChat()
        {
            WeightedRandom<string> chat = new WeightedRandom<string>();

            int partyGirl = NPC.FindFirstNPC(NPCID.PartyGirl);
            if (partyGirl >= 0 && Main.rand.NextBool(4))
            {
                chat.Add(Language.GetTextValue("Mods.ExampleMod.Dialogue.ExamplePerson.PartyGirlDialogue", Main.npc[partyGirl].GivenName));
            }
            // These are things that the NPC has a chance of telling you when you talk to it.
            chat.Add(Language.GetTextValue("Mods.ExampleMod.Dialogue.ExamplePerson.StandardDialogue1"));
            chat.Add(Language.GetTextValue("Mods.ExampleMod.Dialogue.ExamplePerson.StandardDialogue2"));
            chat.Add(Language.GetTextValue("Mods.ExampleMod.Dialogue.ExamplePerson.StandardDialogue3"));
            chat.Add(Language.GetTextValue("Mods.ExampleMod.Dialogue.ExamplePerson.CommonDialogue"), 5.0);
            chat.Add(Language.GetTextValue("Mods.ExampleMod.Dialogue.ExamplePerson.RareDialogue"), 0.1);

            NumberOfTimesTalkedTo++;
            if (NumberOfTimesTalkedTo >= 10)
            {
                //This counter is linked to a single instance of the NPC, so if ExamplePerson is killed, the counter will reset.
                chat.Add(Language.GetTextValue("Mods.ExampleMod.Dialogue.ExamplePerson.TalkALot"));
            }

            return chat; // chat is implicitly cast to a string.
        }

        public override void SetChatButtons(ref string button, ref string button2)
        { // What the chat buttons are when you open up the chat UI
            button = Language.GetTextValue("LegacyInterface.28");

        }
        // Not completely finished, but below is what the NPC will sell

        public override void SetupShop(Chest shop, ref int nextSlot)
        {
            shop.item[nextSlot++].SetDefaults(ItemID.Torch);
            shop.item[nextSlot++].SetDefaults(ItemID.Rope);
            shop.item[nextSlot++].SetDefaults(ItemID.Bomb);
            shop.item[nextSlot++].SetDefaults(ItemID.RopeCoil);
            shop.item[nextSlot++].SetDefaults(ItemID.DirtBomb);
            shop.item[nextSlot++].SetDefaults(ItemID.Ruby);
            shop.item[nextSlot++].SetDefaults(ItemID.Topaz);
            shop.item[nextSlot++].SetDefaults(ItemID.Diamond);
            shop.item[nextSlot++].SetDefaults(ItemID.Amethyst);
            shop.item[nextSlot++].SetDefaults(ItemID.Emerald);
            shop.item[nextSlot++].SetDefaults(ItemID.Amber);
            shop.item[nextSlot++].SetDefaults(ItemID.Sapphire);
            shop.item[nextSlot++].SetDefaults(ItemID.LargeRuby);
        }
        //
        // if (Main.LocalPlayer.HasBuff(BuffID.Lifeforce)) {
        // shop.item[nextSlot++].SetDefaults(ItemType<ExampleHealingPotion>());
        // }
        //
        // // if (Main.LocalPlayer.GetModPlayer<ExamplePlayer>().ZoneExample && !GetInstance<ExampleConfigServer>().DisableExampleWings) {
        // // shop.item[nextSlot].SetDefaults(ItemType<ExampleWings>());
        // // nextSlot++;
        // // }
        //
        // if (Main.moonPhase < 2) {
        // shop.item[nextSlot++].SetDefaults(ItemType<ExampleSword>());
        // }
        // else if (Main.moonPhase < 4) {
        // // shop.item[nextSlot++].SetDefaults(ItemType<ExampleGun>());
        // shop.item[nextSlot].SetDefaults(ItemType<ExampleBullet>());
        // }
        // else if (Main.moonPhase < 6) {
        // // shop.item[nextSlot++].SetDefaults(ItemType<ExampleStaff>());
        // }
        //
        // // todo: Here is an example of how your npc can sell items from other mods.
        // // var modSummonersAssociation = ModLoader.TryGetMod("SummonersAssociation");
        // // if (ModLoader.TryGetMod("SummonersAssociation", out Mod modSummonersAssociation)) {
        // // shop.item[nextSlot].SetDefaults(modSummonersAssociation.ItemType("BloodTalisman"));
        // // nextSlot++;
        // // }
        //
        // // if (!Main.LocalPlayer.GetModPlayer<ExamplePlayer>().examplePersonGiftReceived && GetInstance<ExampleConfigServer>().ExamplePersonFreeGiftList != null) {
        // // foreach (var item in GetInstance<ExampleConfigServer>().ExamplePersonFreeGiftList) {
        // // if (Item.IsUnloaded) continue;
        // // shop.item[nextSlot].SetDefaults(Item.Type);
        // // shop.item[nextSlot].shopCustomPrice = 0;
        // // shop.item[nextSlot].GetGlobalItem<ExampleInstancedGlobalItem>().examplePersonFreeGift = true;
        // // nextSlot++;
        // // //TODO: Have tModLoader handle index issues.
        // // }
        // // }
        // }

        public override void ModifyNPCLoot(NPCLoot npcLoot)
        {
            npcLoot.Add(ItemDropRule.Common(ItemID.BombFish));
        }

        // Make this Town NPC teleport to the King and/or Queen statue when triggered.
        public override bool CanGoToStatue(bool toKingStatue) => true;
        // Create a square of pixels around the NPC on teleport.
        public void StatueTeleport()
        {
            for (int i = 0; i < 30; i++)
            {
                Vector2 position = Main.rand.NextVector2Square(-20, 21);
                if (Math.Abs(position.X) > Math.Abs(position.Y))
                {
                    position.X = Math.Sign(position.X) * 20;
                }
                else
                {
                    position.Y = Math.Sign(position.Y) * 20;
                }

                Dust.NewDustPerfect(NPC.Center + position, (DustID.ManaRegeneration), Vector2.Zero).noGravity = true;
            }
        }

        public override void TownNPCAttackStrength(ref int damage, ref float knockback)
        {
            damage = 20;
            knockback = 6f;
        }

        public override void TownNPCAttackCooldown(ref int cooldown, ref int randExtraCooldown)
        {
            cooldown = 30;
            randExtraCooldown = 30;
        }

        // todo: implement
        // public override void TownNPCAttackProj(ref int projType, ref int attackDelay) {
        // projType = ProjectileType<SparklingBall>();
        // attackDelay = 1;
        // }

        public override void TownNPCAttackProjSpeed(ref float multiplier, ref float gravityCorrection, ref float randomOffset)
        {
            multiplier = 12f;
            randomOffset = 2f;
        }

        public override void LoadData(TagCompound tag)
        {
            NumberOfTimesTalkedTo = tag.GetInt("numberOfTimesTalkedTo");
        }

        public override void SaveData(TagCompound tag)
        {
            tag["numberOfTimesTalkedTo"] = NumberOfTimesTalkedTo;
        }
        public class ExamplePersonProfile : ITownNPCProfile
        {
            public int RollVariation() => 0;
            public string GetNameForVariant(NPC npc) => npc.getNewNPCName();

            public Asset<Texture2D> GetTextureNPCShouldUse(NPC npc)
            {
                if (npc.IsABestiaryIconDummy && !npc.ForcePartyHatOn)
                    return ModContent.Request<Texture2D>("NPCMorshu/Content/NPCs/RubyMerchant");

                if (npc.altTexture == 1)
                    return ModContent.Request<Texture2D>("NPCMorshu/Content/NPCs/RubyMerchant_Party");

                return ModContent.Request<Texture2D>("NPCMorshu/Content/NPCs/RubyMerchant");
            }

            public int GetHeadTextureIndex(NPC npc) => ModContent.GetModHeadSlot("NPCMorshu/Content/NPCs/RubyMerchant_Head");
        }
    }
}
Try to copy the code more carefully
did the shop break it?
 
C#:
using Microsoft.Xna.Framework;
using System;
using System.Linq;
using Terraria;
using Terraria.Audio;
using Terraria.ID;
using Terraria.Localization;
using Terraria.ModLoader;
using Terraria.Utilities;
using Terraria.GameContent.Bestiary;
using Terraria.GameContent.ItemDropRules;
using Microsoft.Xna.Framework.Graphics;
using Terraria.GameContent;
using Terraria.GameContent.Personalities;
using Terraria.DataStructures;
using System.Collections.Generic;
using ReLogic.Content;
using Terraria.ModLoader.IO;

namespace ExampleMod.Content.NPCs
{
    // [AutoloadHead] and NPC.townNPC are extremely important and absolutely both necessary for any Town NPC to work at all.
    [AutoloadHead]
    public class ExamplePerson : ModNPC
    {
        public int NumberOfTimesTalkedTo = 0;

        public override void SetStaticDefaults()
        {
            // DisplayName automatically assigned from localization files, but the commented line below is the normal approach.
            // DisplayName.SetDefault("Example Person");
            Main.npcFrameCount[Type] = 25; // The amount of frames the NPC has

            NPCID.Sets.ExtraFramesCount[Type] = 9; // Generally for Town NPCs, but this is how the NPC does extra things such as sitting in a chair and talking to other NPCs.
            NPCID.Sets.AttackFrameCount[Type] = 4;
            NPCID.Sets.DangerDetectRange[Type] = 700; // The amount of pixels away from the center of the npc that it tries to attack enemies.
            NPCID.Sets.AttackType[Type] = 0;
            NPCID.Sets.AttackTime[Type] = 90; // The amount of time it takes for the NPC's attack animation to be over once it starts.
            NPCID.Sets.AttackAverageChance[Type] = 30;
            NPCID.Sets.HatOffsetY[Type] = 4; // For when a party is active, the party hat spawns at a Y offset.

            // Influences how the NPC looks in the Bestiary
            NPCID.Sets.NPCBestiaryDrawModifiers drawModifiers = new NPCID.Sets.NPCBestiaryDrawModifiers(0)
            {
                Velocity = 1f, // Draws the NPC in the bestiary as if its walking +1 tiles in the x direction
                Direction = -1 // -1 is left and 1 is right. NPCs are drawn facing the left by default but ExamplePerson will be drawn facing the right
                               // Rotation = MathHelper.ToRadians(180) // You can also change the rotation of an NPC. Rotation is measured in radians
                               // If you want to see an example of manually modifying these when the NPC is drawn, see PreDraw
            };

            NPCID.Sets.NPCBestiaryDrawOffset.Add(Type, drawModifiers);

            // Set Example Person's biome and neighbor preferences with the NPCHappiness hook. You can add happiness text and remarks with localization (See an example in ExampleMod/Localization/en-US.lang).
            // NOTE: The following code uses chaining - a style that works due to the fact that the SetXAffection methods return the same NPCHappiness instance they're called on.
            NPC.Happiness
            .SetBiomeAffection<HallowBiome>(AffectionLevel.Love) // Example Person prefers the forest.
            .SetBiomeAffection<ForestBiome>(AffectionLevel.Love)
            .SetBiomeAffection<DesertBiome>(AffectionLevel.Like)
            .SetBiomeAffection<SnowBiome>(AffectionLevel.Like)
            .SetBiomeAffection<UndergroundBiome>(AffectionLevel.Dislike) // Example Person likes the snow.
            .SetNPCAffection(NPCID.Truffle, AffectionLevel.Like) // Loves living near the dryad.
            .SetNPCAffection(NPCID.Guide, AffectionLevel.Like) // Likes living near the guide.
            .SetNPCAffection(NPCID.Wizard, AffectionLevel.Like) // Dislikes living near the merchant.
            .SetNPCAffection(NPCID.PartyGirl, AffectionLevel.Like) // Dislikes living near the merchant.
            .SetNPCAffection(NPCID.GoblinTinkerer, AffectionLevel.Dislike) // Dislikes living near the merchant.
            .SetNPCAffection(NPCID.TaxCollector, AffectionLevel.Hate) // Hates living near the demolitionist.
            ; // < Mind the semicolon!
        }

        public override void SetDefaults()
        {
            NPC.townNPC = true; // Sets NPC to be a Town NPC
            NPC.friendly = true; // NPC Will not attack player
            NPC.width = 18;
            NPC.height = 40;
            NPC.aiStyle = 7;
            NPC.damage = 10;
            NPC.defense = 15;
            NPC.lifeMax = 250;
            NPC.HitSound = SoundID.NPCHit1;
            NPC.DeathSound = SoundID.NPCDeath1;
            NPC.knockBackResist = 0.5f;

            AnimationType = NPCID.Guide;
        }

        public override void SetBestiary(BestiaryDatabase database, BestiaryEntry bestiaryEntry)
        {
            // We can use AddRange instead of calling Add multiple times in order to add multiple items at once
            bestiaryEntry.Info.AddRange(new IBestiaryInfoElement[] {
// Sets the preferred biomes of this town NPC listed in the bestiary.
// With Town NPCs, you usually set this to what biome it likes the most in regards to NPC happiness.
BestiaryDatabaseNPCsPopulator.CommonTags.SpawnConditions.Biomes.TheHallow,

// Sets your NPC's flavor text in the bestiary.
new FlavorTextBestiaryInfoElement("Did you want some lamp- I mean torches? Rope? Bombs? It's all your's, my friend, because this guy has it."),

// You can add multiple elements if you really wanted to
// You can also use localization keys (see Localization/en-US.lang)
new FlavorTextBestiaryInfoElement("Mods.NPCMorshu.Bestiary.RubyMerchant")
});
        }

        // The PreDraw hook is useful for drawing things before our sprite is drawn or running code before the sprite is drawn
        // Returning false will allow you to manually draw your NPC
        public override bool PreDraw(SpriteBatch spriteBatch, Vector2 screenPos, Color drawColor)
        {
            // This code slowly rotates the NPC in the bestiary
            // (simply checking NPC.IsABestiaryIconDummy and incrementing NPC.Rotation won't work here as it gets overridden by drawModifiers.Rotation each tick)
            if (NPCID.Sets.NPCBestiaryDrawOffset.TryGetValue(Type, out NPCID.Sets.NPCBestiaryDrawModifiers drawModifiers))
            {
                drawModifiers.Rotation += 0.001f;

                // Replace the existing NPCBestiaryDrawModifiers with our new one with an adjusted rotation
                NPCID.Sets.NPCBestiaryDrawOffset.Remove(Type);
                NPCID.Sets.NPCBestiaryDrawOffset.Add(Type, drawModifiers);
            }

            return true;
        }

        public override void HitEffect(int hitDirection, double damage)
        {
            int num = NPC.life > 0 ? 1 : 5;

            for (int k = 0; k < num; k++)
            {
                Dust.NewDust(NPC.position, NPC.width, NPC.height, (DustID.Blood));
            }
        }

        public override bool CanTownNPCSpawn(int numTownNPCs, int money)
        { // Requirements for the town NPC to spawn.
            for (int k = 0; k < 255; k++)
            {
                Player player = Main.player[k];
                if (!player.active)
                {
                    continue;
                }

                // Player has to have either an ExampleItem or an ExampleBlock in order for the NPC to spawn
                if (player.inventory.Any(item => item.type == (ItemID.Ruby) || item.type == (ItemID.LargeRuby)))
                {
                    return true;
                }
            }

            return false;
        }


        public override ITownNPCProfile TownNPCProfile()
        {
            return new ExamplePersonProfile();
        }

        public override List<string> SetNPCNameList()
        {
            return new List<string>() {
"Morshu"
};
        }

        public override void FindFrame(int frameHeight)
        {
            /*npc.frame.Width = 40;
            if (((int)Main.time / 10) % 2 == 0)
            {
            npc.frame.X = 40;
            }
            else
            {
            npc.frame.X = 0;
            }*/
        }

        public override string GetChat()
        {
            WeightedRandom<string> chat = new WeightedRandom<string>();

            int partyGirl = NPC.FindFirstNPC(NPCID.PartyGirl);
            if (partyGirl >= 0 && Main.rand.NextBool(4))
            {
                chat.Add(Language.GetTextValue("Mods.ExampleMod.Dialogue.ExamplePerson.PartyGirlDialogue", Main.npc[partyGirl].GivenName));
            }
            // These are things that the NPC has a chance of telling you when you talk to it.
            chat.Add(Language.GetTextValue("Mods.ExampleMod.Dialogue.ExamplePerson.StandardDialogue1"));
            chat.Add(Language.GetTextValue("Mods.ExampleMod.Dialogue.ExamplePerson.StandardDialogue2"));
            chat.Add(Language.GetTextValue("Mods.ExampleMod.Dialogue.ExamplePerson.StandardDialogue3"));
            chat.Add(Language.GetTextValue("Mods.ExampleMod.Dialogue.ExamplePerson.CommonDialogue"), 5.0);
            chat.Add(Language.GetTextValue("Mods.ExampleMod.Dialogue.ExamplePerson.RareDialogue"), 0.1);

            NumberOfTimesTalkedTo++;
            if (NumberOfTimesTalkedTo >= 10)
            {
                //This counter is linked to a single instance of the NPC, so if ExamplePerson is killed, the counter will reset.
                chat.Add(Language.GetTextValue("Mods.ExampleMod.Dialogue.ExamplePerson.TalkALot"));
            }

            return chat; // chat is implicitly cast to a string.
        }

        public override void SetChatButtons(ref string button, ref string button2)
        { // What the chat buttons are when you open up the chat UI
            button = Language.GetTextValue("LegacyInterface.28");

        }
        // Not completely finished, but below is what the NPC will sell

        public override void SetupShop(Chest shop, ref int nextSlot)
        {
            shop.item[nextSlot++].SetDefaults(ItemID.Torch);
            shop.item[nextSlot++].SetDefaults(ItemID.Rope);
            shop.item[nextSlot++].SetDefaults(ItemID.Bomb);
            shop.item[nextSlot++].SetDefaults(ItemID.RopeCoil);
            shop.item[nextSlot++].SetDefaults(ItemID.DirtBomb);
            shop.item[nextSlot++].SetDefaults(ItemID.Ruby);
            shop.item[nextSlot++].SetDefaults(ItemID.Topaz);
            shop.item[nextSlot++].SetDefaults(ItemID.Diamond);
            shop.item[nextSlot++].SetDefaults(ItemID.Amethyst);
            shop.item[nextSlot++].SetDefaults(ItemID.Emerald);
            shop.item[nextSlot++].SetDefaults(ItemID.Amber);
            shop.item[nextSlot++].SetDefaults(ItemID.Sapphire);
            shop.item[nextSlot++].SetDefaults(ItemID.LargeRuby);
        }
        //
        // if (Main.LocalPlayer.HasBuff(BuffID.Lifeforce)) {
        // shop.item[nextSlot++].SetDefaults(ItemType<ExampleHealingPotion>());
        // }
        //
        // // if (Main.LocalPlayer.GetModPlayer<ExamplePlayer>().ZoneExample && !GetInstance<ExampleConfigServer>().DisableExampleWings) {
        // // shop.item[nextSlot].SetDefaults(ItemType<ExampleWings>());
        // // nextSlot++;
        // // }
        //
        // if (Main.moonPhase < 2) {
        // shop.item[nextSlot++].SetDefaults(ItemType<ExampleSword>());
        // }
        // else if (Main.moonPhase < 4) {
        // // shop.item[nextSlot++].SetDefaults(ItemType<ExampleGun>());
        // shop.item[nextSlot].SetDefaults(ItemType<ExampleBullet>());
        // }
        // else if (Main.moonPhase < 6) {
        // // shop.item[nextSlot++].SetDefaults(ItemType<ExampleStaff>());
        // }
        //
        // // todo: Here is an example of how your npc can sell items from other mods.
        // // var modSummonersAssociation = ModLoader.TryGetMod("SummonersAssociation");
        // // if (ModLoader.TryGetMod("SummonersAssociation", out Mod modSummonersAssociation)) {
        // // shop.item[nextSlot].SetDefaults(modSummonersAssociation.ItemType("BloodTalisman"));
        // // nextSlot++;
        // // }
        //
        // // if (!Main.LocalPlayer.GetModPlayer<ExamplePlayer>().examplePersonGiftReceived && GetInstance<ExampleConfigServer>().ExamplePersonFreeGiftList != null) {
        // // foreach (var item in GetInstance<ExampleConfigServer>().ExamplePersonFreeGiftList) {
        // // if (Item.IsUnloaded) continue;
        // // shop.item[nextSlot].SetDefaults(Item.Type);
        // // shop.item[nextSlot].shopCustomPrice = 0;
        // // shop.item[nextSlot].GetGlobalItem<ExampleInstancedGlobalItem>().examplePersonFreeGift = true;
        // // nextSlot++;
        // // //TODO: Have tModLoader handle index issues.
        // // }
        // // }
        // }

        public override void ModifyNPCLoot(NPCLoot npcLoot)
        {
            npcLoot.Add(ItemDropRule.Common(ItemID.BombFish));
        }

        // Make this Town NPC teleport to the King and/or Queen statue when triggered.
        public override bool CanGoToStatue(bool toKingStatue) => true;
        // Create a square of pixels around the NPC on teleport.
        public void StatueTeleport()
        {
            for (int i = 0; i < 30; i++)
            {
                Vector2 position = Main.rand.NextVector2Square(-20, 21);
                if (Math.Abs(position.X) > Math.Abs(position.Y))
                {
                    position.X = Math.Sign(position.X) * 20;
                }
                else
                {
                    position.Y = Math.Sign(position.Y) * 20;
                }

                Dust.NewDustPerfect(NPC.Center + position, (DustID.ManaRegeneration), Vector2.Zero).noGravity = true;
            }
        }

        public override void TownNPCAttackStrength(ref int damage, ref float knockback)
        {
            damage = 20;
            knockback = 6f;
        }

        public override void TownNPCAttackCooldown(ref int cooldown, ref int randExtraCooldown)
        {
            cooldown = 30;
            randExtraCooldown = 30;
        }

        // todo: implement
        // public override void TownNPCAttackProj(ref int projType, ref int attackDelay) {
        // projType = ProjectileType<SparklingBall>();
        // attackDelay = 1;
        // }

        public override void TownNPCAttackProjSpeed(ref float multiplier, ref float gravityCorrection, ref float randomOffset)
        {
            multiplier = 12f;
            randomOffset = 2f;
        }

        public override void LoadData(TagCompound tag)
        {
            NumberOfTimesTalkedTo = tag.GetInt("numberOfTimesTalkedTo");
        }

        public override void SaveData(TagCompound tag)
        {
            tag["numberOfTimesTalkedTo"] = NumberOfTimesTalkedTo;
        }
        public class ExamplePersonProfile : ITownNPCProfile
        {
            public int RollVariation() => 0;
            public string GetNameForVariant(NPC npc) => npc.getNewNPCName();

            public Asset<Texture2D> GetTextureNPCShouldUse(NPC npc)
            {
                if (npc.IsABestiaryIconDummy && !npc.ForcePartyHatOn)
                    return ModContent.Request<Texture2D>("NPCMorshu/Content/NPCs/RubyMerchant");

                if (npc.altTexture == 1)
                    return ModContent.Request<Texture2D>("NPCMorshu/Content/NPCs/RubyMerchant_Party");

                return ModContent.Request<Texture2D>("NPCMorshu/Content/NPCs/RubyMerchant");
            }

            public int GetHeadTextureIndex(NPC npc) => ModContent.GetModHeadSlot("NPCMorshu/Content/NPCs/RubyMerchant_Head");
        }
    }
}
Try to copy the code more carefully
I almost got it fixed!

But for some reason the public class got broken and another error appeared:
1660169919950.png

1660169936967.png
 
Back
Top Bottom