Larian Banner: Baldur's Gate Patch 9
Previous Thread
Next Thread
Print Thread
#567752 18/08/15 05:54 AM
Joined: Aug 2015
J
stranger
OP Offline
stranger
J
Joined: Aug 2015
How do i go about making an NPC intermittently speak the content of different strings that i've defined in the TranslatedStringKey editor? I want the text to appear above the head of said NPC.

Joined: Jun 2013
old hand
Offline
old hand
Joined: Jun 2013
If you mean just the text from the translated string key that's pretty easy.

I'm gonna assume you want them to be randomly selected? If not that changes everything. Also do you want the text to display when you click on the NPC or just anytime?

You could run it on a timer:

Code
INIT:
DB_OverheadText(0, "Text0");
DB_OverheadText(1, "Text1");
DB_OverheadText(2, "Text2");
DB_OverheadText(3, "Text3");
DB_OverheadText(4, "Text4");
DB_OverheadText(5, "Text5");
TimerLaunch("TextTimer",10000);


KB:
IF
TimerFinished("TextTimer")
AND
Random(5,_TextNum)    // 5 should be the maximum integer.
AND
DB_OverheadText(_TextNum,(STRING)_TextToShow)  //not sure if you need (STRING) or not
THEN
CharacterDisplayText(YOURCHARACTER,_TextToShow);
TimerLaunch("TextTimer",10000);  //Restarts the same timer.



I'm not 100% this script will work since I'm away from my access to the editor at the moment. But it should be pretty close. I'll double check it tomorrow.




The prim and proper way to do this is using what is called an Automated Dialog. This does not use the TSK but instead uses the normal keyword editor. This is helpful because you can define multiple phrases that will randomly(or not) appear.

There is some information on Automated Dialogs in the file "Useful Osiris Systems":
http://www.divinityoriginalsin.com/download.php

This is probably one of the things I'll do a tutorial on at some point. The call is DialogStartOneSpeakerDialog if you wanna dig into that. Once you get it going it's much cleaner to use than the TSK.

Last edited by SniperHF; 18/08/15 08:05 PM.
Joined: Jun 2013
old hand
Offline
old hand
Joined: Jun 2013
Just an FYI, I tested this and it almost worked. Having never used the "RANDOM" query before I wasn't sure if it used 0 or not. Turns out it does.

So you would need to add a DB entry for 0.
DB_OverheadText(0, "Text0");
DB_OverheadText(1, "Text1");
DB_OverheadText(2, "Text2");
DB_OverheadText(3, "Text3");
DB_OverheadText(4, "Text4");
DB_OverheadText(5, "Text5");


Then it's good to go.

Last edited by SniperHF; 18/08/15 08:36 PM.
Joined: Aug 2015
J
stranger
OP Offline
stranger
J
Joined: Aug 2015
Worked well, thank you. Is this going to be a resource drain though, since it will be firing all the time regardless of where the player is?

Joined: Jun 2013
old hand
Offline
old hand
Joined: Jun 2013
The tl:dr version is I probably wouldn't worry about it for now.


Maybe it could cause issues. I've got way more intensive stuff running like this and it doesn't seem to cause a problem. But then again my module is about 1/3rd the size of Div:OS Act 1. But to give you an idea, I have a scene where I put at least 25 global NPCs all seated in a little auditorium and they all chant overhead texts (and I added animations) like this in unison several times. No issues.



You could always throw another query on it like:

Code
IF
TimerFinished("TextTimer")
AND
Random(5,_TextNum)    // 5 should be the maximum integer.
AND
DB_OverheadText(_TextNum,(STRING)_TextToShow)  //not sure if you need (STRING) or not
AND
_Player.isPlayer()
AND
CharacterCanSeeCharacter(YOURCHARACTER, _Player,1) 
THEN
CharacterDisplayText(YOURCHARACTER,_TextToShow);
TimerLaunch("TextTimer",10000);  //Restarts the same timer.   


That way it only displays text when your character can be seen.

This does introduce another problem though in that the timer still has to restart but it will not since the CANSEECHARACTER query will not always be true. So you could add another conditional after this one:

Code
IF
TimerFinished("TextTimer")
THEN
TimerLaunch("TextTimer",10000); 


And then simply remove the timer launch from the statement with the display text.



There's a few different ways I can think of doing this that would be even less intensive.

You could have them fire from a character event in a charscript. That would probably be the least resource intensive way of going about it. Charscripting is annoying though so if it's just a few NPCs I'd leave it in the story editor.

If we're talking a larger campaign with lots of NPCs with this type of overhead text I would switch it to an automated dialog AND a charscript.


And just as a random note: If you aren't already using it, I would say bite the bullet early and switch over to the Standalone Project Template. Or you could do what I did and piecemeal the scripts over.

Last edited by SniperHF; 19/08/15 03:20 AM.
Joined: Aug 2015
J
stranger
OP Offline
stranger
J
Joined: Aug 2015
Great. I was actually thinking of using a character script that makes a bunch of NPC's move to a location and then dissapear when the player enters a trigger. Ie, player enters trigger ---> NPC's starts walking ---> NPC's dissapear when they reach destination. Something like:

INIT

CHARACTER:__Me

EXTERN TRIGGER:%Waypoint1 = null

EVENTS

EVENT testings
ON
?
ACTION
function ?

In story:

IF
CharacterEnteredTrigger(x, y)
THEN
SetGlobalEvent(testings) <-----?

Joined: Jun 2013
old hand
Offline
old hand
Joined: Jun 2013
Zoltan pretty much wrote the book on charscripts here:
http://larian.com/forums/ubbthreads...Words=scripts&Search=true#Post563932

I mostly just hack them together by reading larian script files that I unpacked.



Code
INIT

CHARACTER:__Me

EXTERN TRIGGER:%Waypoint1 = null



EVENTS

EVENT LeaveArea
ON
    OnGlobalEventSet("Leave")
ACTIONS
    CharacterDisappear(__Me,CHECK ARGUMENTS)  //I believe this one is the same as CharacterDisappearOutofSight from the story editor, check the arguments.  It might not be.



In story:

IF
CharacterEnteredTrigger(_Player, TRIGGER)
AND
_Player.isPlayer()
THEN
GlobalSetEvent("leave");
TriggerUnregisterforPlayers(TRIGGER);


One of the things Zoltan didn't mention, or maybe even know about at the time is that you can directly call specific events from the charscript in the story editor. Those events are exactly the same as character events.

So for example, if your character completes the event "LeaveArea", you can make a statement based on that in the story editor.

Code
IF
CharacterEvent(YOURCHARACTER,"LeaveArea")
THEN
Whatever you want to do.


I've been using this a ton lately for chaining events together. It really helps nail timing of scripted sequences.

Last edited by SniperHF; 30/08/15 04:12 AM.
Joined: Aug 2015
J
stranger
OP Offline
stranger
J
Joined: Aug 2015
Zoltans guide is good but it's pretty difficult to move from the guide into actual practice smile. As for the thing i was doing, i was going to use CharacterMoveTo(). For that function/command i need a position. To get a position i need an object (a point trigger for example?) but i'm unsure how to code all of this.

INIT

CHARACTER:__Me

EXTERN TRIGGER:%Waypoint1 = null
FLOAT3:%pos=null


EVENTS

EVENT LeaveArea
ON
OnGlobalEventSet("Leave")
ACTIONS
GetPosition(Teleportation_point_Jail, %pos)
CharacterMoveTo(%pos) //I believe this one is the same as Chara

Joined: Jun 2013
old hand
Offline
old hand
Joined: Jun 2013
So for the CharacterMoveTo call, it doesn't have to be a FLOAT3 despite what the little help text says. I would just make it a trigger like how you have Waypoint1 setup.

You can probably remove GetPosition too.

The main thing you are missing right now is a BEHAVIOR section with REACTIONs.

Usually how Larian does these scripts is an EVENT is triggered by something like a globalevent, that EVENT sets a priority for the REACTION which starts that set of behavior. The NPC will keep doing that behavior until you tell it to stop by changing the priority to be higher than the current action or you simply set the current action to 0. That's what I did below:



To do it exactly how you described, this is what you need I think:

[Linked Image]


Code
INIT

CHARACTER:__Me

EXTERN TRIGGER:%Waypoint1 = null
EXTERN STRING:%LeaveGlobal = NPCLeaves


BEHAVIOUR

REACTION Leave, 0
	USAGE PEACE
	ACTIONS
		CharacterMoveTo(%Waypoint1)
		CharacterSetOffStage()
		SetPriority("Leave", 0)

EVENTS

EVENT LeaveArea
ON
	OnGlobalEventSet(%LeaveGlobal)
ACTIONS
	SetPriority("Leave", 1100)



In action:



The reason I suggested disappear out of sight is I think it looks better. So they'll walk off in the direction you specify, you don't have to place a trigger, and they fade away instead of jarringly get set off stage. The correct call in Charscript for that is "CharacterMoveOutOfSight(100)"



The 100 number is just an integer which sets the direction they walk off in. Takes a little bit of playing around to figure out what number corresponds to which direction. Think it takes negative numbers too.


Do you know how to import scripts into your mod through the resource manager? If you don't I have a guide with pictures included in the State Manager charscript thread I made.
http://larian.com/forums/ubbthreads.php?ubb=showflat&Number=567495#Post567495


Personally I consider learning char and item scripts the absolute lowest priority of modding D:OS. They are powerful and important for systemic actions but WAY too much work relative to the results.

Last edited by SniperHF; 30/08/15 04:11 AM.
Joined: Aug 2015
J
stranger
OP Offline
stranger
J
Joined: Aug 2015
This is all great, i've learned a lot more about using character scripts, thanks.

Joined: Jun 2013
old hand
Offline
old hand
Joined: Jun 2013
No problem smile.

Any ideas for other tutorials to post? Been hankering to make another one but not sure what to do next.

Joined: Aug 2014
old hand
Offline
old hand
Joined: Aug 2014
Not sure, but don't do a dialog tutorial since apparently there's a shiny new dialog editor in D:OS2, though not sure if that will come with the EE of D:OS. A lot of people would probably appreciate a thorough traipse through the various stat files. I've thought about making a video on them, but I'm lazy.

Joined: Jun 2013
old hand
Offline
old hand
Joined: Jun 2013
Personally I think the stat files are pretty well covered by the creating combat doc, though a searchable tutorial on the board here isn't a bad idea. Maybe with an emphasis on real in-game results.

One thing that could be better explained is how the mapped values work at various levels. Though I'm still cloudy on that myself.

One thing I was thinking of doing is a scripted scene building tutorial. Like how to make events and timings line up and such. Calling actions from within dialog and what limits there are for the player character vs NPCs.

Last edited by SniperHF; 30/08/15 04:13 AM.

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