Jump to content

Recommended Posts

Posted (edited)

You should be familiar with the Modding Basic Concepts tutorial before following this one.
 
In this tutorial, I'm going to show you how to use a ModScriptHookGameData object to add a new item to a store or other inventory in the game.
 
ModScriptHookGameData is a new game data type that was added in v2.1.0.  It contains a set of scripts that will be run each time the player enters a scene in the game.  This is a good way for a mod to make alterations to the contents of scenes with your mod.
 
Here's an example game data object I created for this tutorial:

{
	"GameDataObjects": [
		{
			"$type": "Game.GameData.ModScriptHookGameData, Assembly-CSharp",
			"DebugName": "Metalworks_ItemAdd",
			"ID": "417f4f5e-7d01-4cd6-aa9d-1f0b1d0b4be2",
			"Components": [
				{
					"$type": "Game.GameData.ModScriptHookComponent, Assembly-CSharp",
					"RunOnlyOnce": "false",
					"SucceedOnlyOnce": "true",
					"Script": {
						"Conditional": {
							"Operator": 0,
							"Components": [
								{
									"$type": "OEIFormats.FlowCharts.ConditionalCall, OEIFormats",
									"Data": {
										"FullName": "Boolean IsInActiveScene(Guid)",
										"Parameters": [
											"3f84e9ad-761d-47fa-9e38-7a492ff24b95"
										]
									},
									"Not": false,
									"Operator": 0
								}
							]
						},
						"Scripts": [
							{
								"Data": {
									"FullName": "Void GenerateLootListInto(Guid, Guid)",
									"Parameters": [
										"3f84e9ad-761d-47fa-9e38-7a492ff24b95",
										"f3a0a676-c69c-46b2-9a9e-8bae94fae19a"
									]
								},
								"Conditional": {
									"Operator": 0,
									"Components": []
								}
							}
						]
					}
				}
			]
		}
	]
}

This is a pretty straightforward object, with only three properties:

  • RunOnlyOnce - if "true", this script will only be run one time ever in a player's game.
  • SucceedOnlyOnce - if "true", this script will be run on each scene load until the Conditional component of the script succeeds, then it won't be run again.
  • Scripts - a Conditional to check, and Scripts to call if the Conditional passes

In my example object, I have one conditional IsInActiveScene(3f84e9ad-761d-47fa-9e38-7a492ff24b95), checking if a certain object is in the active scene, and one script GenerateLootListInto(3f84e9ad-761d-47fa-9e38-7a492ff24b95, f3a0a676-c69c-46b2-9a9e-8bae94fae19a), which generates my custom loot list (not shown) into that object's inventory.  I've set it to SucceedOnlyOnce, so once my items have been generated into that inventory, they won't be duplicated if I come back to the scene later.
 
How can you find the GUID of the object you want to modify?

  • If the object is visible in the scene, hover your mouse over it and enter "PrintInstance oei_hovered" into the console.  This will print the GUID in the combat log and copy it to the clipboard.

    post-113185-0-77495300-1535062425.png
     
  • If the object is not visible in the scene, you can search for it by name with the console command "FindObject". For example, "FindObject Store" will output to the combat log all objects with the string "Store" in their name.

    post-113185-0-66447900-1535062670.png

    You can then copy down the GUID manually or copy it to the clipboard with PrintInstance (e.g. "PrintInstance Store_05_Marihi").

That's all it takes to insert your custom items into the game without fear of conflicts with other mods.

 

For a list of available scripts and conditionals, see the documentation: scripts, conditionals.

storeadd-printinstancehover.png

storeadd-findobject.png

Edited by BMac
fix images for forum update
  • Like 4
Posted (edited)

Forgive the basic questions:

 

Would generating your lootlist into the object add your lootlist to the existing lootlist, or replace it? I presume it would just add, hence avoiding conflicts with mods?

 

Second, you mention stores specifically but presumably this can be used with any object that contains loot? Ie if I want to add a unique weapon to the digsite dungeon at the start of the game all I'd need to do is go to that dungeon, find a suitable loot container, and PrintInstance to get the ID?

 

This is very exciting news by the way!

Edited by house2fly
  • Like 2
Posted (edited)

Second, you mention stores specifically but presumably this can be used with any object that contains loot? Ie if I want to add a unique weapon to the digsite dungeon at the start of the game all I'd need to do is go to that dungeon, find a suitable loot container, and PrintInstance to get the ID?

Relatedly, if you did this to a NPC, is it possible to add it to its LootList via the same means? This would make it so an NPC could drop a specific item on death, which I know a couple of people have been asking about.

 

(and would it be pickpocketable if so [some people might not like that, is why I ask, though it wouldn't matter for hostile NPCs as they can't be pickpocketed])

 

Even if it doesn't, this opens up a world of possibilities.  :thumbsup:

Edited by Zap Gun For Hire
  • Like 1
Posted

The main thing that I think answers your questions is that this script doesn't add a loot list itself to anything. Instead, it immediately generates a set of items as defined by the specified loot list and places them into an inventory, where they'll stay until they're removed.
 

Would generating your lootlist into the object add your lootlist to the existing lootlist, or replace it? I presume it would just add, hence avoiding conflicts with mods?

Second, you mention stores specifically but presumably this can be used with any object that contains loot? Ie if I want to add a unique weapon to the digsite dungeon at the start of the game all I'd need to do is go to that dungeon, find a suitable loot container, and PrintInstance to get the ID?

This would be in addition to any existing loot lists that generate into this object.  There would be two separate events happening: the store would generate items from its loot lists into the container, and then your script would generate items from its loot list into the container, adding to the ones that are already there.
 
Yes, this could be used on any object with an inventory (containers, characters, stores).
 

Relatedly, if you did this to a NPC, is it possible to add it to its LootList via the same means? This would make it so an NPC could drop a specific item on death, which I know a couple of people have been asking about.
 
(and would it be pickpocketable if so [some people might not like that, is why I ask, though it wouldn't matter for hostile NPCs as they can't be pickpocketed])

You can't add additional loot lists onto NPCs or creatures such that they will generate when that character dies. However, if the character is configured to drop its inventory on the Unity object (I believe this is true for most kith characters), then the items would have been added to its inventory and would be available in the corpse container or when pickpocketing.

  • Like 3
Posted (edited)

I just had a go at this and thought I'd share the results

 

Please note that this ONLY works with 2.1.0Beta or above (like the release when we get it)

 

First grab this https://www.nexusmods.com/pillarsofeternity2/mods/125

 

Then grab the attachments to this post

 

Extract savegames.zip into C:\Users\<Your Login User>\Saved Games\Pillars of Eternity II (or wherever it goes on Max / Linux)

 

The savegames have cheats enabled BTW so ignore the usual moan about missing junk. These saves are both having gone from the beach talking to Rinco + Savia (coulda skipped that bit) and headed straight for Eofania (nothing else), this is a good clean small save.

 

Next extract the NexusMods version into override (this version will break)

 

Start up POE2 and load Mapper -> Before Eofania then talk to her (you're stood next to her) and open her store - LOTS of added items

 

Now load After Eofania. The only difference between these saves is that in the second one I've already had a look at her inventory. Check her store - all Mod items are now missing

 

This is an issue we've been aware of since the game came out

 

If you check ...

 

override\pdx-unique-items\design\gamedata\pdx-unique-items.gamedatabundle you'll see a standard lootlist re-write

	"DebugName": "Store_09_PM_Eofania_BaseInventory",
	"ID": "0954daa7-cef5-4ffe-9a65-08abfbd618e8",

Exit to Desktop

 

Delete the Nexus Mods version of pdx-unique-items in override and replace it with pdx-unique-items-additem (attached)

 

Repeat the above Eofania loads and now BOTH have the correct Modded itemlists

 

This fixes a big headache for all Modders who do lootlists

 

If you examine the gamedatabundle you'll see that all I've done is change the lootlist override so it now looks like this...

	"DebugName": "Store_09_PM_Eofania_Peardox",
	"ID": "fd5c33c9-2e15-45bd-89f5-7b98562b31e9",

The ID is a new one and I changed the DebugName - that's the ONLY alteration to the mod - the payload happens in lootlist.gamedatabundle

 

This was a quick test - I should really have removed the original, pre-mod, items from the lootlist 

 

Finally if you check lootlist.gamedatabundle you'll see I've taken BMac's example and replaced the IDs

 

Again I've changed DebugName and the IDs

 

The important ID is c164ad1a-fabc-4c50-9238-c86f2f8999ad, this is the store triggered by asking Eofania to show you her lootlist

 

First I've got ....

	"Data": {
		"FullName": "Boolean IsInActiveScene(Guid)",
		"Parameters": [
			"c164ad1a-fabc-4c50-9238-c86f2f8999ad"
		]

This checks if Eofania's store is in the level which, in the case of the supplied savegames, it is

 

Then we've got this

	"Data": {
		"FullName": "Void GenerateLootListInto(Guid, Guid)",
		"Parameters": [
			"c164ad1a-fabc-4c50-9238-c86f2f8999ad",
			"fd5c33c9-2e15-45bd-89f5-7b98562b31e9"
		]
	},

This adds our altered lootlist to Eofania's lootlist. You can have BOTH versions of the mod installed at the same time and the broken original is still broken but the new version fixes the bad one.

 

There are 56 conversations that trigger an OpenStore in exported/design/conversations, in this case I'm using 09_port_maje/09_cv_eofania.conversationbundle

 
Simply search for OpenStore in that file and you'll see that triggers c164ad1a-fabc-4c50-9238-c86f2f8999ad which in turn now has the new lootlist added to it
 
As far as I understand the OpenStore loads the original lootlist we can Mod in exported as that and the openstore ID both appear in level347 but this new scriptable alters the openstore to add our new items (if it's not exactly what happens it's close enough to the high-level version of what happens)
 
The only thing you need to do to have free reign with any Store is to find it's OpenStore call

I'll post a list of where they occur later to make it easier for people to track the one you're interested in down
 
One VITAL point about this new very easy to add functionality is that we no longer need to worry about Vendor Clash when 2.1.0 hits release. For example @TT1 uses The Wild Mare for his Uniques. There is no concern over anyone adding new loot to that list using the new method (started tracking Vendor Clash a few weeks ago - pointless now). Actually, think I'll verify this by loading his Mod + change the Store to his one (I see no reason for it to fail)
 

Using the lootlist.gamedatabundle example and making a minor change to your existing Mods makes for an easy and foolproof better way of making your Mod Items available

pdx-unique-items-additem.zip

savegames.zip

Edited by peardox

OK Fair warning has been applied

 

I'm gonna move the domain to https://perspak.com early Feb but will keep all content

 

There are reasons behind this move which basically boil down to unifying my release schedule

 

My friends are welcome to play (I'll set you up your own areas if you desire them)

 

Please note that this process is messy so may take a few weeks 

Posted (edited)
As promised above here is a list of every conversationbundle that triggers an OpenStore

 

[Arrgh - addition] Just discovered we've also got an OpenInn that triggers unmarked stores in conversationbundle files (there are eight) - investigating 1cf96a2c-466a-4246-b224-95648881beb0 (Wild Mare)

 

At some point I'll link them to their characters but as a quick reference this is useful

 

If you want to find a specific vendor then you simply need to find them in charaters.gamedatabundle. Using Eofania as an example again if you search for her you'll find she has this property...

 

"SpeakerID": "6b043fd4-902e-48ef-af38-c92cd4b5c7e4"

 

From the following list this one only crops up in /09_port_maje/09_cv_eofania.conversationbundle (grep or something similar really helps here)

 

Check out that file and search for OpenStore and we get the ID we need to plug in to lootlist.gamedatabundle

 

These are all in exported/design/conversations

 

/00_prototype/00_cv_himuihi.conversationbundle

/00_prototype/00_cv_vektor.conversationbundle

/03_neketaka_vailian_district/03_cv_sanza.conversationbundle

/03_neketaka_vailian_district/03_cv_vd_vendor_armorer.conversationbundle

/03_neketaka_vailian_district/03_cv_vd_vendor_cobbler.conversationbundle

/03_neketaka_vailian_district/03_cv_vd_vendor_fishmonger.conversationbundle

/03_neketaka_vailian_district/03_cv_vd_vendor_huntingandsundries.conversationbundle

/03_neketaka_vailian_district/03_cv_vd_vendor_tailor.conversationbundle

/03_neketaka_vailian_district/03_cv_zamar.conversationbundle

/04_neketaka_palace_district/04_cv_vendor_general.conversationbundle

/04_neketaka_palace_district/04_cv_vendor_pets.conversationbundle

/05_neketaka_artisans_district/05_cv_fessina.conversationbundle

/05_neketaka_artisans_district/05_cv_herbalist.conversationbundle

/05_neketaka_artisans_district/05_cv_imp_store.conversationbundle

/05_neketaka_artisans_district/05_cv_iolfr.conversationbundle

/05_neketaka_artisans_district/05_cv_marihi.conversationbundle

/05_neketaka_artisans_district/05_cv_vendor_drink.conversationbundle

/05_neketaka_artisans_district/05_cv_vendor_food.conversationbundle

/06_neketaka_slums_district/06_cv_fabrozzo.conversationbundle

/06_neketaka_slums_district/06_cv_street_dealer.conversationbundle

/06_neketaka_slums_district/06_cv_tender_toko.conversationbundle

/06_neketaka_slums_district/06_cv_vendor_bm_aumaua.conversationbundle

/06_neketaka_slums_district/06_cv_vendor_bm_orlan.conversationbundle

/06_neketaka_slums_district/06_cv_zahak.conversationbundle

/07_neketaka_temple_district/07_cv_dawnstar_vendor.conversationbundle

/07_neketaka_temple_district/07_cv_vendor_temple.conversationbundle

/07_neketaka_temple_district/07_cv_vendor_tiabo.conversationbundle

/08_neketaka_rauatai_district/08_bs_lounge_server.conversationbundle

/08_neketaka_rauatai_district/08_cv_orlan_peddler.conversationbundle

/08_neketaka_rauatai_district/08_cv_sabormi.conversationbundle

/08_neketaka_rauatai_district/08_cv_uto.conversationbundle

/09_port_maje/09_bs_fishmonger.conversationbundle

/09_port_maje/09_cv_eofania.conversationbundle

/09_port_maje/09_cv_port_maje_tavernkeeper.conversationbundle

/09_port_maje/09_cv_shady_merchant.conversationbundle

/09_port_maje/09_cv_vendor_market_blessings.conversationbundle

/09_port_maje/09_cv_vendor_market_trading_post.conversationbundle

/09_port_maje/09_cv_vendor_market_weapons.conversationbundle

/13_fort_deadlight/13_cv_deadlight_merchant_02.conversationbundle

/13_fort_deadlight/13_cv_deadlight_merchant.conversationbundle

/14_slaver_port/14_cv_aeldys_spy.conversationbundle

/14_slaver_port/14_cv_merchant.conversationbundle

/15_rdc_port/15_cv_fish_vendor_01.conversationbundle

/15_rdc_port/15_cv_weapon_merchant_01.conversationbundle

/16_wahaki_island/16_cv_wahaki_trader.conversationbundle

/17_dunnage/17_cv_dimesa.conversationbundle

/17_dunnage/17_cv_market_bartender.conversationbundle

/17_dunnage/17_cv_market_food_vendor.conversationbundle

/17_dunnage/17_cv_ramaso.conversationbundle

/17_dunnage/17_cv_tavern_owner.conversationbundle

/20_splintered_reef/20_cv_undead_barkeep.conversationbundle

/26_uncharted_islands/26_cv_tama_watua.conversationbundle

/28_drowned_barrows/28_cv_vendor_huntress.conversationbundle

/generic/00_cv_debug_guy_random_encounters.conversationbundle

/re_scripted_interactions/re_cv_generic_merchant.conversationbundle

/re_scripted_interactions/re_cv_generic_slaver.conversationbundle

Edited by peardox

OK Fair warning has been applied

 

I'm gonna move the domain to https://perspak.com early Feb but will keep all content

 

There are reasons behind this move which basically boil down to unifying my release schedule

 

My friends are welcome to play (I'll set you up your own areas if you desire them)

 

Please note that this process is messy so may take a few weeks 

Posted (edited)

I've now explored OpenInn

 

Go grab https://www.nexusmods.com/pillarsofeternity2/mods/111 and install

 

If you change lootlist.gamedatabundle in the above attachment and replace c164ad1a-fabc-4c50-9238-c86f2f8999ad with 1cf96a2c-466a-4246-b224-95648881beb0 (twice!!!) - this one's the same as OpenStore but has some extra stuff

 

We're now adding to The Wild Mare

 

I've got a save where TT1's Dead Parrot is shown - this may not be true for you so just use any Wild Mare you have to hand

 

I could EASILY now be 100% TT1's would appear by adding it to lootlist.gamedatabundle but that means modding his mod. I'm not doing that - his stuff is his stuff, anything posted by myself here is free for use though.

 

Wild Mare now has the stuff we stuck on Eofania earlier! If you've got TT1's loaded and a good save you've also got his stuff

 

Here are the additional lootlists you can play with...
 

exported/design/conversations/00_prototype/00_cv_himuihi.conversationbundle
exported/design/conversations/00_prototype/00_cv_nairi.conversationbundle
exported/design/conversations/03_neketaka_vailian_district/03_cv_gyntel.conversationbundle
exported/design/conversations/05_neketaka_artisans_district/05_cv_bathhouse_owner.conversationbundle
exported/design/conversations/06_neketaka_slums_district/06_cv_tender_toko.conversationbundle
exported/design/conversations/09_port_maje/09_cv_port_maje_tavernkeeper.conversationbundle
exported/design/conversations/16_wahaki_island/16_cv_wahaki_trader.conversationbundle
exported/design/conversations/17_dunnage/17_cv_tavern_owner.conversationbundle
Edited by peardox

OK Fair warning has been applied

 

I'm gonna move the domain to https://perspak.com early Feb but will keep all content

 

There are reasons behind this move which basically boil down to unifying my release schedule

 

My friends are welcome to play (I'll set you up your own areas if you desire them)

 

Please note that this process is messy so may take a few weeks 

Posted

Forgive the basic questions:

 

Would generating your lootlist into the object add your lootlist to the existing lootlist, or replace it? I presume it would just add, hence avoiding conflicts with mods?

 

Second, you mention stores specifically but presumably this can be used with any object that contains loot? Ie if I want to add a unique weapon to the digsite dungeon at the start of the game all I'd need to do is go to that dungeon, find a suitable loot container, and PrintInstance to get the ID?

 

This is very exciting news by the way!

 

Rats - forgot this one my Slack friend

 

I'll do a sample at the start of game that does an object attach as I think I understand this now

 

I'm not gonna Mod your mod, simply detail how to do what you ask (I'll use my Mod as I can permit myself to do this kinda stuff)

 

May try a character mod as well (simply to see if I can do it)

 

Now I have to reload 2.1b - arggh!

 

Shoulda thought this thru!

OK Fair warning has been applied

 

I'm gonna move the domain to https://perspak.com early Feb but will keep all content

 

There are reasons behind this move which basically boil down to unifying my release schedule

 

My friends are welcome to play (I'll set you up your own areas if you desire them)

 

Please note that this process is messy so may take a few weeks 

Posted

OK - done @house2fly's version

 

This one uses a diffo save and a very small mod to the original lootlist.gamedatabundle above

 

If you load the savegame and cheat (console) PrintInstance oei_hovered you'll find it's ID is 05b7a207-5857-4a01-b62d-cd3345dc2c22

 

All we have to do is change lootlist.gamedatabundle to use this ID (twice!!!)

 

Note that all these Mods happily co-exist in 2.1b (don't test my theory though!)

 

If you read the above instructions it's exactly the same deal apart from this time you wanna load Mapper -> FirstBox (it's the first locked box I tend to come across in Sea Cave) 

 

The box is locked but it's pickable - the playable has enough to do this (ain't there a console that unlocks everything?)

 

One last point is that players call console the Cheat, we actually rely on it when developing Mods

 

Look at the crappy character I gave you in this save! If there's something we can't afford from someone like this piece of junk we need to be able to givePlayerMoney 10000000 simply to test things out. We constantly use giveItem <ID> (Rant over)

 

So - here are the files - if you Mod this is extremely simple - no real need to read the rest :)

 

Where's the fun in that

 

OK - I recommend a clean override before you start

 

First install the savegave (see my initial message on this above)

Load the save and open the box - full of junk

 

Exit to desktop

 

Install the new mod in override and open the box again - cool, far better loot

 

I'm gonna try an NPC with the same lootlist tomorrow

 

I THINK we need a NAMED NPC to lootlist them ATM (may change my mind)

 

Tried the piggie before seacave, that one's harder but have changed it's lootlist

 

Problem is I can't printInstance the thing

 

Here are the files...

 

Housefly.zip is the savegame

 

pdx-unique-items-housefly.zip

housefly.zip

OK Fair warning has been applied

 

I'm gonna move the domain to https://perspak.com early Feb but will keep all content

 

There are reasons behind this move which basically boil down to unifying my release schedule

 

My friends are welcome to play (I'll set you up your own areas if you desire them)

 

Please note that this process is messy so may take a few weeks 

Posted

 

Second, you mention stores specifically but presumably this can be used with any object that contains loot? Ie if I want to add a unique weapon to the digsite dungeon at the start of the game all I'd need to do is go to that dungeon, find a suitable loot container, and PrintInstance to get the ID?

Relatedly, if you did this to a NPC, is it possible to add it to its LootList via the same means? This would make it so an NPC could drop a specific item on death, which I know a couple of people have been asking about.

 

(and would it be pickpocketable if so [some people might not like that, is why I ask, though it wouldn't matter for hostile NPCs as they can't be pickpocketed])

 

Even if it doesn't, this opens up a world of possibilities.  :thumbsup:

 

 

OK here's a well fed boar (they eat anything)

 

The savegame is in porky.zip, the other one's the loot

 

Getting the ID is tricky going on my attempts to get it - you need the target (Young Boar) to be visible but you need to NOT be in attack mode. There's a very short period between the Boar being visible and the auto-attack kicking in. Pause in that window and do a printInstance with your mouse over the Boar and you get it (c0d8cf7b-8f24-4bb2-b7d9-51ea73f897b8)

 

This one's exactly the same as the others above so read them for the skinny.

 

The changes are ...

 

1) the lootlist in pdx-unique-items.gamedatabundle has been shortened as there are only 14 slots on a pig

2) the attached trigger in lootlist.gamedatabundle now has the Boar's ID

3) The boar's normal drop is set to one_random and I've already given it six so the natural drop don't happen

 

If you load Mapper -> Porky the boar will wander into view after a few seconds, kill it to get the new lootlist rather than the usual Pork drop

pdx-unique-items-additem-porky.zip

porky.zip

  • Like 3

OK Fair warning has been applied

 

I'm gonna move the domain to https://perspak.com early Feb but will keep all content

 

There are reasons behind this move which basically boil down to unifying my release schedule

 

My friends are welcome to play (I'll set you up your own areas if you desire them)

 

Please note that this process is messy so may take a few weeks 

Posted

So if there's limited slots the mod lootlist would override the original one? Ie if I have 14 items and add them all to the pig it'll drop those 14 items and none of its original loot?

 

Regarding attack mode, do you mean when the enemy is officially "spotted" and autopause kicks in (if enabled)? That WOULD be a short window! But if that window is all you need to add loot to any NPC or creature in the game then that's plenty

Posted

So if there's limited slots the mod lootlist would override the original one? Ie if I have 14 items and add them all to the pig it'll drop those 14 items and none of its original loot?

 

Regarding attack mode, do you mean when the enemy is officially "spotted" and autopause kicks in (if enabled)? That WOULD be a short window! But if that window is all you need to add loot to any NPC or creature in the game then that's plenty

 

I'm not sure if there's a race - I've tried this half a dozen times but the porky mod APPEARS to always win - I'm guessing that the ModScriptHook takes preference over a lootlist rewrite - Only @BMac nows for sure.

 

As the standard lootlist 

	"DebugName": "LL_Boar_Young",
	"ID": "310520c4-4ab8-401f-b7c8-79c3f4a91343",

Has a "OutputMode": "One_Random" we can replace it with a "OutputMode": "All" in our override

 

Add this one (it's in the attach) - make sure you don't have porky mod installed as they use the same ID for the lootlist.gamedatabundle (all the above do), load the porky save and, voila...

 

Now we get the pork as well as the added items

 

There IS however an apparent limit on loot from anything that ain't a shop of 14 items - ships appear to fill it up (no reason we can't use the same trick with everything)

 

The printInstance oei_hovered does work when you hit auto-pause (just checked). Maybe they've changed something? Maybe I just mis-typed the command in debug? Dunno.

 

I used the Boar as it's right at the start but it potentially works on ANY NPC

pdx-unique-items-additem-porky-plus.zip

OK Fair warning has been applied

 

I'm gonna move the domain to https://perspak.com early Feb but will keep all content

 

There are reasons behind this move which basically boil down to unifying my release schedule

 

My friends are welcome to play (I'll set you up your own areas if you desire them)

 

Please note that this process is messy so may take a few weeks 

Posted (edited)

Thought I'd take this one stage further now we're live on 2.1.0

 

The save (random_guy.zip) is some - err - random guy walking around Port Maje

 

The Mod is the other one - simply changed the lootlist.gamedatabundle to target him (TWICE) rather than the pig

 

To test this one out make sure you've got no other sample mods in this series installed and install this one (ID clash otherwise - being lazy)

 

Load Modder -> Random Guy and pause straight away!

 

You want the friendly guy who's walking North under the trees - switch to attack mode (Sword in the UI) and kill the poor guy (bad rep for this) - he now drops the piggy loot!

 

I then wen't on a killing frenzy in PM (actually only killed one other) and that one didn't have piggy loot.

 

The DebugName on random_guy ended in _Clone - I'm not gonna slaughter the entire town to find out, this was just a diversion as I wanna wait til after DevStream for anything new

 

Rationally every single character will have a different ID - otherwise the clones would do stuff at the same time

 

This technique is, however, extremely flexible

 

You can create a really cool item and 'hide' it on someone

 

You simply need to printInstance oei_hovered the poor sap and you've got his / her UUID in ClipBoard ready to paste into lootlist.gamedatabundle

 

I feel a Quest coming on :)

 

"Someone in Queens landing has the most powerful <insert item> in the world, kill them and it's yours" :)

 

So you have to go slaughter Queens Landing simply to find out who has is :)

This changes the game in ways the Devs never saw coming :)

Never give a loaded gun to a ... ModDev :)

random_guy.zip

pdx-unique-items-additem-random-guy.zip

Edited by peardox
  • Like 1

OK Fair warning has been applied

 

I'm gonna move the domain to https://perspak.com early Feb but will keep all content

 

There are reasons behind this move which basically boil down to unifying my release schedule

 

My friends are welcome to play (I'll set you up your own areas if you desire them)

 

Please note that this process is messy so may take a few weeks 

Posted

This is gonna work!

 

I hope...

 

I've done a drop on <someone in QB>

 

God - I'm gonna be writing this for days!

 

What would you like the end result to be?

OK Fair warning has been applied

 

I'm gonna move the domain to https://perspak.com early Feb but will keep all content

 

There are reasons behind this move which basically boil down to unifying my release schedule

 

My friends are welcome to play (I'll set you up your own areas if you desire them)

 

Please note that this process is messy so may take a few weeks 

  • 3 weeks later...
Posted

I wanted to check on something: would the IsInActiveScene check be broken if it's checking for a DLC object in a game which doesn't have DLC installed? It just searches for a GUID and if the GUID isn't there it gets on with its life, and it doesn't need the GUID in question to be in the game files, right? I think a mod which adds lootlists to DLC and main game areas should be fully compatible with any combination of DLC or no DLC, as long as the lootlist itself doesn't use DLC assets, but figured I'd get Official Confirmation before going nuts

Posted

The onhovered result DEPENDS in the level file, I've established this in another thread and by comments from BMac

 

OnHovered returns the ID of the in-game object, everything in ANY exported is an alias

 

If you ain't got the expansion by definition you ain't got the level file so the object CANT be in scene

  • Like 1

OK Fair warning has been applied

 

I'm gonna move the domain to https://perspak.com early Feb but will keep all content

 

There are reasons behind this move which basically boil down to unifying my release schedule

 

My friends are welcome to play (I'll set you up your own areas if you desire them)

 

Please note that this process is messy so may take a few weeks 

Posted

I'm afraid I don't know whether that means I'm right or wrong- sorry, my brain runs at a slower speed maybe! That probably is an indicator that I'd be wrong!

 

Say I make a mod which adds a lootlist to a Scourge in Beast Of Winter. The IsInActiveScene check would look for the Scourge's GUID, and if it finds it it adds the lootlist. If someone doesn't have the DLC and installs my mod, and the IsInActiveScene check runs in, say, Vilario's Rest... would the result be "no, that GUID is not in this scene" or "Error: that GUID is not valid" and the mod wouldn't work.

 

Now that I think about it I could test this easily enough: hit /poe uuid in slack to get a random uuid which doesn't correspond to anything in the game files, and have the script search for that. If the mod still works then it means the search just looks for the ID and doesn't find it; if the mod stops working then it means the ID must be in the game files to begin with

Posted

I wanted to check on something: would the IsInActiveScene check be broken if it's checking for a DLC object in a game which doesn't have DLC installed? It just searches for a GUID and if the GUID isn't there it gets on with its life, and it doesn't need the GUID in question to be in the game files, right? I think a mod which adds lootlists to DLC and main game areas should be fully compatible with any combination of DLC or no DLC, as long as the lootlist itself doesn't use DLC assets, but figured I'd get Official Confirmation before going nuts

Your mod will work fine.  The check will simply never pass if it's searching for a GUID that doesn't exist in the game.

  • Like 1
  • 3 months later...
Posted (edited)

Here's an example game data object I created for this tutorial:

 

 

 

{
	"GameDataObjects": [
		{
			"$type": "Game.GameData.ModScriptHookGameData, Assembly-CSharp",
			"DebugName": "Metalworks_ItemAdd",
			"ID": "417f4f5e-7d01-4cd6-aa9d-1f0b1d0b4be2",
			"Components": [
				{
					"$type": "Game.GameData.ModScriptHookComponent, Assembly-CSharp",
					"RunOnlyOnce": "false",
					"SucceedOnlyOnce": "true",
					"Script": {
						"Conditional": {
							"Operator": 0,
							"Components": [
								{
									"$type": "OEIFormats.FlowCharts.ConditionalCall, OEIFormats",
									"Data": {
										"FullName": "Boolean IsInActiveScene(Guid)",
										"Parameters": [
											"3f84e9ad-761d-47fa-9e38-7a492ff24b95"
										]
									},
									"Not": false,
									"Operator": 0
								}
							]
						},
						"Scripts": [
							{
								"Data": {
									"FullName": "Void GenerateLootListInto(Guid, Guid)",
									"Parameters": [
										"3f84e9ad-761d-47fa-9e38-7a492ff24b95",
										"f3a0a676-c69c-46b2-9a9e-8bae94fae19a"
									]
								},
								"Conditional": {
									"Operator": 0,
									"Components": []
								}
							}
						]
					}
				}
			]
		}
	]
}

 

I am following this example, but my custom item doesn't appear in that container.

What am I doing wrong?

 

- copied your ModScriptHookGameData

- pointed it to my custom loot list "415badf2-4f4c-42d9-833f-d547cf7cd303"

- that loot list contains a reference to one custom item that I made: "8a0dc1b9-2b18-4f03-bfc7-5f62c599e79b"

 

Here's the code:

 

 

{
    "GameDataObjects": [
        {
            "$type": "Game.GameData.ModScriptHookGameData, Assembly-CSharp",
            "DebugName": "ItemsAdd_Marihi",
            "ID": "5642214e-9b85-4b1d-a84b-38def72a3cd9",
            "Components": [
                {
                    "$type": "Game.GameData.ModScriptHookComponent, Assembly-CSharp",
                    "RunOnlyOnce": "false",
                    "SucceedOnlyOnce": "true",
                    "Script": {
                        "Conditional": {
                            "Operator": 0,
                            "Components": [
                                {
                                    "$type": "OEIFormats.FlowCharts.ConditionalCall, OEIFormats",
                                    "Data": {
                                        "FullName": "Boolean IsInActiveScene(Guid)",
                                        "Parameters": [
                                            "3f84e9ad-761d-47fa-9e38-7a492ff24b95"
                                        ]
                                    },
                                    "Not": false,
                                    "Operator": 0
                                }
                            ]
                        },
                        "Scripts": [
                            {
                                "Data": {
                                    "FullName": "Void GenerateLootListInto(Guid, Guid)",
                                    "Parameters": [
                                        "3f84e9ad-761d-47fa-9e38-7a492ff24b95",
                                        "415badf2-4f4c-42d9-833f-d547cf7cd303"
                                    ]
                                },
                                "Conditional": {
                                    "Operator": 0,
                                    "Components": []
                                }
                            }
                        ]
                    }
                }
            ]
        },
        {
            "$type": "Game.GameData.LootListGameData, Assembly-CSharp",
            "DebugName": "MQ_Custom_LootList_Marihi",
            "ID": "415badf2-4f4c-42d9-833f-d547cf7cd303",
            "Components": [
                {
                    "$type": "Game.GameData.LootListComponent, Assembly-CSharp",
                    "Conditional": {
                        "Operator": 0,
                        "Components": []
                    },
                    "OutputChance": 1,
                    "OutputMode": "All",
                    "Items": [
                        {
                            "Conditional": {
                                "Operator": 0,
                                "Components": []
                            },
                            "OutputChance": 1,
                            "MinCount": 1,
                            "MaxCount": 1,
                            "Weight": 1,
                            "ItemID": "8a0dc1b9-2b18-4f03-bfc7-5f62c599e79b",
                            "LootListID": "00000000-0000-0000-0000-000000000000",
                            "LockedVisible": "false"
                        }
                    ]
                }
            ]
        }
    ]
}

 

 

And here's the item:

 

 

{
	"GameDataObjects": [
		{
			"$type": "Game.GameData.EquippableGameData, Assembly-CSharp",
			"DebugName": "Hands_U_Gauntlets_Of_Swift_Action",
			"ID": "8a0dc1b9-2b18-4f03-bfc7-5f62c599e79b",
			"Components": [
				{
					"$type": "Game.GameData.ItemComponent, Assembly-CSharp",
					"DisplayName": 131300000,
					"DescriptionText": 131300001,
					"FilterType": "Clothing",
					"InventoryAudioEventListID": "3b0b476e-883e-4a9e-9a61-956eabf30b6d",
					"IsQuestItem": "false",
					"IsIngredient": "false",
					"IsCurrency": "false",
					"IsAdventuringItem": "false",
					"CanSellForFullValue": "false",
					"MaxStackSize": 1,
					"NeverDropAsLoot": "false",
					"CanBePickpocketed": "false",
					"IsUnique": "true",
					"Value": 2800,
					"IconTextureSmall": "gui/icons/items/hand/gauntlet02_s.png",
					"IconTextureLarge": "gui/icons/items/hand/gauntlet02_l.png",
					"PencilSketchTexture": "",
					"InspectOnUseButton": [],
					"IsPlaceholder": "false"
				},
				{
					"$type": "Game.GameData.EquippableComponent, Assembly-CSharp",
					"EquipmentType": "None",
					"EquipmentSlot": "Hand",
					"AppearancePiece": {
						"ModelVisualDataPath": ""
					},
					"ItemModsIDs": [
						"4a7093a0-912e-4157-add0-d5c698597e2a"
					],
					"OnEquipVisualEffects": [],
					"RestrictedToClassIDs": [],
					"RestrictedToPlayer": "false",
					"ProficientAbilityID": "00000000-0000-0000-0000-000000000000",
					"CannotUnequip": "false",
					"ItemRendererPrefab": "",
					"ItemModel": "",
					"AnimationController": "",
					"PaperdollOverrideRenderer": "",
					"AttackSummonID": "00000000-0000-0000-0000-000000000000",
					"CannotSheathe": "false",
					"PropVisualEffects": []
				}
			]
		},
		{
			"$type": "Game.GameData.ItemModGameData, Assembly-CSharp",
			"DebugName": "MQ_Gauntlets_Of_Swift_Action_MOD_Quickness",
			"ID": "4a7093a0-912e-4157-add0-d5c698597e2a",
			"Components": [
				{
					"$type": "Game.GameData.ItemModComponent, Assembly-CSharp",
					"DisplayName": 131310000,
					"HideFromUI": "false",
					"EnchantCategory": "None",
					"Cost": 7,
					"DisplayEvenIfCostZero": "true",
					"CursesItem": "false",
					"StatusEffectsOnEquipIDs": [
						"349b6e69-58cb-40e0-b1af-f46459857d09"
					],
					"StatusEffectsOnLaunchIDs": [],
					"StatusEffectsOnAttackIDs": [],
					"AbilityModsOnEquipIDs": [],
					"OnEquipVisualEffects": [],
					"DamageProcs": [],
					"AbilitiesOnEquipIDs": []
				}
			]
		},
		{
			"$type": "Game.GameData.StatusEffectGameData, Assembly-CSharp",
			"DebugName": "MQ_Gauntlets_Of_Swift_Action_SE_Quickness",
			"ID": "349b6e69-58cb-40e0-b1af-f46459857d09",
			"Components": [
				{
					"$type": "Game.GameData.StatusEffectComponent, Assembly-CSharp",
					"StatusEffectType": "AttackSpeedMultiplier",
					"OverrideDescriptionString": -1,
					"OverrideDescriptionStringTactical": -1,
					"UseStatusEffectValueAs": "None",
					"BaseValue": 1.15,
					"DynamicValue": {
						"Stat": "None",
						"SkillDataID": "00000000-0000-0000-0000-000000000000",
						"ClassID": "00000000-0000-0000-0000-000000000000",
						"MultiplyBy": 1,
						"Operator": "Add"
					},
					"KeywordsIDs": [],
					"DurationType": "Infinite",
					"Duration": 1,
					"MaxStackQuantity": 0,
					"ApplicationBehavior": "StackIfAlreadyApplied",
					"ApplicationType": "ApplyOnStart",
					"IntervalRateID": "00000000-0000-0000-0000-000000000000",
					"StackedChildrenApplyEffects": "false",
					"ApplicationPrerequisites": {
						"Conditional": {
							"Operator": 0,
							"Components": []
						}
					},
					"TriggerAdjustment": {
						"TriggerOnEvent": "None",
						"TriggerOffEvent": "None",
						"ValidateWithAttackFilter": "false",
						"ParamValue": 0,
						"ValueAdjustment": 0,
						"DurationAdjustment": 0,
						"ResetTriggerOnEffectTimeout": "false",
						"MaxTriggerCount": 0,
						"IgnoreMaxTriggerCount": "false",
						"RemoveEffectAtMax": "false",
						"ChanceToTrigger": 1
					},
					"PowerLevelScaling": {
						"UseCharacterLevel": "false",
						"BaseLevel": 0,
						"LevelIncrement": 1,
						"MaxLevel": 0,
						"ValueAdjustment": 0,
						"DurationAdjustment": 0
					},
					"IsHostile": "false",
					"ClearOnCombatEnd": "false",
					"ClearOnRest": "false",
					"ClearOnFoodRest": "false",
					"ClearWhenAttacks": "false",
					"ClearOnDeath": "false",
					"HideFromCombatTooltip": "false",
					"HideFromCombatLog": "false",
					"HideFromUI": "false",
					"VisualEffects": [],
					"MaterialReplacementID": "00000000-0000-0000-0000-000000000000",
					"AttackFilter": {
						"KeywordsIDs": [],
						"KeywordLogic": "Or",
						"Race": "None",
						"IsKith": "false",
						"HealthPercentage": 0,
						"HealthOperator": "EqualTo",
						"Range": "None",
						"ClassTypeID": "00000000-0000-0000-0000-000000000000",
						"Source": "None",
						"DefendedBy": "None",
						"Empowered": "false",
						"Disengagement": "false",
						"Stealthed": "false",
						"UseStealthLinger": "false",
						"PowerLevel": 0,
						"PowerLevelOperator": "EqualTo",
						"ChanceToApply": 1,
						"AttackHostility": "Default",
						"TargetType": "None"
					},
					"AttackTargetFilter": {
						"KeywordsIDs": [],
						"KeywordLogic": "Or",
						"Race": "None",
						"IsKith": "false",
						"HealthPercentage": 0,
						"HealthOperator": "EqualTo",
						"Distance": 0,
						"DistanceOperator": "EqualTo",
						"HasDOT": "false",
						"IsMarked": "false",
						"TargetHostility": "Default"
					},
					"ExtraValue": 0,
					"OverridePenetration": 0,
					"DamageTypeValue": "All",
					"KeywordValueID": "00000000-0000-0000-0000-000000000000",
					"RaceValue": "None",
					"StatusEffectTypeValue": "None",
					"ItemValueID": "00000000-0000-0000-0000-000000000000",
					"AfflictionTypeValueID": "00000000-0000-0000-0000-000000000000",
					"StatusEffectsValueIDs": [],
					"AttackValueID": "00000000-0000-0000-0000-000000000000",
					"AttackOverrideValue": "None",
					"EventValue": "OnApply",
					"ClassValueID": "00000000-0000-0000-0000-000000000000",
					"WeaponTypeValue": "None",
					"AttackHitType": "None",
					"SkillValueID": "00000000-0000-0000-0000-000000000000",
					"AudioEventListID": "00000000-0000-0000-0000-000000000000",
					"BedRestDaysMinimum": 0,
					"BedRestDaysMaximum": 0
				}
			]
		}
	]
}

 

 

 

Extra info:

- The item referenced by "8a0dc1b9-2b18-4f03-bfc7-5f62c599e79b" exists, and I can check it via giveitem Hands_U_Gauntlets_Of_Swift_Action, just fine

- But it doesn't appear in that container. It also doesn't appear in Marihi's store, if I substitute the container id with:

> 3f84e9ad-a781-4fcd-9d95-e26215ecfe8c (NPC_Marihi), or

> 3f84e9ad-43x9-4ef6-a8c6-5b6acd3380b3 (Store_05_Marihi)

 

- I have tried resting for 25+ hours, and re-entering the shop.

 

So, what am I missing?

 

 


Update:

 

There seems to be some save-independent cache?

 

I have partially solved my case. The problem was that initially I tried ID of Marihi (NPC) without success, and later changed it to id of that container, but the thing got cached somehow. And the item was appearing only if I was setting "SucceedOnlyOnce": "false".

But after the change of store id, plus reroll of ModScriptHookGameData and LootListGameData ids, the item started to appear in that container, even if "SucceedOnlyOnce" was set "true". That's great.

 

 

The remaining part of the problem though is: I have experienced the following scenario:

 

- loaded an early save were my party is in Queen's Berth, and have never been to Periki's Overlook before

- ran to Marihi's Metalworks. And the item appears in that container. So far so good.

 

- now loading the same save again.

- and again running to Marihi's Metalkworks. Item does NOT appear in that container...

 

restarting pc

 

- loading the same save again.

- again running to Marihi's Metalkworks. Item appears in that container. Ok.

 

 

- loading the same save again.

- again running to Marihi's Metalkworks. Item does NOT appear in that container.

 

 

What the heck... :)

Edited by MaxQuest
Posted

I tried to reproduce that and couldn't get it to happen on 4.1.0. If you can provide the save game I might be able to see what's up.

Posted (edited)

I am on v4.1.0. This is the save on which I could reliably reproduce it: link to google drive

And here's the link to the mod I am making, that adds the gloves to that container: link

 

Now the scenario is:

 

You start in Queen's Berth.

> run to Marihi's Metalworks

> increase Aloth mechanics enough to open that container

> check that the item (Gauntlets of Swift Action) is there

 

reload the save

> run to Marihi's Metalworks

> increase Aloth mechanics enough to open that container

> check that the item (Gauntlets of Swift Action) this time is NOT there (and it won't appear until you restart the game)

 


Update:

 

I think I've figured it out.

 

It's not only about current game version. It's also important on what version was the save made.

Looking at the date of that save (9 july 2018) it must be made around v1.2.0.

 

I have re-saved it now. And if I use this new save (made on v4.1.0), I can no longer reproduce that shroedinger effect.

 

Hurray :)

Edited by MaxQuest
Posted

That's good. I believe I know what the issue is now - I'll test it with your save and have it fixed for 5.0.0.

  • Like 1
  • 3 weeks later...
Posted

What are these lines? Where are the values found/generated?

	"GameDataObjects": [
		{
			"$type": "Game.GameData.ModScriptHookGameData, Assembly-CSharp",
			"DebugName": "Metalworks_ItemAdd",
			"ID": "417f4f5e-7d01-4cd6-aa9d-1f0b1d0b4be2",
			"Components": [
				{
					"$type": "Game.GameData.ModScriptHookComponent, Assembly-CSharp",
					"RunOnlyOnce": "false",
					"SucceedOnlyOnce": "true",
					"Script": {
Posted

Most of that is defining what the Game Data object is and what components it has one it, as covered by the Basic Concepts tutorial.  The last three lines are specific data for the ModScriptHookComponent and are documented in the documentation here.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...