Larian Banner: Baldur's Gate Patch 9
Previous Thread
Next Thread
Print Thread
Joined: Jun 2013
old hand
OP Offline
old hand
Joined: Jun 2013
Using the State Manager.

The State Manager is a script you can utilize with charscripts you create. The main usage of it is to setup different behaviors for NPCs. Larian specifically uses it a lot for what an NPC should be doing before and after a quest. But there are many more uses for it.
The other great advantage of the State Manager is you can more easily interact with the charscript using the story editor. There are alternatives to using the State Manger but I find it the most versatile option. It also alleviates the need in dealing with charscript action priorities.

This tutorial assumes you know a bit about charscriping. For a good intro on that see this thread: Character and Item Scripts



Making a new charscript that uses the State Manager:

1. Open the script editor.

[Linked Image]

2. Create a new Charscript. This is mine:

Code
#INCLUDE State_Manager

INIT
USING State_Manager
CHARACTER:__Me

EXTERN TRIGGER:%MorningPlace,null
EXTERN TRIGGER:%NoonPlace,null
EXTERN TRIGGER:%NightPlace,null
EXTERN TRIGGER:%HidingPlace,null
EXTERN ITEM:%Bed,null
EXTERN FIXEDSTRING:%AttackText,null

BEHAVIOUR
	
REACTION State_Morning, 0
	USAGE PEACE
	ACTIONS
		GetRandom(%currentAction, "Action_Morning")
		SetPriority(%currentAction, 1100)
	
REACTION Action_Morning, 0
	USAGE PEACE
	ACTIONS
		CharacterMoveTo(%MorningPlace)
		SetPriority(%currentAction, 0)
		
		
REACTION State_Noon, 0
	USAGE PEACE
	ACTIONS
		GetRandom(%currentAction, "Action_Noon")
		SetPriority(%currentAction, 1100)
		
REACTION Action_Noon, 0
	USAGE PEACE
	ACTIONS
		CharacterMoveTo(%NoonPlace)
		SetPriority(%currentAction, 0)
		
			
REACTION State_Night, 0
	USAGE PEACE
	ACTIONS
		GetRandom(%currentAction, "Action_Night")
		SetPriority(%currentAction, 1100)
		
		
REACTION Action_Night, 0
	USAGE PEACE
	ACTIONS
	IF "!c1"
		CharacterHasStatus(__Me,"LYING")
		//CharacterHasStatus(__Me,"LYING")
	THEN 
		CharacterMoveTo(%NightPlace)
		CharacterMoveTo(%Bed)
		CharacterUseItem(%Bed)
		SetPriority(%currentAction, 0)
	ENDIF
		Sleep(3)
		
		
REACTION State_Hide, 0 
	USAGE PEACE
	ACTIONS
		GetRandom(%currentAction, "Action_Hide")
		SetPriority(%currentAction, 1100)
		
REACTION Action_Hide, 0 
	USAGE PEACE
	ACTIONS
		DisplayText(__Me,%AttackText,4)
		CharacterMoveTo(%HidingPlace,1)
		SetPriority(%currentAction, 0)
		SetVar(__Me,"currentState",FIXEDSTRING:)   //clears state so this only happens once.
		
EVENTS

EVENT  FrontGateAttack
ON 
	OnTimer("CaptainAnimationTimer")
ACTIONS
	SetVar(__Me,"currentState",FIXEDSTRING:State_Hide)
	


[Linked Image]
http://i335.photobucket.com/albums/m468/SniperHF/StateMangerTutorial/myscript2_2.png

3. Using this script above I'm creating some NPC scheduling in my Day/Night cycle. This tutorial will use it the rest of the way. Once you get it working you can change the actions and state names to suit your own needs.

4. The State manager is a separate script file included with the editor. To start using it add the line in the INIT section "USING State_Manager".

5. Once you have created a charscript that uses the state manager, save your work and close the script editor. We'll be coming back to it later.




Add the charscript to your mod:

1. Open the resource Manager.
[Linked Image]

2. Create the proper folder tree under your mod:
[Linked Image]

3. Add a package with the name Scripts
[Linked Image]

4. Click add resource and Select Script.
[Linked Image]
[Linked Image]

5. Navigate to where your script file is saved and import it. I save all my scripts in Data\Public\MOD NAME HERE\scripts" This follows the Main game convention.
[Linked Image]

6. Make sure the correct scripts package is selected and then click okay for all.

7. Save your work and restart the editor, importing scripts causes the editor to crash.




Assign your new script to an NPC.

1. From the sidebar add the script to your NPC. Your script should now appear in the list.

2. Assign the necessary external variables.

[Linked Image]

3. Note the variable currentState. This variable is what you will use to set which actions your NPC should take.

As long as currentState is blank, none of the actions in the script for those states will run.



Making use of those States.

Now we are going to make use of the script.

1. Note from the charscript the behaviors named "State_". In my script it's State_Morning, State_Noon, State_Night, and State_Hide. The last one is specifically for one of my quests.

2. The simplest way to define an NPCs current state is to type in one of those states in this box:

[Linked Image]

3. This should be considered an NPCs default state as it will be what the character does immediately when the game loads. If you leave it blank the NPC will remain idle which could also be desirable.



Changing States during gameplay.

4. The main benefit of the State manager is the ease of which you can change NPC states on the fly through the story editor. If we consider the previous method your default state, then simply create conditional statements in the story editor for which you want to change NPC behavior.
5. The call for this is
Code
CharacterSetVarFixedString(CHARACTER_NPCHERE, "currentState", "State_Noon");

This script sets the variable "currentState" to the fixed string "State_Noon". In the example script this makes the NPC walk over to a trigger.

6. Since my script is for a day/night cycle these conditional statements go along with that cycle.
Code
IF
TimerFinished("TimeOfDay")
AND
Time(_,12,_)
THEN
CharacterSetVarFixedString(CHARACTER_NPCHERE, "currentState", "State_Noon");


From this you can see that when the timer finishes, and the time is 12, the state gets changed to Noon and thus the NPC will walk over to his spot.


Here is the script in action:



You can see the 3 different states in rapid succession as I have it sped up to test. Then I triggered the quest state "Hide" where the NPC takes cover from an attack on the town.



Clearing States and returning to idle.

If you don't make a state specifically for idle conditions, or just want to stop an NPCs actions for some reason you can use the same call as before. But instead leave the final string blank as such:
Code
CharacterSetVarFixedString(CHARACTER_NPCHERE, "currentState", "");

Think of this as deleting the sidebar entry you created for currentState as the string would be empty.

NOTES:
As I mentioned previously Larian uses them a lot for defining NPC actions before and after a quest. For a great example of this see the script "CYS_CookMorris"

Another state manager script that is very useful is CYS_GuardBowTraining. This script will work in any mod as it has external variables. Simply add it to a character and you can set the state to "State_Training". This will have your NPC repeatedly attack an item like the training guards in Cyseal. This is an ideal script to play around with since it will work without writing your own charscript and importing it.

There are many ways to accomplish these same tasks with charscripts or in the story editor. If you don't want an NPC to switch to a state you can simply not set it to do so. And using the story editor for every mundane NPC action or animation creates a heavy load on the game and can impact performance. Performance issues aren't a big deal for smaller mods though.

But the reason I like using the State_Manager is its very easy to create modular scripts which work for many different NPCs.
When you have scripts reacting to fixed events like timers or globalevents you might have to rewrite your script to use it for another NPC and import it.

Also you can very easily set conditions for testing without having to playtest up to that point first. Simply paste in the states you want to test.

Last edited by SniperHF; 30/07/15 10:06 PM.
Joined: Aug 2014
old hand
Offline
old hand
Joined: Aug 2014
A real meaty tutorial! I'd put the video up top to help visualize what the scripts are doing before we get into them. Also might be a good idea to link your day night cycle code for reference.

Question: In the "Clearing States and returning to idle" section, did you mean to have the code be "CharacterSetVarFixedString(CHARACTER_NPCHERE, "currentState", "");" instead of "CharacterSetVarFixedString(CHARACTER_NPCHERE, "currentState", "State_Noon");" ?

Otherwise, I'm not sure what you mean by leaving the final string blank.

I think a good tutorial would be the various steps of making a standalone mod, from overall design and writing, to terraining and all its many steps (atmosphere, textures, object placement, AI grid, etc), charscripts, to implementing quests, stat designs, balancing combat, final playtesting, etc. Link to other tutorials for more detail, but it would just be general roadmap. Certainly would be a big one, but I think it'd help people understand what steps making a mod entails, and the best order to approach things, and just a good resource for linking to other tutorials.

Joined: Jun 2013
old hand
OP Offline
old hand
Joined: Jun 2013
Originally Posted by Baardvark

Question: In the "Clearing States and returning to idle" section, did you mean to have the code be "CharacterSetVarFixedString(CHARACTER_NPCHERE, "currentState", "");" instead of "CharacterSetVarFixedString(CHARACTER_NPCHERE, "currentState", "State_Noon");" ?

Otherwise, I'm not sure what you mean by leaving the final string blank.


Yes indeed, fixed.

I still haven't really nailed down exactly how I'm going to charscript out the schedules. Right now I just did a cheap morning/noon/night.

But I'm thinking what might be better is have one single state for "on the cycle" and then have those listen to global events. Then use the state manager instead of switching states, only to switch off the cycle when needed. I think that's more efficient anyway.

My original plan was to stick all the NPCs that use the day/night cycle in a DB and check each one and set the state based on which DB they are in. If the NPC is in the cycle DB they do those things and if not they do quest related stuff.

That way is less elegant but it has the benefit of being much more configurable.

If all my NPCs react on globals then they would all be changing cycles at the same time and that would be kind of weird. And if I make separate globals that puts me right back at making separate scripts.

Still not sure yet. I think the more clunky script solution would actually produce better results in game.


Quote

I think a good tutorial would be the various steps of making a standalone mod, from overall design and writing, to terraining and all its many steps (atmosphere, textures, object placement, AI grid, etc), charscripts, to implementing quests, stat designs, balancing combat, final playtesting, etc. Link to other tutorials for more detail, but it would just be general roadmap. Certainly would be a big one, but I think it'd help people understand what steps making a mod entails, and the best order to approach things, and just a good resource for linking to other tutorials.


I'm too bad at some of this stuff unfortunately ouch
Especially writing and map making. Heck I've even forgot some of the basics in setting up the editor for a new mod since I only did it a couple times like 10 months ago. I do have a HUGE list of notes though that I might make into a presentable DOC.

I'll have to stick to specific systems tuts for now. Though once I actually finish my mod I do plan on doing some more comprehensive ones like "design a quest" or "branching dialog". The latter being really damn hard to do in D:OS.

I had to cut down some of my own dialog ambitions because of how time consuming it is. I'm sure it's time consuming in other editors, but having to keep track of, flag out, and pass choices between nodes is a HUGE pain. It really is a "keyword" editor.

Last edited by SniperHF; 30/07/15 10:26 PM.
Joined: Aug 2014
old hand
Offline
old hand
Joined: Aug 2014
NPC Day Night scheduling really does sound like a nightmare (and complex dialog trees are too.) It seems like you'd need to have tons of triggers for each NPC, and have scripts particular to each NPC.

Didn't do it myself, but I think flow charts would be immensely useful for making complex dialog trees. I really wish the dialog editor was visually more capable of organizing complex dialog trees. Possibly setting up a few dialog templates would help speed things up a lot, though you'd have to edit the template to fit every quest to make sure flags don't overlap, set special conditions and actions, add or subtract certain trees, etc.

Specific system tutorials are plenty useful too. There's no hurry for a meta-tutorial, though some form of it might be nice for when the enhanced edition comes out, because that could revitalize the modding scene a bit and people would like a guide to give them step-by-step advice. I could definitely help with some sections, though I haven't really been actively modding for months.

Joined: Jun 2013
old hand
OP Offline
old hand
Joined: Jun 2013
Originally Posted by Baardvark
NPC Day Night scheduling really does sound like a nightmare (and complex dialog trees are too.) It seems like you'd need to have tons of triggers for each NPC, and have scripts particular to each NPC.


My idea right now is to make a set of 3-4 modular scripts with EXTERNs and maybe 3 states + quests as required. One of the nice things about the state manager is you can combine scripts. So I can have a generic Day/Night script and then separate scripts for quests.

So say the script has an EXTERN for:
Awake position
Sleep Position
Bed
Some Mid Day activity.

But to spice it up I could EXTERN animations too.
So during the awake position I could put different animations in each NPCs sidebar with an EXTERN (or random) timer for the animation.

And to modify the times so every NPC isn't acting on a pattern I could stick them all in a DB. So NPCs that wake up at 8am go in the DB_Wakeup8((CHARACTER)_NPC).

And when my timer fires for 8am I go:
Code
//8am
IF
TimerFinished("TimeOfDay")
AND
Time(_,8,_)
AND
DB_Wakeup8((CHARACTER)_8AMNPC)
THEN
CharacterSetVarFixedString(_8AMNPC, "currentState", "State_Morning");


Then bam, every 8AM NPC switches at 8am. No separate script required. Just a few quick definitions in the INIT section. And if I need an NPC to stop doing it I just NOT the DB when the quest starts.

It's a little more story editor heavy than I would like but I think it's the most effective solution on a time/effectiveness basis.

Quote

Didn't do it myself, but I think flow charts would be immensely useful for making complex dialog trees. I really wish the dialog editor was visually more capable of organizing complex dialog trees. Possibly setting up a few dialog templates would help speed things up a lot, though you'd have to edit the template to fit every quest to make sure flags don't overlap, set special conditions and actions, add or subtract certain trees, etc.


I use a naming convention for each node in more serious dialog trees. Plus I keep a list of flags.

So if the dialog starts with:
Have you seen my cat?
I'll do:
Response1
Response2
Response3

Then if each response has a branch it will be
Response 1.1
Response 1.2
Response 1.3

Response 2.1
Response 2.2
Response 2.3

Response 3.1
Response 3.2
Response 3.3

But what gets complicated is when you are supposed to be able to jump branches. Then the system breaks down. The main workaround for this I use is just straight up brute force. Duplicate nodes.

But I often don't follow my own convention. If I were starting over from scratch I would.

The other thing I do is extra flagging. One thing that is not conducive to trees is that it doesn't automatically remember and clear nodes you used. So I simply local flag every response to correspond with its node name and place the same action on the node.

In more simple dialogs I just use the relevant global flags. But the problem is sometimes I clear global flags so then I have to go back and make an extra local. Which I only realize after testing it, 30 hours later.



Joined: Aug 2014
old hand
Offline
old hand
Joined: Aug 2014
Ah, I see now. You can set your own EXTERN variables for every NPC. You can use the same template script, but you still need to place like three position triggers for where they move.

If you attack an NPC or otherwise interrupt them, do they revert to their normal schedule without hitch. Also, how are you dealing with transitioning to different zones with your day night cycle? I guess since you have 24 hours (and 24 atmospheres, right?) the atmosphere is only static momentarily. NPC scheduling still works when you go from one zone to another?

I was also doing the same Response1, response 1.1, etc. thing, but jumping branches really screws the organization up, and brute forcing is inelegant and just sets up more opportunities for bugs. Not sure if there's a good way to really cut down the time implementing dialog enormously. I still think having like 5-10 templates set up with the greeting and goodbye, and then two choices, three choices, two choices that each lead to two different choices, etc. would help save a lot of time setting each NPC up since you could just copy and paste in the dialogs and it'd work.

Last edited by Baardvark; 31/07/15 02:51 AM.
Joined: Jun 2013
old hand
OP Offline
old hand
Joined: Jun 2013
I don't know enough yet about combat situations and what they do afterward. Still kinda prototyping. My guess is yes they will return to their currentState behavior since that's defined by USAGE PEACE. Thus when combat is happening they will stop doing that. I think the defaultcharacter script will handle that.

I'm not using 24 atmospheres, though I might later. All daylight hours have an atmosphere. I have two night atmospheres. The first night atmosphere is immediately after the sun goes down till about 1am. The only reason I have two night atmospheres is to stealthily move the "sun" back over to the east. If you don't move the sun back to the east before morning you'll get a weird shadow transition when the sun comes up. You can't naturally move the sun below the map as if the world were round.

I have no solution for moonlight currently. There's only one sun, and you have to use that for moon by changing the color.

I don't know about separate zones because I don't have any. I went for a dense content mod primarily focused on quests and I reuse environments. Primarily to cover up my own map making deficiencies and also because the map was done and I don't feel like expanding it now. Though if the EE breaks my map I will take that opportunity. But I'm hoping to release before the EE, at least a beta. So my mod might have it's own "EE" lol.

But anyway I'm pretty sure that problem could be solved easily. There are a number of scripts larian runs on area transition and I could just bolt my stuff on to that.

Oh and on the trigger positioning and such, there are tricks to get around that. For starters sometimes I'll just use items which are already placed. All my NPCs who sit in chairs at the diner can just walk to existing chairs. NPCs that do need a trigger can reuse some of them. If you look in the tutorial you'll notice I used ownership triggers. Since I already placed those they are easy to reuse. Or my worker NPCs that go out and smash stuff with pickaxes can move to those objects.

Last edited by SniperHF; 31/07/15 03:27 AM.
Joined: Aug 2014
old hand
Offline
old hand
Joined: Aug 2014
Lots of stuff clarified there. Good idea to reuse ownership triggers. Are you going to do an ownership system tutorial? Probably pretty intertwined with the guard system code, too. And attitude. :P What's your plan so far? You're tutorials are quite good. Making me think about working on ODAD again, though I'm still iffy about spending a lot of time before the EE. At least there'll be the old version of D:OS still to run the mods, though.

Joined: Jun 2013
old hand
OP Offline
old hand
Joined: Jun 2013
I haven't monkeyed around with the guard system much yet. I tried playing with it a little bit but it wasn't working quite right. Possibly due to a problem I found yesterday where my AAA_FirstGoal file was under "start" when it shouldn't have been.

That was also causing problems with exploration XP, that's what I was trying to fix.

I think to get guards and such working right I would need to make a jail first. Right now any time you steal in my mod they warn you twice then attack you. Better behavior than how the editor functions without the system anyway. Without the jail it's a fight to the death and forces a reload. I did look at it a couple months ago and it's pretty damn complicated. The Guards.txt file is nearly double the size of the next biggest one. And it intertwines with the second biggest file NPC_Actions.

Having a full blown guard system isn't totally necessary for my mod so it's something I'll look at later.

Last edited by SniperHF; 31/07/15 07:13 PM.
Joined: Aug 2014
old hand
Offline
old hand
Joined: Aug 2014
Yeah the guard code is pretty gnarly, though I think you could just paste it in and figure out the correct databases and it'd work dandy without 100% understanding the code. They do talk about guards some in the Useful Osiris Systems doc.

The Dialogs doc also reminded me that you can make dialog templates and only import certain nodes. So you could make a huge tree of like three choices each with like 5 successive choices, and then just import the nodes you need for each quest, and I believe all the pushes and flags and what not will be set up. Rename the nodes, add the dialog and any special actions, and it should save a lot of time over essentially remaking the template every time you make a dialog.

Joined: Jun 2013
old hand
OP Offline
old hand
Joined: Jun 2013
I you haven't read them yet, the files included with the special edition of the game are really good as well. Not as modding specific but useful. There's also some images of how they layout the levels for combat and such. I decided to use a similar method.

Last edited by SniperHF; 01/08/15 12:17 AM.
Joined: Aug 2014
old hand
Offline
old hand
Joined: Aug 2014
Na, I haven't seen those files. Sounds cool.


Link Copied to Clipboard
Powered by UBB.threads™ PHP Forum Software 7.7.5