Larian Banner: Baldur's Gate Patch 9
Previous Thread
Next Thread
Print Thread
#555234 20/09/14 04:49 AM
Joined: Aug 2014
old hand
OP Offline
old hand
Joined: Aug 2014
So I've looked in the goals and found scripting for ownership. I think I get most of it, but some of it I don't quite understand.
From what I can tell, you place triggers inside owned areas, and then you set up a database to connect the trigger with a character. Hopefully someone can make sure I'm on the right track and answer my questions (in the code).I don't want to spread misinformation, but I think I'm mostly correct about how it works. Just some confusion here and there.

Thanks


Code

INIT

// There's three databases (I think): 
"ItemOwnerShipTriggers", which relates a region with a trigger and a character to define what triggers are associated with what characters.
"ItemOwnershipClearItem" defines specific exceptions to ownership. They're mostly stuff like doors and chairs. 
"ItemOwneShipIgnoreTemplates" defines root templates (e.g., campfires) that are never owned.

ItemOwnerShipTriggers("Cyseal",TRIGGER_CYS_Ownership_Cyseal_LegionCamp,CHARACTER_CYS_GuardBarrackKitchen);
ItemOwnerShipTriggers("Cyseal",TRIGGER_CYS_Ownership_Cyseal_Dietmar,CHARACTER_CYS_Dietmar);

ItemOwnerShipClearItem("Cyseal",ITEM_TeleportPyramidB);
ItemOwnerShipClearItem("Cyseal",ITEM_CYS_WarehouseBackDoor);

ItemOwnerShipIgnoreTemplates("LTS_Campfire_A_8c515a6e-381f-4fa6-b459-6d450b8258de");


And KB is...

Code
PROC
PROC_Init_SetItemOwners((STRING)_Region)
AND
ItemOwnerShipTriggers(_Region,_Trigger,_Owner)
THEN
TriggerSetItemOwner(_Trigger,_Owner);
ProcTriggerRegisterForPlayers(_Trigger);
NOT ItemOwnerShipTriggers(_Region,_Trigger,_Owner);
DB_TempItemOwnerShipTrigger(_Region,_Trigger);

//So this section defines a procedure that sets owners. "TriggerSetItemOwner" is the primary hardcoded function here, 
I believe.
 Unless it's defined somewhere else, but I'm not sure...

PROC
PROC_Init_ClearItemOwners((STRING)_Region)
AND
ItemOwnerShipClearItem(_Region,_Item)
THEN
ItemClearOwner(_Item); // the main hardcoded command
NOT ItemOwnerShipClearItem(_Region,_Item);

//This is the procedure which sets exceptions. Note that it's AFTER the procedure above 
because Osiris reads code from top to bottom.
 So it sets ownership, then it sets exceptions.

PROC
PROC_Init_ClearItemOwners((STRING)_Region)
AND
DB_TempItemOwnerShipTrigger((STRING)_Region,(TRIGGER)_Trigger)
AND
ItemOwnerShipIgnoreTemplates(_Temp)
THEN
NOT DB_TempItemOwnerShipTrigger(_Region,_Trigger);
TriggerClearItemTemplateOwners(_Trigger,_Temp);

//This code defines the items that will always be ignored by ownership.
 It looks like you can define procedures multiple times, 
and I guess the code combines together and doesn't replace one another.

IF
ItemOwnerShipTriggers(_Region,_Trigger,_Owner)
AND
CurrentLevel(_Region)
THEN
PROC_Init_SetItemOwners(_Region);
PROC_Init_ClearItemOwners(_Region);

//This section actually runs the procedures that were defined above.
 Whatever level you're in, ownership will be defined. 
I assume doing this way means scripts aren't be run for regions that you currently aren't in? 
To save on processing or something?

IF
RegionStarted(_Region)
THEN
PROC_Init_SetItemOwners(_Region);
PROC_Init_ClearItemOwners(_Region);

//I'm not what the difference between "RegionStarted" and "CurrentLevel" are.
 Someone could maybe explain why there's both these sections?

IF
CharacterEnteredTrigger(_Player,_Trigger)
AND
ItemOwnerShipTriggers(_,_Trigger,_Owner)
THEN
CharacterSetVarInteger(_Player,"InOwnedArea",1);
CharacterSetVarCharacter(_Player,"OwnedAreaOwner",_Owner);

//I don't understand the purpose of this section at all. Maybe it's used to initiate certain dialogs?
 If you're InOwnedArea
 then OwnedAreaOwner will respond to you with certain universal dialog responses to stealing?

IF
CharacterLeftTrigger(_Player,_Trigger)
AND
ItemOwnerShipTriggers(_,_Trigger,_Owner)
THEN
CharacterSetVarInteger(_Player,"InOwnedArea",0);




Last edited by Baardvark; 20/09/14 04:54 AM.
Joined: Jul 2014
R
addict
Offline
addict
R
Joined: Jul 2014
You are pretty much correct about what the script does. It links Items within a certain Area (Trigger) to be owned by a Character when the map is loaded. It also sets certain variables within a Character's CharScript when they enter an Owned Area (InOwnedArea and OwnedAreaOwner).

The code is a little bit confusing without any other context, but I'll try my best to walk through a Trace of the code.

The first thing that happens when you enter a map (a Region) is this:
Code
IF
RegionStarted(_Region)
THEN
PROC_Init_SetItemOwners(_Region);
PROC_Init_ClearItemOwners(_Region);


Say for example you enter Cyseal. _Region will be "Cyseal". It then goes to the first PROC, PROC_Init_SetItemOwners

Code
PROC
PROC_Init_SetItemOwners((STRING)_Region)
AND
ItemOwnerShipTriggers(_Region,_Trigger,_Owner)
THEN
TriggerSetItemOwner(_Trigger,_Owner);
ProcTriggerRegisterForPlayers(_Trigger);
NOT ItemOwnerShipTriggers(_Region,_Trigger,_Owner);
DB_TempItemOwnerShipTrigger(_Region,_Trigger);

This portion is really the main powerhouse of the script. Because we're saying that we entered Cyseal, "Cyseal" is passed to the _Region variable here.

It then checks the AND, which checks the ItemOwnerShipTriggers database for entries with a _Region of "Cyseal", and outputs a TRIGGER and a CHARACTER to _Trigger and _Owner variable respectively.

So say for example we have this in the INIT:
Code
ItemOwnerShipTriggers("Cyseal",TRIGGER_CYS_Ownership_Cyseal_Dietmar,CHARACTER_CYS_Dietmar);

Because "Cyseal" matches, it outputs TRIGGER_CYS_Ownership_Cyseal_Dietmar to _Trigger and CHARACTER_CYS_Dietmar to _Owner.

The function then continues into the THEN statements.

-TriggerSetItemOwner is indeed a hardcoded Story function, and presumably links the Trigger to the Owner character.

-ProcTriggerRegisterForPlayers is presumably defined within the _PROC file (elsewhere in the Story files).

-NOT ItemOwnerShipTriggers(_Region,_Trigger,_Owner); This removes the entry from the database after ownership has been set, so that subsequent checks won't set ownership again.

-DB_TempItemOwnerShipTrigger(_Region,_Trigger); This creates a Database entry with "Cyseal" and TRIGGER_CYS_Ownership_Cyseal_Dietmar in this example.


After PROC_Init_SetItemOwners finishes, it moves on to the next part of the RegionStarted code, PROC_Init_ClearItemOwners(_Region);
Code
PROC
PROC_Init_ClearItemOwners((STRING)_Region)
AND
ItemOwnerShipClearItem(_Region,_Item)
THEN
ItemClearOwner(_Item); // the main hardcoded command
NOT ItemOwnerShipClearItem(_Region,_Item);


PROC
PROC_Init_ClearItemOwners((STRING)_Region)
AND
DB_TempItemOwnerShipTrigger((STRING)_Region,(TRIGGER)_Trigger)
AND
ItemOwnerShipIgnoreTemplates(_Temp)
THEN
NOT DB_TempItemOwnerShipTrigger(_Region,_Trigger);
TriggerClearItemTemplateOwners(_Trigger,_Temp);

Note that there are two separate instances of the PROC. As such, they are checked sequentially starting with the top one (or whichever is loaded first, in the case that the multiple is in a different Story file).

At this point of the example the variables/databases look like this:

_Region: "Cyseal"

DB_TempItemOwnerShipTrigger("Cyseal", TRIGGER_CYS_Ownership_Cyseal_Dietmar);

ItemOwnerShipClearItem("Cyseal",ITEM_TeleportPyramidB);
ItemOwnerShipClearItem("Cyseal",ITEM_CYS_WarehouseBackDoor);

ItemOwnerShipIgnoreTemplates("LTS_Campfire_A_8c515a6e-381f-4fa6-b459-6d450b8258de");


So the first AND statement of the first PROC is checked
Code
ItemOwnerShipClearItem(_Region,_Item)

In this example, this checks for "Cyseal" being the first entry and outputs the second one into _Item. Because of the INIT, ITEM_TeleportPyramidB is outputted into _Item.

Code
ItemClearOwner(_Item); // the main hardcoded command
NOT ItemOwnerShipClearItem(_Region,_Item);

This removes the owner from the Pyramid and removes the Database entry for the Pyramid.

The second PROC is then checked.
Code
AND
DB_TempItemOwnerShipTrigger((STRING)_Region,(TRIGGER)_Trigger)
AND
ItemOwnerShipIgnoreTemplates(_Temp)
THEN
NOT DB_TempItemOwnerShipTrigger(_Region,_Trigger);
TriggerClearItemTemplateOwners(_Trigger,_Temp);

The first AND indeed has "Cyseal" and a _Trigger, so it outputs TRIGGER_CYS_Ownership_Cyseal_Dietmar to _Trigger.

The second AND retrieves the value from the ItemOwnerShipIgnoreTemplates database. In this case, "LTS_Campfire_A_8c515a6e-381f-4fa6-b459-6d450b8258de" is put into _Temp.

The THEN statement then removes the first AND's Database entry (so subsequent calls won't work) and removes the owners from the IgnoreTemplate (the Campfire) should it be within the Trigger area.

That should cover the three main PROCs. The other thing of note is this:
Code
IF
ItemOwnerShipTriggers(_Region,_Trigger,_Owner)
AND
CurrentLevel(_Region)
THEN
PROC_Init_SetItemOwners(_Region);
PROC_Init_ClearItemOwners(_Region);

Because ItemOwnerShipTriggers is a Database, this technically runs whenever three values are entered into the ItemOwnerShipTriggers database (such as from INIT). This would normally run at the start of the game, but because CurrentLevel returns CharacterCreation (in Main), databases that use "Cyseal" won't trigger the PROCs.

Otherwise, this is identical to the RegionEntered. They fulfill the same function; this works at Game Start (when RegionEntered hasn't occurred), and RegionEntered works everytime afterwards upon entering a new map.

The last part of the script is this:
Code
IF
CharacterEnteredTrigger(_Player,_Trigger)
AND
ItemOwnerShipTriggers(_,_Trigger,_Owner)
THEN
CharacterSetVarInteger(_Player,"InOwnedArea",1);
CharacterSetVarCharacter(_Player,"OwnedAreaOwner",_Owner);


IF
CharacterLeftTrigger(_Player,_Trigger)
AND
ItemOwnerShipTriggers(_,_Trigger,_Owner)
THEN
CharacterSetVarInteger(_Player,"InOwnedArea",0);

These depend on ItemOwnerShipTriggers still existing, so presumably it's reset/refilled elsewhere in the code because the above code removes Entries from this Database upon entering the map.

That being said, the purpose of these two codes is to set CharScript variables. These variables can presumably be used elsewhere in the Story (such as for the Thievery script), but on its own this is just setting/unsetting a variable.

Joined: Aug 2014
old hand
OP Offline
old hand
Joined: Aug 2014
Thanks Rhidian! Makes a lot more sense now. Might turn our explanations into a tutorial for the wiki soon.

One more question: are there any other ways to set ownership? Or is using this script the only way.

Cheers

Last edited by Baardvark; 20/09/14 07:24 AM.

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