Larian Banner: Baldur's Gate Patch 9
Previous Thread
Next Thread
Print Thread
Page 1 of 2 1 2
Joined: Jul 2015
D
Detect Offline OP
member
OP Offline
member
D
Joined: Jul 2015
I have a box trigger and a PointTrigger.

PC runs through the trigger. Fires below script. Item spawns at PointTrigger.

But its not working.
Call ItemCreateAt Trigger((TRIGGERGUID)_Trigger, (STRING)_TemplateId

-INIT-
DB_IsPlayer(CHARACTERGUID_S_GLO_CharacterCreationDummy_001_da072fe7-fdd5-42ae-9139-8bd4b9fca406);

-KB-
IF
CharacterEnteredTrigger(_Character, TRIGGERGUID_spawnerTrigger001_ad34df51-5cf4-4163-8d8e-40631efc10d9)
AND
CharacterIsPlayer(_Character, 1)
THEN
ItemCreateAtTrigger(TRIGGERGUID_spawntrigger001_f1695295-7b38-41da-aa37-6ed5c602b159, "WPN_Common_Sword_1H_A2_47ba6f56-85a7-4ac5-a403-b8d5768ca4d7");

Last edited by Detect; 05/01/18 04:00 PM.
Joined: Nov 2017
L
member
Offline
member
L
Joined: Nov 2017
Is the trigger registered for players? If not, box triggers won't throw an event.

Joined: Jul 2015
D
Detect Offline OP
member
OP Offline
member
D
Joined: Jul 2015
Thanks. I will look into this...

Last edited by Detect; 06/01/18 03:07 PM.
Joined: Jul 2015
D
Detect Offline OP
member
OP Offline
member
D
Joined: Jul 2015
so this compiles...But no text or sword is spawned.

IF
CharacterEnteredTrigger(_Character, TRIGGERGUID_BoxTrigger_000_a4a30b90-97ba-43b5-b6a9-4511a3e3d38b)
AND
CharacterIsPlayer(_Character, 1)
THEN
TriggerRegisterForCharacter(TRIGGERGUID_BoxTrigger_000_a4a30b90-97ba-43b5-b6a9-4511a3e3d38b, _Character);
ItemCreateAtTrigger(TRIGGERGUID_PointTrigger_SWORDTEST_3efff6b1-b419-4142-a228-2856dc5b5c7a, "WPN_Common_Sword_1H_A2_47ba6f56-85a7-4ac5-a403-b8d5768ca4d7");
DisplayText(TRIGGERGUID_PointTrigger_SWORDTEST_3efff6b1-b419-4142-a228-2856dc5b5c7a, "TESTSPAWN");

Need to build the end of it correctly..
I know
THEN
AND
ElSIF?
"&"

How do I those actions to fire consecutively? If I could use ELSIF I would want to do this...But I'm a fledgling scripter...

IF
CharacterEnteredTrigger(_Character, TRIGGERGUID_BoxTrigger_000_a4a30b90-97ba-43b5-b6a9-4511a3e3d38b)
AND (ELSIF)
CharacterIsPlayer(_Character, 1)
THEN
TriggerRegisterForCharacter(TRIGGERGUID_BoxTrigger_000_a4a30b90-97ba-43b5-b6a9-4511a3e3d38b, _Character);
(AND)
ItemCreateAtTrigger(TRIGGERGUID_PointTrigger_SWORDTEST_3efff6b1-b419-4142-a228-2856dc5b5c7a, "WPN_Common_Sword_1H_A2_47ba6f56-85a7-4ac5-a403-b8d5768ca4d7");
(AND)
DisplayText(TRIGGERGUID_PointTrigger_SWORDTEST_3efff6b1-b419-4142-a228-2856dc5b5c7a, "TESTSPAWN");

Last edited by Detect; 06/01/18 10:20 PM.
Joined: Sep 2017
veteran
Offline
veteran
Joined: Sep 2017
The trigger has to be registered before the character enters it in order for it to recognize being entered. However that's not necessary for Event Triggers as they always listen for enter/leave events. So if you switch that boxtrigger with an event trigger, it should work providing the item actually exists :] You may also want to switch parameter 1 in the display text to target something physically in-world. I'm not sure a trigger itself would actually display any text.

Joined: Nov 2017
L
member
Offline
member
L
Joined: Nov 2017
The Composer is right in that, for a trigger to throw events upon entry, the trigger has to be registered for the character entering it.
However, it is best to use registerd triggers rather than event triggers unless you actually need the trigger to throw an event for every single character, as in the case of weather (because e.g. every character needs to get wet in the rain) to avoid excessive events being thrown.
So, for example, you could do:
Code
-INIT-
TriggerRegisterForPlayers(TRIGGERGUID_spawnerTrigger001_ad34df51-5cf4-4163-8d8e-40631efc10d9);

-KB-
IF
CharacterEnteredTrigger(_Character, TRIGGERGUID_spawnerTrigger001_ad34df51-5cf4-4163-8d8e-40631efc10d9)
THEN
ItemCreateAtTrigger(TRIGGERGUID_spawntrigger001_f1695295-7b38-41da-aa37-6ed5c602b159, "WPN_Common_Sword_1H_A2_47ba6f56-85a7-4ac5-a403-b8d5768ca4d7"); 


Notice the lack of "CharacterIsPlayer" check - your trigger will only ever trigger for player characters to begin with.
However, it appears like you may want this event to occur only once, in which case there's a helper -
DB_OneShotPlayerTrigger.

What you'd do then is:
Code
-INIT-
DB_OneShotPlayerTrigger(TRIGGERGUID_spawnerTrigger001_ad34df51-5cf4-4163-8d8e-40631efc10d9);

-KB-
PROC
ProcOneShotTriggerEntered(_Character, TRIGGERGUID_spawnerTrigger001_ad34df51-5cf4-4163-8d8e-40631efc10d9)
THEN
ItemCreateAtTrigger(TRIGGERGUID_spawntrigger001_f1695295-7b38-41da-aa37-6ed5c602b159, "WPN_Common_Sword_1H_A2_47ba6f56-85a7-4ac5-a403-b8d5768ca4d7"); 


If you follow the link in my first post, there's some documentation about registering triggers on the wiki.

Joined: Jul 2015
D
Detect Offline OP
member
OP Offline
member
D
Joined: Jul 2015
Thanks a lot guys. I did read through the documentation. I'm just not really a scripter. Just a hack - builder just trying to get by. I have worked with scripts at work and other game projects, so I'm not a total noob. I use PS at work. What I seem to be having trouble with the structure of the script
Not sure how to use PROC yet. I have some reading to do.

I look at examples and move the lines of my script around till it complies... Then go test in game.I'm sure I will get in a flow soon. Just throw me in the pool.

I suspected the trigger is the issue. So I will swap out the trigger and give it another shot. I am buried in finishing the design off in one of my large areas and that took me too many hours to admit too.

Overview:
While I have been building. I have been trying to reach a mile stone with my scripts that I think I will need. Spawning items would be useful. How much use I'm not sure yet, its more of a POC. OK the game can spawn items on the ground or in containers. Now how would I use a trigger that spawns an Item?

Its really to try to move away from "static" content and see if I can introduce randomness. We already have treasure tables. So the next step is to have the Items spawn from a treasure table " randomly at the trigger. Probably another way of doing this. (I haven't set up a chest yet to speak to this) I will assume they can be random in terms of what spawns inside.

Finally if we can spawn an item to the game world can we also spawn a creature to the game world... another game concept I haven't really addressed yet and really where I am headed in the end with this script.

I do not see a "CreateCreature", "spawnActor"...
I do see Move off stage, move back to stage.

Game concept:
Randomly generated creature list that spawns at Trigger location.. hey and why not spawn in a camp like a fire, tent and some odds and ends.. sure a chest or a sack would be nice.. Like a prefab, including the creature...

I can't see any reference to spawning a creature. Lets say I want the conversation of another NPC to spawn an Item and a creature at location.

what is the best way to do this? spawn from a trigger, spawn from a conversation...what if I don't have th3e convenience of a conversation?

OR.. just after the dungeon level is complete. There is a new option from the NPC that let the player " re populate the dungeon again...hence perpetual dungeon...

Last edited by Detect; 07/01/18 02:07 PM.
Joined: Nov 2017
L
member
Offline
member
L
Joined: Nov 2017
For spawning creatures, you can use https://docs.larian.game/Osiris/API/CharacterCreateAtTrigger or the other calls linked from that page.


Treasure tables are, indeed, random, selecting from a pre-defined set of items or categories of items. They have a considerable amount of functionality to keep the results balanced on both the small and the large scale.
How they work is documented here:
https://docs.larian.game/Treasure_Tables
There's no scripting involved in setting up a treasure table for an container. However, as far as I know there's no built-in functionality that allows you to spawn something from a treasure table at a trigger.

If you want to use a treasure table, the best you can do is probably to use a dummy container and the GenerateTreasure call, then move the contents of that container to the trigger.

Be advised, though, that spawning a very large number of creatures will be a strain on performance. For this case, it's better to use https://docs.larian.game/Osiris/API/TemporaryCharacterCreateAtTrigger instead.

Last edited by LarIlya; 07/01/18 02:10 PM.
Joined: Jul 2015
D
Detect Offline OP
member
OP Offline
member
D
Joined: Jul 2015
Brilliant!!

You have filled my cup for some time. You really have been a great help LarIlya.

I really appreciate it!

Nice! I have all day to work on this. Back to work tomorrow. The future of my Mod is looking bright!!

Last edited by Detect; 07/01/18 02:23 PM.
Joined: Jul 2015
D
Detect Offline OP
member
OP Offline
member
D
Joined: Jul 2015
the panacea - what a sweet call

CharacterCreateAtTrigger((TRIGGERGUID)_Trigger, (STRING)_TemplateId, (INTEGER)_PlaySpawn)

the best part is the temporary nature of it..

Creates a temporary character of the root template defined by _TemplateId (in a <root template name>_<root template UUID> format) at the _Trigger. If _PlaySpawn is 1, the creature will play its spawn animation as it appears. A temporary character's corpse is not saved. This call is useful to avoid very large save file sizes if it is used to spawn very large numbers of characters.

Joined: Nov 2017
L
member
Offline
member
L
Joined: Nov 2017
Be sure to make the distinction between TemporaryCharacterCreateAtTrigger and just CharacterCreateAtTrigger.
You may want the former if you need temporary characters.

Last edited by LarIlya; 07/01/18 03:18 PM.
Joined: Jul 2015
D
Detect Offline OP
member
OP Offline
member
D
Joined: Jul 2015
Originally Posted by LarIlya
The Composer is right in that, for a trigger to throw events upon entry, the trigger has to be registered for the character entering it.
However, it is best to use registerd triggers rather than event triggers unless you actually need the trigger to throw an event for every single character, as in the case of weather (because e.g. every character needs to get wet in the rain) to avoid excessive events being thrown.
So, for example, you could do:
Code
-INIT-
TriggerRegisterForPlayers(TRIGGERGUID_spawnerTrigger001_ad34df51-5cf4-4163-8d8e-40631efc10d9);

-KB-
IF
CharacterEnteredTrigger(_Character, TRIGGERGUID_spawnerTrigger001_ad34df51-5cf4-4163-8d8e-40631efc10d9)
THEN
ItemCreateAtTrigger(TRIGGERGUID_spawntrigger001_f1695295-7b38-41da-aa37-6ed5c602b159, "WPN_Common_Sword_1H_A2_47ba6f56-85a7-4ac5-a403-b8d5768ca4d7"); 


Notice the lack of "CharacterIsPlayer" check - your trigger will only ever trigger for player characters to begin with.
However, it appears like you may want this event to occur only once, in which case there's a helper -
DB_OneShotPlayerTrigger.

What you'd do then is:
Code
-INIT-
DB_OneShotPlayerTrigger(TRIGGERGUID_spawnerTrigger001_ad34df51-5cf4-4163-8d8e-40631efc10d9);

-KB-
PROC
ProcOneShotTriggerEntered(_Character, TRIGGERGUID_spawnerTrigger001_ad34df51-5cf4-4163-8d8e-40631efc10d9)
THEN
ItemCreateAtTrigger(TRIGGERGUID_spawntrigger001_f1695295-7b38-41da-aa37-6ed5c602b159, "WPN_Common_Sword_1H_A2_47ba6f56-85a7-4ac5-a403-b8d5768ca4d7"); 


If you follow the link in my first post, there's some documentation about registering triggers on the wiki.


OK tested this out. Thanks for pointing out that "OneShot" can be in the INIT area...I didn't realize TriggerRegisterForPlayers could also go in INIT..

TESTED and both work perfectly:

Quote

INIT
DB_IsPlayer(CHARACTERGUID_S_GLO_CharacterCreationDummy_001_da072fe7-fdd5-42ae-9139-8bd4b9fca406);
//DB_OneShotPlayerTrigger(TRIGGERGUID_spawnerTrigger001_ad34df51-5cf4-4163-8d8e-40631efc10d9);
//TriggerRegisterForPlayers(TRIGGERGUID_Monkworks_EventTrigger_000_7c51d4d5-1730-4e3c-88f3-9e07746e3ab5);
TriggerRegisterForPlayers(TRIGGERGUID_MonkworksBOXtrigger000_287131ab-cb9a-4506-841a-d40afdd5b53c);

KB
IF
CharacterEnteredTrigger(_Character, TRIGGERGUID_MonkworksBOXtrigger000_287131ab-cb9a-4506-841a-d40afdd5b53c)
//CharacterEnteredTrigger(_Character, TRIGGERGUID_Monkworks_EventTrigger_000_7c51d4d5-1730-4e3c-88f3-9e07746e3ab5)
THEN
ItemCreateAtTrigger(TRIGGERGUID_MonkworksSpawnPoint_000_662700e2-b906-4045-939c-5090c8eef2f9, "WPN_Common_Sword_1H_A2_47ba6f56-85a7-4ac5-a403-b8d5768ca4d7");


Both swapped out and fired perfectly!



Last edited by Detect; 07/01/18 04:46 PM.
Joined: Jul 2015
D
Detect Offline OP
member
OP Offline
member
D
Joined: Jul 2015
the monster spawned!!!

INiT
DB_IsPlayer(CHARACTERGUID_S_GLO_CharacterCreationDummy_001_da072fe7-fdd5-42ae-9139-8bd4b9fca406);
//TriggerRegisterForPlayers(TRIGGERGUID_Monkworks_EventTrigger_000_7c51d4d5-1730-4e3c-88f3-9e07746e3ab5);
TriggerRegisterForPlayers(TRIGGERGUID_MonkworksBOXtrigger000_287131ab-cb9a-4506-841a-d40afdd5b53c);

KB

IF
CharacterEnteredTrigger(_Character, TRIGGERGUID_MonkworksBOXtrigger000_287131ab-cb9a-4506-841a-d40afdd5b53c)
//CharacterEnteredTrigger(_Character, TRIGGERGUID_Monkworks_EventTrigger_000_7c51d4d5-1730-4e3c-88f3-9e07746e3ab5)
THEN
//ItemCreateAtTrigger(TRIGGERGUID_MonkworksSpawnPoint_000_662700e2-b906-4045-939c-5090c8eef2f9, "WPN_Common_Sword_1H_A2_47ba6f56-85a7-4ac5-a403-b8d5768ca4d7");
CharacterCreateAtTrigger(TRIGGERGUID_MonkworksSpawnPoint_000_662700e2-b906-4045-939c-5090c8eef2f9, "CHARACTERGUID_Animals_Crocodile_A_Polymorph_4e394cab-17d5-4eb5-9b1b-f81a66db35d9", 1);

Joined: Jul 2015
D
Detect Offline OP
member
OP Offline
member
D
Joined: Jul 2015
Now need to add logic and a condition. Has the script already created the monster? Or does the monster that was created from this script exist?

"CharacterCreateAtTrigger"
This does not return the character being created. If you need to reference that character, it is best to query the _Trigger's position and use TemporaryCharacterCreateAtPosition, which does return the character.

query TemporaryCharacterCreateAtPosition([in](REAL)_X, [in](REAL)_Y, [in](REAL)_Z, [in](STRING)_TemplateId, [in](INTEGER)_PlaySpawn, [out](CHARACTERGUID)_Created)


How can we use this for a check before creation?

Like this?
IF
TemporaryCharacterCreateAtPosition("_TemplateId", 0) <<<??? would this go in INIT?
THEN
CharacterCreateAtTrigger(TRIGGERGUID_MonkworksSpawnPoint_000_662700e2-b906-4045-939c-5090c8eef2f9, "CHARACTERGUID_Animals_Crocodile_A_Polymorph_4e394cab-17d5-4eb5-9b1b-f81a66db35d9", 1);

Last edited by Detect; 07/01/18 05:35 PM.
Joined: Nov 2017
L
member
Offline
member
L
Joined: Nov 2017
The general structure of an Osiris rule is as follows (note that the colours below don't reflect the colouring within the Osiris editor, they're just colours that I picked because they're easily distinguishable on the forums' black background):

IF
<triggering event>
AND
<condition>
AND
<other condition>
THEN
<actions>.

Here, the triggering event need to be an event, the conditions need to be queries (built-in or custom-defined), and the actions need to be calls, either built-in ones or procedures.

Databases can be used for all three of these, with subtly different meanings - a database used as an event triggers that rule when it something is added to the database. A database used as a query checks whether something exists in the database, and a database used as an action adds something to the database.
The latter two uses can be modified with the NOT keyword, to do the opposite.

If you ever require information that is not already supplied by the event, you'll need to use queries to get that information, so that'll go before the THEN section.

In practice, that means you'll want to use
IF
CharacterEnteredTrigger(_Character, TRIGGERGUID_MonkworksBOXtrigger000_287131ab-cb9a-4506-841a-d40afdd5b53c)
AND
GetPosition(TRIGGERGUID_MonkworksBOXtrigger000_287131ab-cb9a-4506-841a-d40afdd5b53c, _X, _Y, _Z)
AND
CharacterCreateAtPosition(_X, _Y, _Z, "CHARACTERGUID_Animals_Crocodile_A_Polymorph_4e394cab-17d5-4eb5-9b1b-f81a66db35d9", 1, _Crocodile)
THEN
DB_MonkWorksCrocodileDatabase(_Crocodile);

After the crocodile has been created, it will be stored in the DB_MonkWorksCrocodileDatabase (I suggest you rename it to something more convenient in your actual script), which you can then check when you need to know whether the creature exists and what that creature is.
Note that CharacterCreateAtPosition is a query. It must be, because it has a return value: it tells you something - what character was created.


Now, for what goes into the INIT section of your code:
The Init section is a list of calls (actions) that need to be taken when the goal is first loaded, effectively at game start. You can't put queries or events there.


Joined: Jul 2015
D
Detect Offline OP
member
OP Offline
member
D
Joined: Jul 2015
ok man, great stuff... Let me try it out. I hope others are watching and also getting the benefit here and thanks again so much to LarIlya who is just a master at explaining this stuff..

Joined: Jul 2015
D
Detect Offline OP
member
OP Offline
member
D
Joined: Jul 2015
its was comical so I though I would share. Obviously the script is dirty, so I got some interesting behaviour for sure lol...

IF
CharacterEnteredTrigger(_Character, TRIGGERGUID_MonkworksBoxTriggerBW_000_23b012a2-c074-45f8-94cb-3d3bc9faa20e)
AND
GetPosition(TRIGGERGUID_MonkworksBoxTriggerBW_000_23b012a2-c074-45f8-94cb-3d3bc9faa20e, _X, _Y, _Z)
AND
CharacterCreateAtPosition(_X, _Y, _Z, "CCHARACTERGUID_Creatures_Undead_Zombie_A_99419eeb-e574-4b5f-8e71-d642364ebf4b", 1, _Zombie)
THEN
DB_MonkWorksZombieDatabase(_Zombie);

so what happened here is:

PC enters the trigger
Zombie starts fight from 1000 feet away
Zombie is teleported to PC
PC is killed in first two hits

My coffee ends up all over my screen :0
too funny
I must have switched them around.

I need a simple naming convention

Last edited by Detect; 07/01/18 06:58 PM.
Joined: Jul 2015
D
Detect Offline OP
member
OP Offline
member
D
Joined: Jul 2015
some good testing done.
Results

IF
CharacterEnteredTrigger(_Character, TRIGGERGUID_MonkworksBoxTriggerBW_000_23b012a2-c074-45f8-94cb-3d3bc9faa20e)
AND
GetPosition(TRIGGERGUID_SpawnTrigger_MOB_001_e1efc019-8dd4-43f8-9b8f-bb4fd7813e9f, _X, _Y, _Z)
AND
CharacterCreateAtPosition(_X, _Y, _Z, "CHARACTERGUID_Creatures_Undead_Zombie_A_99419eeb-e574-4b5f-8e71-d642364ebf4b", 1, _Zombie)
THEN
DB_MonkWorksZombieDatabase(_Zombie);


ran through the trigger 4 times. run over to the spawn point. 4 zombies spawned.

I know we can use OneShot. But I want the trigger to keep one Zombie there and only one...

Last edited by Detect; 07/01/18 07:26 PM.
Joined: Jul 2015
D
Detect Offline OP
member
OP Offline
member
D
Joined: Jul 2015
some testing behaviour stuff..

so a zombie is spawned for each action off the trigger. BUT if I say run through the trigger 3 times and three zombies are spawn. if I leave the level and return. Only one will be at the spawn point. That's a good thing..

Should we not check if zombie is in DB first? seems like the script adds it to the DB but doesn't query it..fist

Joined: Nov 2017
L
member
Offline
member
L
Joined: Nov 2017
If you want to make sure that there's only ever one zombie, you could add a query

AND
NOT DB_MonkWorksZombieDatabase(_)
THEN

and also add a rule along the lines of

IF
CharacterDied(_Zombie)
AND
DB_MonkWorksZombieDatabase(_Zombie)
THEN
NOT DB_MonkWorksZombieDatabase(_Zombie);

Page 1 of 2 1 2

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