Hello, I’ve been working on a custom NPC (Mr. Jason) for my GZDoom project. I’ve got most of the features working like Text box and dialogue system, Text shows correctly, Text shows correctly and Sound effect (VTS.wav) plays during dialogue. all working!
[youtube]https://youtu.be/l77XHVkkRis[/youtube]
The only thing I can’t get working is his movement. I want him to walk toward the player (Doomguy) so that when he’s close enough, the dialogue triggers. if he closer to doomguy and stop there, the text box, dialogue system, Text shows correctly, Text shows correctly and Sound effect (VTS.wav) plays during dialogue will show up. but Right now, he just stands in place and never approaches the player. How do I make Mr. Jason move/walk closer to the player, like a normal monster would, but instead of attacking, trigger my dialogue when he’s near? Thanks in advance.
NPC Not Moving Toward Player Before Dialogue Starts
Moderator: GZDoom Developers
Forum rules
Before asking on how to use a ZDoom feature, read the ZDoom wiki first. If you still don't understand how to use a feature, then ask here.
Please bear in mind that the people helping you do not automatically know how much you know. You may be asked to upload your project file to look at. Don't be afraid to ask questions about what things mean, but also please be patient with the people trying to help you. (And helpers, please be patient with the person you're trying to help!)
Before asking on how to use a ZDoom feature, read the ZDoom wiki first. If you still don't understand how to use a feature, then ask here.
Please bear in mind that the people helping you do not automatically know how much you know. You may be asked to upload your project file to look at. Don't be afraid to ask questions about what things mean, but also please be patient with the people trying to help you. (And helpers, please be patient with the person you're trying to help!)
- Mhmiii
- Posts: 5
- Joined: Mon Jul 07, 2025 1:54 pm
- Preferred Pronouns: He/Him
- Operating System Version (Optional): windows 11
- Graphics Processor: Not Listed
Re: NPC Not Moving Toward Player Before Dialogue Starts
oh yeah, by the way. Here is how the code look like in ZScript... I'm pretty sure what is wrong:
Spoiler:
-
- Posts: 100
- Joined: Wed Dec 15, 2021 8:38 pm
- Graphics Processor: nVidia (Modern GZDoom)
Re: NPC Not Moving Toward Player Before Dialogue Starts
Mr. Jason doesn't seem to have any properties? +LOOKALLAROUND might be good so that he spots you no matter where he's facing and starts walking towards you.
- Mhmiii
- Posts: 5
- Joined: Mon Jul 07, 2025 1:54 pm
- Preferred Pronouns: He/Him
- Operating System Version (Optional): windows 11
- Graphics Processor: Not Listed
Re: NPC Not Moving Toward Player Before Dialogue Starts
thanks for the tip about +LOOKALLAROUND. I tried it but Mr. Jason still just stands there and never walks toward the player, so the dialog never triggers. I want him to walk up to Doomguy and then open the textbox, sound, text, whatever. What I tried so far Added +LOOKALLAROUND, Added +LOOKALLAROUND. Gave the actor a non-zero Speed (8), Gave the actor a non-zero Speed (8), Put A_Look in Spawn and A_Chase in the See state, Attempted setting target = players[ConsolePlayer].mo in PostBeginPlay and used SetStateLabel("See"), Confirmed there are no compilation errors (ZScript compiles), Actor is not DORMANT in the map (placed normally). I have both a DECORATE actor (older) and a ZScript actor named MrJason in my mod, I keep getting a warning that the class is defined more than once (so GZDoom renames one of them). I haven’t removed DECORATE because I’m worried about breaking other parts. anyways here my code of zscript if it something wrong:Heisanevilgenius wrote: ↑Fri Sep 26, 2025 11:37 am Mr. Jason doesn't seem to have any properties? +LOOKALLAROUND might be good so that he spots you no matter where he's facing and starts walking towards you.
version "4.14" class MyTextBoxHandler : EventHandler { TextureID textBox; Array<string> dialogues; int dialogueIndex; int currentChar; int ticker; int speed; bool active; bool pressedLastTick; TextureID currentFace; TextureID currentFaceTalking; int talkCycleTimer; bool mouthOpen; override void OnRegister() { textBox = TexMan.CheckForTexture("UTB", TexMan.Type_Any); dialogues.Clear(); dialogues.Push("Hello world!"); dialogues.Push("And how are you today?"); dialogues.Push("Oh me? I'm fine! Thank you so much!"); dialogueIndex = 0; currentChar = 0; ticker = 0; speed = 3; active = true; pressedLastTick = false; currentFace = TexMan.CheckForTexture("N", TexMan.Type_Any); currentFaceTalking = TexMan.CheckForTexture("N(T)", TexMan.Type_Any); talkCycleTimer = 0; mouthOpen = false; } void StartDialog() { active = true; dialogueIndex = 0; currentChar = 0; ticker = 0; talkCycleTimer = 0; mouthOpen = false; pressedLastTick = false; } override void WorldTick() { if (!active) return; string currentDialogue = dialogues[dialogueIndex]; if (currentChar < int(currentDialogue.Length())) { ticker++; if (ticker >= speed) { ticker = 0; currentChar++; string ch = currentDialogue.Mid(currentChar - 1, 1); if (ch != " " && ch != "\t" && ch != "\n") { S_StartSound("VTS", CHAN_VOICE); } } talkCycleTimer++; if (talkCycleTimer >= 6) { mouthOpen = !mouthOpen; talkCycleTimer = 0; } } else { mouthOpen = false; talkCycleTimer = 0; } UpdateFace(); int cp = ConsolePlayer; bool pressed = false; if (cp >= 0 && cp < int(players.Size())) { if (players[cp].mo != null) { pressed = (players[cp].cmd.buttons & BT_USE) != 0; } } if (pressed && !pressedLastTick) { if (currentChar < int(currentDialogue.Length())) { currentChar = int(currentDialogue.Length()); } else { dialogueIndex++; if (dialogueIndex >= int(dialogues.Size())) { active = false; } else { currentChar = 0; ticker = 0; talkCycleTimer = 0; mouthOpen = false; } } } pressedLastTick = pressed; } void UpdateFace() { if (dialogueIndex == 0 || dialogueIndex == 1) { currentFace = TexMan.CheckForTexture("H", TexMan.Type_Any); currentFaceTalking = TexMan.CheckForTexture("H(T)", TexMan.Type_Any); } else if (dialogueIndex == 2) { if (currentChar < int(dialogues[dialogueIndex].Length())) { currentFace = TexMan.CheckForTexture("H(EC)", TexMan.Type_Any); currentFaceTalking = TexMan.CheckForTexture("H(TACE)", TexMan.Type_Any); } else { currentFace = TexMan.CheckForTexture("SM(EC)", TexMan.Type_Any); currentFaceTalking = TexMan.CheckForTexture("SM(EC)", TexMan.Type_Any); } } } void SetFace(String face, String talkFace) { currentFace = TexMan.CheckForTexture(face, TexMan.Type_Any); currentFaceTalking = TexMan.CheckForTexture(talkFace, TexMan.Type_Any); } override void RenderOverlay(RenderEvent e) { if (!active) return; if (textBox.isValid()) { Screen.DrawTexture(textBox, false, 50, 150, DTA_Clean, true); } TextureID faceToDraw = (mouthOpen && currentChar < int(dialogues[dialogueIndex].Length())) ? currentFaceTalking : currentFace; if (faceToDraw.isValid()) { Screen.DrawTexture(faceToDraw, false, 10, -54, DTA_Clean, true); } string shown = dialogues[dialogueIndex].Left(currentChar); BrokenLines br = BigFont.BreakLines(shown, 327); double lineHeight = BigFont.GetHeight(); double posx = 112.0; double posy = -28.0; for (int i = 0; i < br.Count(); i++) { Screen.DrawText(CONFONT, Font.CR_WHITE, posx, posy + i * lineHeight, br.StringAt(i), DTA_Clean, true); } } } class MrJason : Actor { Default { Health 100; Radius 20; Height 56; Speed 8; SeeSound "jason/see"; +LOOKALLAROUND +FRIENDLY } States { Spawn: TROO A 10 A_Look; Loop; See: TROO AABBCCDD 4 A_Chase; Loop; } }
so what i see is MrJason is spawned (I placed him manually in map), He never moves. he stays standing where I placed him, See state exists and contains A_Chase, Speed is not zero. No errors in console; only warning earlier about duplicate MrJason class (DECORATE & ZScript). Things I’m worried about/could be causing it is Duplicate definitions (DECORATE and ZScript both define MrJason), I get a “tried to define class 'MrJason' more than once” warning. Could that break targeting / states? My PostBeginPlay target assignment might be wrong or unnecessary. maybe A_Look should set target automatically. Maybe A_Chase needs Thing_Hate or other flags when used with +FRIENDLY? (I want him to approach but not attack.) Could the actor be blocked by geometry, or on a different floor/sector so he can't pathfind?
and i have so many quesions:
Could the duplicate definition warning (DECORATE + ZScript) prevent A_Look/A_Chase from running properly? Should I remove the old DECORATE class and keep only the ZScript class for MrJason?
If I should keep DECORATE for something else, can I rename the ZScript class or the DECORATE class instead so they don’t collide? Which is recommended?
Is +LOOKALLAROUND + A_Look in Spawn + Speed non-zero the correct minimal set for "actor will spot and walk to player"? Anything else I must add (flags, Thing_Hate, target behavior)?
If A_Chase still doesn’t move MrJason, is TryMove(Vec2Angle(...)) in Tick() a better approach? Example of that approach I can try?
Anything obvious I missed (map placement flags, DORMANT, not on same 3D floor, player actor type differences)?
Thanks again... I’m stuck on this movement part only. The dialog box, typewriter text and face sprites all work fine once MrJason gets close: I just need him to approach Doomguy.
-
- Posts: 100
- Joined: Wed Dec 15, 2021 8:38 pm
- Graphics Processor: nVidia (Modern GZDoom)
Re: NPC Not Moving Toward Player Before Dialogue Starts
That's pretty baffling. This is beyond my skill level I think.