Make NPCs disappear at night?
#1
Posté 01 juillet 2015 - 12:29
#2
Posté 01 juillet 2015 - 12:37
Probably the easiest way is in the area heartbeat script, check the time of day. If it's after the time you want them to disappear, loop through the npcs and make them script hidden. In the morning, un-scripthide them. You probably want to store this hidden value on the npc, and run a check to make sure it's set appropriately before hiding/unhiding so you're not hiding/unhiding them every heartbeat when they are already appropriately hidden/unhidden.
Alternately you could build that same logic into the heartbeat script of the individual npcs, a check on time of day. There's also IsNight and IsDay functions if you want less precise control over the time they disappear, IsNight and IsDay I think are coded for specific times.
Uncle FB's npc control and my commoner generics ai both allow for going to actual places at night, so you probably saw one of those.
#3
Posté 01 juillet 2015 - 12:39
It's easy, especially if you don't want them to walk up to specific doors. Several ways to do it, but I think the most efficient way would be to have a single heartbeat script that checks the time (rather than putting the code in the heartbeat scripts of each NPC). With that heartbeat you can do a lot of things, but let's say you just use it to make the NPCs come and go.
So the heartbeat checks the time. The heartbeat can be on the area. If it's not the right time, it does nothing. When it's time to make the NPCs disappear, it cycles through each NPC in the area. It can check for a particular name prefix or suffix, tag, local variable, whatever you want to use to identify which NPCs disappear. Then make those NPCs script hidden, or maybe send them to limbo, if that function works. Do the opposite at the time for them to reappear.
#4
Posté 01 juillet 2015 - 01:48
You also have to run the script on area-enter, in case dusk came while the player was off in another area.
#5
Posté 01 juillet 2015 - 01:58
What, do area heartbeats behave differently, and not run all the time as other heartbeats do, even when you're not in the same area?
#6
Posté 01 juillet 2015 - 03:46
I recently implemented NPCs who go home at night in the module I'm (occasionally) working on. I do it from the individual NPC's heartbeat script, so that each NPC can go home and return at a different time (so no mass exodus occurs).
The simplest method I came up with was to have two versions of an NPC; one outside and another inside. Each version of the NPC has a series of variables set on them:
- Door (string)
- Time1 (int)
- Time2 (int)
- OtherTag (string)
When their heartbeat script detects that the time is within the range of Time1 to Time2 (courtesy of a useful little function in ginc_time), they attempt to open the door with a tag that matches their Door value (walking over to it first if they're not right next to it). The attempt is only made if they're not in combat or conversation, and their action queue is empty.
The door has an OnOpen script that checks for the existence of an OtherTag string on the user. If it finds a valid string, them it hides the user and unhides the NPC with the same tag as their OtherTag string. Each version of the NPC has a different (non-overlapping) time range during which they head for their respective doors.
For instance, the outdoor version of one NPC will attempt to go home between 10pm (Time1 = 22) and 6am (Time2 = 6). Unless you keep them busy talking they generally head straight for their (outside) house door at 10pm, but if they're busy they'll keep retrying up until 6am. The indoor version of the NPC will head for their own door (inside the house) between 7am (Time1 = 7) and 9 pm (Time2 = 21). I had to make sure the two time ranges didn't overlap, otherwise they developed obsessive compulsive disorder (repeatedly heading back and forward during the overlap period).
The two scripts I'm using (NPC heartbeat and door OnOpen):
- Groove Widdit aime ceci
#7
Posté 03 juillet 2015 - 12:19
Okay, this is what I've got for the area heartbeat. It won't compile--I get: "DECLARATION DOES NOT MATCH PARAMETERS" on the townie lass line.
#include "ginc_time"
void main()
{
int iHour = GetTimeHour();
if (iHour > 6)
{
DelayCommand(1.1, SetScriptHidden("Townie Lass", FALSE));
}
if (iHour > 22)
{
DelayCommand(1.0, SetScriptHidden("Townie Lass", TRUE));
}
}
#8
Posté 03 juillet 2015 - 12:45
SetScriptHidden needs to have an object in that spot, not a string like "Townie Lass". Declare an object with GetObjectByStringTag("Townie Lass").
Note that this will only do it to the first object it finds by that string.
#9
Posté 03 juillet 2015 - 02:49
It will also make that one NPC blink in and out of existence once every six seconds between 10pm and midnight, since both if statements will then be true. Admittedly you might not notice the 0.1 seconds during which they're visible. It will do nothing between midnight and 5am (hours 0 to 5).
If you're using ginc_time, then the IsCurrentHourInRange() function might be a better option.
#10
Posté 03 juillet 2015 - 07:22
Okay, I changed it to the below, and now I'm getting "ERROR PARSING VARIABLE LIST" on the object line.
#include "ginc_time"
void main()
{
int iHour = GetTimeHour();
object oTownie = GetObjectByString("Townie Lass");
if (iHour == 6)
{
DelayCommand(1.1, SetScriptHidden(oTownie, FALSE));
}
if (iHour == 22)
{
DelayCommand(1.0, SetScriptHidden(oTownie, TRUE));
}
}
#11
Posté 03 juillet 2015 - 08:05
Sorry, I miswrote the function. It's GetObjectByTag, not GetObjectByString.
Ultimately, you'll want to create a loop that iterates though all creatures with that tag and makes them all appear or disappear, assuming you plan to have more than one.
#12
Posté 03 juillet 2015 - 08:34
#13
Posté 03 juillet 2015 - 11:56
She's not disappearing. I start it at five and she's out there. Shouldn't the below make her disappear?
#include "ginc_time"
void main()
{
int iHour = GetTimeHour();
object oTownie = GetObjectByTag("Townie Lass");
DelayCommand(1.0, SetScriptHidden(oTownie, TRUE));
if (iHour == 6)
{
DelayCommand(1.1, SetScriptHidden(oTownie, FALSE));
}
if (iHour == 22)
{
DelayCommand(1.0, SetScriptHidden(oTownie, TRUE));
}
}
#14
Posté 04 juillet 2015 - 12:12
No, because if you start at 5, then the condition that the hour equals 22 hasn't happened yet, so she has never been set hidden. The way you have it set now, it will only happen if the script is running on those particular hours. You need more complex checks, like checking "the hour is greater than or equal to this number, but less than this other number, and the character is/isn't already hidden".
#15
Posté 04 juillet 2015 - 12:45
#16
Posté 04 juillet 2015 - 12:48
#17
Posté 04 juillet 2015 - 12:49
The default time when you start the game is 12 (noon), so you'll be waiting a long time ingame to test that unless you have a time wand or the SLS time girl npc.
Also, it will fail if you jump the time by advancing it past those times, as the set time and advance time by x hour functions do not make the intervening times happen. If the time is 5 and you set the time to 8 or advance the time by 3 (so it's 8), then 6 and 7 never happen. Additionally, you would want to have else if instead of if on that second check, for performance reasons if you're going to be doing this for a lot of npcs.
Tchos mentioned checking if they are already in the correct hidden/non-hidden state, you need to do that so they don't get repeatedly hidden/shown on each heartbeat of the relevant hours. It makes the performance of the first heartbeat of the given hour slower, but likely speeds up all the other heartbeats of that hour.
You could look at how I handled doing things in a given time period in my ai, I got all that time stuff figured out (and more importantly, tested).
A style point: I hate spaces in tags.
#18
Posté 04 juillet 2015 - 12:53
Ah yes, I missed that line, and yes, it would hide her every heartbeat. Also, is "Townie Lass" her tag, or her name? As Kamal suggests, you might want to remove the space if it's in her tag. At any rate, you need to use the tag in the script for the function GetObjectByTag to work.
#19
Posté 04 juillet 2015 - 01:20
#20
Posté 04 juillet 2015 - 06:02
best way is to take something which al rdy work and adapt it to your need.
I did day /night cycle in every major city area of the baldur's gate reloaded mode. Just check how it 's done.
#21
Posté 05 juillet 2015 - 10:33
My scripts posted above work fine. You could adapt the NPC HB script to your needs. Then each NPC that is intended to hide can run their own script, avoiding the need for loops from an area HB. Something like this should work, even if you advance the time:
#include "ginc_time"
void main()
{
int iTime1 = 6;
int iTime2 = 22;
int iHour = GetTimeHour();
// Between 6am and 10pm, appear if not visible
if (IsCurrentHourInRange(iTime1, iTime2) && GetIsScriptHidden(OBJECT_SELF, TRUE))
{
SetScriptHidden(OBJECT_SELF, FALSE);
}
// Between 11pm and 5am, disappear if visible (and not busy)
if (IsCurrentHourInRange(iTime2+1, iTime1-1) && GetIsScriptHidden(OBJECT_SELF, FALSE)
&& !IsInConversation(OBJECT_SELF) && !GetIsInCombat(OBJECT_SELF))
{
SetScriptHidden(OBJECT_SELF, TRUE, FALSE);// Keep HB running while hidden
}
// Run the standard creature heartbeat script
ExecuteScript("nw_c2_default1", OBJECT_SELF);
}
#22
Posté 05 juillet 2015 - 10:59
Personally, it feels cleaner to me to have one master control heartbeat script that checks the time once per tick to affect a groups of NPCs, rather than all of those NPCs checking the time independently in their own heartbeats. Not that it's significant for something like this...
#23
Posté 05 juillet 2015 - 11:38
I went for individual HBs in my case because I was storing different disappear times on my NPCs. That way you don't get a mass exodus at knock-off time. Although my solution is a fancier one, where they walk to a door, open it, disappear, and a second version of them is unhidden inside their home. The second version of the NPC has opposite disappear times, using the same set of scripts but with different local variables.
Since NPCs are running HB scripts anyway, a few more lines in the script shouldn't slow things down too much. Although my modified solution above makes them run their HB scripts while hidden. All that does though is to make things run at a consistent speed all the time, whereas the area HB approach would speed things up at night (when a whole lot of NPCs are no longer running their HB scripts).
#24
Posté 05 juillet 2015 - 11:50
#25
Posté 06 juillet 2015 - 12:47
don't underestimate the value of Random() when trying to create human behavior ...
Especially when alcohol is involved... ![]()





Retour en haut







