Larian Banner: Baldur's Gate Patch 9
Previous Thread
Next Thread
Print Thread
Joined: Oct 2017
H
Hyped Offline OP
stranger
OP Offline
stranger
H
Joined: Oct 2017
Hi,

I noticed that sometimes ''IF'' gets replaced by a query or proc. I have read the docs about scripting and can't seem to understand how queries and procs work.

Does anyone have a simplyfied explanation since my english isn't my native language.

These questions might help your answer so i can understand it:

- What is it good for?
- What should the prefix be named? (QRY_MyPrefix_QueryName((TYPE1)_Param1[,(TYPE2)_Param2..])
- What is the difference between the query and proc?

thanks in advance <3

Joined: Jul 2014
Location: East Coast
journeyman
Offline
journeyman
Joined: Jul 2014
Location: East Coast
First, you will never see a QRY or PROC used in an IF, those are strictly for events like CharacterUsedSkillOnTarget.

Make sure you know the difference between Query and QRY, as well as Call and PROC.


Query is an internal call that takes in fields and returns something. These calls usually pose a question (HasActiveStatus) or specifically state the word get (GetCharacterAbility).

QRY is a very strange way to get a divergent code path (as well as commonalize a conditional statement used across multiple events), meaning it lets you say "Do A OR Do B". A QRY is able to return a DB_NOOP call, which kills the current code path. This lets you, for example, do different things based on if a target is Frozen or Burning without having to hook into the same event twice (more on why this is important later).

A Call is simply a function with no return value. You likely figured this out already. It does something, given arguments. Easy as that.

A PROC is best described as a re-usable function, and it also lets you do multiple reactions to an Event. Say for example, you wanted anyone hit by Fireball to be Burning(pretend Fireball doesn't already burn). Additionally, if they were already Burning, you wanted to Fear them. Again, this would normally take 2 events. But with a proc, it can now be done with a single event.


Now, why is reducing the number of events important? Events are incredibly generic. You are working with a status, but which one? A character did something, but who? Starting at an Event means you are going to need to filter, and in OR or ALSO cases, you have already done this work once. Why do it in every consecutive place if you are always checking "This was a player" and "Was the spell cast fireball?" (or more realistically, "Was the spell cast one of these spells that do custom things in my DB?").


I tried to give very simple examples. Try to write a QRY and PROC given the above examples and let me know what you come up with. Make sure to reference https://docs.larian.game/Osiris_Overview if you need more help.

Last edited by Sinistralis; 24/10/17 10:01 PM.
Joined: Mar 2016
Location: Belgium
T
addict
Offline
addict
T
Joined: Mar 2016
Location: Belgium
A small correction:
Quote

A QRY is able to return a DB_NOOP call, which kills the current code path.

Defining a database fact is not a call. There is also nothing special about defining DB_NOOP(1) compared to defining any other database fact.

A user-defined query only succeeds (i.e., a rule calling a query will only continue checking the next condition) if all conditions of one of the query definitions succeeds. The issue is that when all conditions of a query succeed, you need to write at least one action. If there is nothing that the query needs to do if it succeeds (like defining a database fact with its result), then the convention is to define the (dummy) database fact DB_NOOP(1).

Joined: Nov 2017
J
stranger
Offline
stranger
J
Joined: Nov 2017
I have read this thread 3 times, and I am still no closer to understanding how Proc works. Can someone post a screen cap or a reference to some specific code and explain how that piece works? I simply have no idea how to use a proc function.

Joined: Nov 2017
J
stranger
Offline
stranger
J
Joined: Nov 2017
Regarding my above post, what confuses me most is what makes a proc do its thing. IF THEN is pretty straightforward, but what activates the proc?

Joined: Oct 2017
Location: United Kingdom
journeyman
Offline
journeyman
Joined: Oct 2017
Location: United Kingdom
Ok.. say you have a blue and red crystal, and if you pick any of them up a healing status gets put on the player. But only if you are level 3 or above. Then use this:

Code
IF
ItemTemplateAddedToCharacter(_BlueCrystal,_,_Player)
THEN
PROC_CrystalEffects((CHARACTERGUID)_Player);

IF
ItemTemplateAddedToCharacter(_RedCrystal,_,_Player)
THEN
PROC_CrystalEffects((CHARACTERGUID)_Player);

PROC
PROC_CrystalEffects((CHARACTERGUID)_Player)
AND
CharacterGetLevel(_Player,_Level)
AND
_Level >= 3
THEN
ApplyStatus(_Player,"HEALING",8.0);


Now, if the player is a human and you wanted to apply a blinded status if so, then you could add below:

Code
PROC
PROC_CrystalEffects((CHARACTERGUID)_Player)
AND
CharacterGetRace(_Player,0,_Race)
AND
_Race == "Human"
THEN
ApplyStatus(_Player,"BLIND",8.0);


You can now call this PROC and do these things at any point by using the PROC_CrystalEffects((CHARACTERGUID)_Player); line at the end of a THEN.

So you could call it if a player entered a trigger, or left a dialog or whatever. Instead of typing all that code again you can just call it with one line.

By adding (CHARACTERGUID)_Player to the PROC_CrystalEffects you store the _Player gathered from the ItemTemplateAddedToCharacter event and pass it on to the PROC.

Joined: Oct 2017
Location: United Kingdom
journeyman
Offline
journeyman
Joined: Oct 2017
Location: United Kingdom
Then what if we have a special white crystal, that does all the above but also applies invisible status on pick up?

Code
IF
ItemTemplateAddedToCharacter(_WhiteCrystal,_,_Player)
THEN
DB_Crystal("white"); // this acts like a flag for the procedure to know a white crystal has been picked up.
PROC_CrystalEffects((CHARACTERGUID)_Player);

PROC
PROC_CrystalEffects((CHARACTERGUID)_Player)
AND
DB_Crystal("white") // checks for the "flag" and if so proceeds onto the THEN section
THEN
ApplyStatus(_Player,"INVISIBLE",8.0);
NOT DB_Crystal("white"); // deletes the "flag" so that it doesn't repeat for any other crystals or whatever



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