1. These forums are still being retired! Please use GitHub discussions or Discord. You cannot create new threads or new accounts now. If you need to contact some user of the forums, you should do it sooner, rather than later. This notice was last updated on May 30th, 2021.

Changing an NPC's properties

Discussion in 'Help and Support' started by MrGgggg243, Feb 13, 2016.

Tags:
  1. MrGgggg243

    MrGgggg243 Level 2

    Joined:
    Aug 17, 2014
    Messages:
    35
    Hi, let me get straight to the point:

    How do I:
    1. Change the maximum health (lifeMax) and health (life) of an NPC?
    2. Change the name and display name of an NPC?
    3. Change the target of an NPC?

    life, lifeMax and target are all values in the NPC Update [23] packet but I have absolutely no idea how to use it. Changing the name is most likely achieved through the Update NPC Name [56] packet.

    Here is my code for the name, life and maxLife (Doesn't work):
    Code:
    int npcIndex = NPC.NewNPC((int)spawnOrigin.X, (int)spawnOrigin.Y, NPCID, 1);
    NPC thisBoss = Main.npc[npcIndex];
    
    thisBoss.name = name;
    thisBoss.displayName = thisBoss.name;
    TSPlayer.All.SendData(PacketTypes.UpdateNPCName, thisBoss.displayName);
    
    thisBoss.lifeMax = (int)(thisBoss.lifeMax * life);
    thisBoss.life = thisBoss.lifeMax;
    TSPlayer.All.SendData(PacketTypes.NpcUpdate, "", npcIndex);
    For those wondering I'm creating an Automated Boss Arena that spawns bosses with custom names, and life. I've got it all working except for these packet issues.

    Here is my code for changing the NPC's target (Doesn't work):
    Code:
    NPC npc = Main.npc[npcIndex];
    npc.target = currentPlayers[random.Next(0, currentPlayers.Count - 1)].Index;
    TSPlayer.All.SendData(PacketTypes.NpcUpdate, "", npcIndex);
    When a player exits the arena, then the boss will change its target to player who's still in the arena.

    I'd really appreciate an answer. I have yet to get my head around packets and how they work.
    Thank you. :) <3
     
  2. GameRoom

    Plugin Developer Zero Day Plugin Author

    Joined:
    Jun 20, 2012
    Messages:
    42
    Yeah, this is a packet issue. You're changing the variables on the server, but that information never gets relayed to the clients. So after you change any variables like that, you have to send a packet. The best way to learn how to do it is to find Terraria's source code and cntrl+F "NetMessage.SendData(23" and so on to see how the game itself handles it. Looking at your code it should work, I think, so maybe it's an issue with some other part of your code. Feel free to PM me if you have any more questions.
     
  3. Marcus101RR

    Marcus101RR Guest

    You need to create the new npc, followed by setting its setdefaults and then scaling any stats you wish after.
     
  4. MrGgggg243

    MrGgggg243 Level 2

    Joined:
    Aug 17, 2014
    Messages:
    35
    That didn't work. Am I doing it right?:
    Code:
    TSPlayer plr = args.Player;
    int npcid = NPC.NewNPC((int)plr.TPlayer.position.X, (int)plr.TPlayer.position.Y - 1, 222, 1);
    NPC npc = Main.npc[npcid];
    npc.SetDefaults(222);
    npc.lifeMax = 255;
    npc.life = 255;
    TSPlayer.All.SendData(PacketTypes.NpcUpdate, "", npcid);
    
     
  5. Marcus101RR

    Marcus101RR Guest

    This is what TShock basically does:
    Code:
                    int npcid = NPC.NewNPC(spawnTileX * 16, spawnTileY * 16, type, 0);
                    // This is for special slimes
                    Main.npc[npcid].SetDefaults(name);
    Try that out with a dummy value and then work your way from there...
     
  6. MrGgggg243

    MrGgggg243 Level 2

    Joined:
    Aug 17, 2014
    Messages:
    35
    So now I've got:
    Code:
    TSPlayer plr = args.Player;
    int npcid = NPC.NewNPC((int)plr.TPlayer.position.X, (int)plr.TPlayer.position.Y - 1, 222, 0);
    NPC npc = Main.npc[npcid];
    npc.SetDefaults(222);
    Okay, now the Health and Name work. Changing the Target is still being weird. It requires a playerID according to the packet documentation. How do I find the player's packet ID? Also, For some reason the boss's target always defaults to 255.
     
  7. Professor X

    Professor X Spam Cleaner 9000.5
    TShock Mod TShock Contributor

    Joined:
    Aug 18, 2014
    Messages:
    246
    There is no such thing as a "player's packet ID", it's the player's index.

    Also, you should take GameRoom's advice and go browse Terraria's source. It might be a pain but it's the best way to learn how things work.
     
  8. Marcus101RR

    Marcus101RR Guest

    That is entirely dependent on how you want it to find the next available player. You could make a for loop and cycle through 255 player index, find which one is online, logged in, alive, and closest to the boss at a given time and then change that id to the target.
     
  9. MrGgggg243

    MrGgggg243 Level 2

    Joined:
    Aug 17, 2014
    Messages:
    35
    It's the index for a Player in the array Main.player[]. I've got it working now. Thank you. I just made a way of getting the player's indexes from Main.player[] and choosing a random one.

    Got it working. If an NPC is targeting a player who is outside of the arena, then it will change its target to a random player within the arena.

    Now the only problem is that some NPCs spazz out when their health is changed. I.e. Pillars, Prime, Plantera, Twins. Is there any way to get around this? When they get hit, they go invisible or start spawning random 'gore' - it's very strange.

    Thanks for all the help :)
     
  10. Marcus101RR

    Marcus101RR Guest

    My guess is because of their 2nd Form, some bosses are more than one form, maybe that is why they are spazzing out? Pillars use a shield before their main health is affected, prime... not so sure, plantera gets a boost when she transforms, and twins turn to metal parts when they lose half their health...

    Just a theory.