I’m trying to make NPCs feel “alive” and have routines, like going from one place to another, sitting down, getting up, and resuming their walk, etc. I was trying to make this work with Citizens paths, but I don’t know if it’s more optimal with Denizen using a loop with while. What would be the most efficient way to do something like this?
#(tugitanito) Npcs routines
100 messages · Page 1 of 1 (latest)
(tugitanito) Npcs routines
Hi I'm AutoThreadBot! Don't mind me, I'll just be adding the helper team to this thread so they can see it. A human will get to you soon.
!e time changes in world
Group
World
Event Lines
time changes (in <world>) time <0-23> (in <world>)
Triggers
when the current time changes in a world (once per mine-hour).
Context
<context.time> returns the current time (the hour, as a number from 0 to 23).
<context.world> returns the world.
^ for timing
you probably don't need to be super worried about performance to start with, address that if it becomes an issue
something like this?
Rutina_Asignacion:
type: assignment
actions:
on assignment:
- trigger name:click state:true
- run RutinaLoop
on time 6-11 in world:
-
walk <npc> <location[992,82,-1457,world]>
-
wait 5s
-
walk <npc> <location[979,83,-1481,world]>
-
wait 5s
-
walk <npc> <location[992,82,-1457,world]>
-
wait 5s
i’ve realized that the NPC doesn’t seem to wait between commands. For example, it reaches a point, doesn’t wait the 5 seconds I assigned, then turns around and doesn’t complete the route properly.
Wrap your code with three tildes when you're pasting it as raw code:
```
Like this
```
It makes it legible,
Like this
Rutina_Asignacion:
type: assignment
actions:
on assignment:
- flag npc Rutina_Mundo
Rutina_Mundo:
type: world
events:
on time 6-11 in world:
- walk <[npc]> <location[992,82,-1457,world]>
on time 12-17 in world:
- walk <[npc]> <location[979,83,-1481,world]>
on time 18-23 in world:
- walk <[npc]> <location[1006,83,-1449,world]>
on time 0-5 in world:
- walk <[npc]> <location[1006,83,-1449,world]>```
i changed it a little
I’m still experimenting and trying to learn, but a little help wouldn’t hurt 😅
Thank you; the same-width spacing and proper formatting helps a lot
The time input is <0-23> indicates one number between 0 and 23; inputs like 6-11 are invalid
Thanks, I’ve studied programming but I haven’t worked in it yet. I know the basics, but I still have a lot to learn
You're doing great, don't worry!
😃
type: assignment
actions:
on assignment:
- narrate "Rutina activada"
Rutina_Mundo:
type: world
events:
# wake up and go to breakfast
on time 6 in world:
- walk npc:358 <location[979,83,-1481,world]>
# go to work
on time 7 in world:
- walk npc:358 <location[989,82,-1463,world]>
- walk npc:358 <location[1009,82,-1463,world]>
- walk npc:358 <location[1033,82,-1461,world]>
# go to eat
on time 13 in world:
- walk npc:358 <location[979,83,-1481,world]>
# go home
on time 19 in world:
- walk npc:358 <location[1006,83,-1449,world]>
i managed to get it working, but the NPC’s workplace is a bit far away, so I thought about setting the path point by point, but it doesn’t seem to work. He doesn’t want to go to work lol
Are you debugging along the way? When you say he doesn't want to go to work, you'll want to check your debug -
!debug
If you need help with a script issue, one of the most powerful tools Denizen has to offer is full debug output. This is displaying in your console whenever scripts are running until you turn debug off. To share a debug log quickly and easily with helpers, simply run the command /denizen debug -r in-game to begin recording, then run through the part of the script you need help with, then run the command /denizen submit. This will give you a link to a paste of the debug log, which you can then copy/paste back to us!
Or just watch your console
The things you want to look for in this case are:
- that the world event (eg, on time 6 in world)
- if there are any errors in the arguments for the walk
- if there's a difference if you're close to the NPC, or not
Another important note is to determine how far the two locations are; the starting location for the NPC and the location they're walking to
The log doesn’t show errors, except when I move away from the NPC and it is no longer loaded. When that happens, the log shows the following error:
ERROR in script 'rutina_mundo' in queue 'RUTINA_MUNDO_1202_HeadsetUsc' while executing command 'WALK' in file 'scripts/pathCitizen1.dsc' on line '19' with NPC 'n@358 (citizen1)'!
Error Message: Woah! Invalid arguments were specified!
Must have a valid spawned NPC attached, or an entity specified.
Is there any way to stop the script when the NPC is not spawned?
And another question: when I put many actions in sequence, does one execute and then the next? Or does the last one execute and the previous ones get canceled? If so, how can I make them execute one after another in order?
!tag entitytag.is_spawned
Returns whether the entity is spawned.
Group
data
Returns
ElementTag(Boolean)
!tag is_truthy
Returns true if the object is 'truthy'. An object is 'truthy' if it exists and is valid, and does not represent a concept like emptiness.
An empty list or an air item will return 'false'. Plaintext "null" or "false", an empty element, or a numeric zero will return 'false' as well.
Some object types may have their own logical implementations, for examples an EntityTag value is 'truthy' only if the entity it represents is spawned.
Errored/broken/invalid tags are also considered 'false' by this log...
Returns
ElementTag(Boolean)
You can, before running the command, check if the NPC is truthy or not before proceeding
You can also use this for your entity tag above:
!tag npcs_assigned
Returns a list of all NPCs assigned to a specified script.
Returns
ListTag(NPCTag)
Group
entity
Syntax
walk (<entity>|...) [<location>/stop] (speed:<#.#>) (auto_range) (radius:<#.#>) (lookat:<location>)
Short Description
Causes an entity or list of entities to walk to another location.
Use to make the NPC walk to an anchored position.
- walk <npc> <npc.anchor[spot1]>
Use to make the NPC walk to an anchored position that may be far away.
- walk <npc> <npc.anchor[spot2]> auto_range
Use to make the NPC walk to an anchored position while looking backwards.
- walk <npc> <npc.anchor[spot3]> lookat:<npc.anchor[spot2]>
Use to make the NPC walk to an anchored position, and then say something after arrival, using ~waitable syntax.
- ~walk <npc> <npc.anchor[spot4]>
- chat "I'm here!"
Use to make a list of NPCs stored in a flag all move together, with a flocking radius based on the number of NPCs included.
- walk <player.flag[squad]> radius:<player.flag[squad].size> <player.location>
These are also good or better example usages you may like for a good reference
okay, with the walk systems im looking for something like the paths system in citizens, i will try to do something similar, i imagine that i have to use the npc.anchor[spot3], i will investigate it, thanks
!tag npctag.anchor
Returns the location associated with the specified anchor, or null if it doesn't exist.
Returns
LocationTag
!search anchor
Search Results
[Perfect Name Match] !Command anchor,
[Partial Name Match] !Tag npctag.anchor, !Tag npctag.has_anchors, !Tag npctag.list_anchors,
[Semi-Decent Match] !Mechanism materialtag.count, !Tag materialtag.count, !Property materialtag.count, !Event player sets spawn, !Tag materialtag.count_max, !Tag materialtag.count_min,
[Just Barely Matched] !Command engage, !Command walk.
!command anchor usage
Required Plugins or Platforms
Citizens
Group
npc
Syntax
anchor [id:<name>] [remove/add <location>]
Short Description
Controls an NPC's Anchor Trait.
Use to add and remove anchors to an NPC.
- define location_name <context.message>
- chat "I have saved this location as <[location_name]>.'
- anchor add <npc.location> id:<[location_name]>
Weird location_name definition example eheh
so, this is how the script looks for now
Rutina_Asignacion:
type: assignment
actions:
on assignment:
- execute as_server "npc pathopt opensdoors true"
- narrate "Rutina del NPC activada"
Rutina_Mundo:
type: world
events:
# Morning - Breakfast
on time 6 in world:
- if <npc[358].is_spawned>:
- ~walk npc:358 <npc.anchor[tabern]> auto_range speed:1.2
# Work
on time 7 in world:
- if <npc[358].is_spawned>:
- ~walk npc:358 <npc.anchor[workwalk1]> auto_range speed:1.2
- ~walk npc:358 <npc.anchor[workwalk2]> auto_range speed:1.2
- ~walk npc:358 <npc.anchor[workwalk3]> auto_range speed:1.2
- ~walk npc:358 <npc.anchor[workwalk4]> auto_range speed:1.2
- ~walk npc:358 <npc.anchor[work]> auto_range speed:1.2
# Eat
on time 13 in world:
- if <npc[358].is_spawned>:
- ~walk npc:358 <npc.anchor[tabern]> auto_range speed:1.2
# Go back home
on time 19 in world:
- if <npc[358].is_spawned>:
- ~walk npc:358 <npc.anchor[home]> auto_range speed:1.2
# Sleep
on time 22 in world:
- if <npc[358].is_spawned>:
- ~walk npc:358 <npc.anchor[home]> auto_range speed:1.2
There are no errors in the console, but I’ve noticed that the NPC takes the routes at the wrong times or does the routes more than once. Any idea why?
(i was waiting for them to share a debug and to explain why a specific command fired three times)
:P
using your debugging tools, add a narrate
ooops 😭
sorry
Possible Confusion
Did you mean to search for time changes in world?
Group
World
Event Lines
time changes (in <world>) time <0-23> (in <world>)
Triggers
when the current time changes in a world (once per mine-hour).
Context
<context.time> returns the current time (the hour, as a number from 0 to 23).
<context.world> returns the world.
<context.time>returns the current time (the hour, as a number from0to23).
<context.world>returns the world.
try narrating these tags in one of your events
as drjoenh said, there's a funny note to remember with this event
Event Lines
time changes (in <world>)
that<world>is a matcher; but when you useworld, insdtead of using the literal world namedworld, its listening to any world - eg,worldandworld_netherandworld_the_end
a good solution to this also is to use a different world name
i like to use home
but its not gamebreaking either
its just preference
yeah my world is called world, i only have world and world_the_end in the server
the correct form is "on time changes in world world:" ?
no, on time changes in <world> where <world> is the world name
on time changes in world is the event line
i was just mentioning that ironically, because your world name and the static name world are going to be the same
(unless you change it)
im using the - narrate <context.world>, im going to send the debug
narrating <context.world> in your event will tell you why its firing multiple times
narrating <context.time> tells you the time for that world firing
Surprisingly, the NPC has completed the entire route perfectly. I’m testing with the ticks set to 90 so it doesn’t take as long
[19:01:32 INFO]: +- Queue 'RUTINA_MUNDO_26_ConnectorInstructional' Executing: (line 33) narrate <context.world> ---------+
[19:01:32 INFO]: Filled tag <context.world> with 'w@world_the_end'.
[19:01:32 INFO]: +> Executing 'NARRATE': Narrating='w@world_the_end'
[19:01:32 INFO]: w@world_the_end
Well... I think in the end it’s best to change the name like you said
!debug
If you need help with a script issue, one of the most powerful tools Denizen has to offer is full debug output. This is displaying in your console whenever scripts are running until you turn debug off. To share a debug log quickly and easily with helpers, simply run the command /denizen debug -r in-game to begin recording, then run through the part of the script you need help with, then run the command /denizen submit. This will give you a link to a paste of the debug log, which you can then copy/paste back to us!
I’m going to change the world name and run another test
For now everything is working well. I’m going to send the script, and I’d like to get some advice, since I want this script to work 100% of times and be stable
sure, can do
!paste
Help us help you by pasting your script to https://paste.denizenscript.com/New/Script and linking it back here.
that or you can check the <context.world.name> before executing scripts; especially if you utilize the same events for different NPCs located in different worlds
renaming the world gives you a safe solution to handling world related stuff, checking data as we run is extra steps in a sense but it's more verbose visually and keeps the default content and keeps things simple
i love ricotta on lasagna, but it's perfectly fine for others to use cottage cheese
Content of Denizen Script Paste #139248: rutine... pasted 2026/02/22 20:22:42 UTC+00:00, Paste length: 1291 characters across 45 lines, Content: Rutina_Asignacion: type: assignment actions:
Thanks for that. After reviewing everything though, it's clear you've already been permanently banned here previously. We strongly advise you to stop. If you need explicit clarification, you're unwelcomed here after refusing to both cooperate and break our rules.
@glass yoke ban 1332784074011709524 permanent You have been banned for evading a previous community ban. We have a strict no-evasion policy. Further attempts to rejoin will be handled accordingly.
Temporary Ban Applied
@last prawn has banned @remote bison. Expires: (indefinite).
