(help) md script to set a condition to unlock blueprints

The place to discuss scripting and game modifications for X4: Foundations.

Moderators: Moderators for English X Forum, Scripting / Modding Moderators

Post Reply
Realspace
Posts: 1400
Joined: Wed, 15. Nov 06, 10:21
x4

(help) md script to set a condition to unlock blueprints

Post by Realspace » Mon, 6. May 24, 16:10

I've removed ship blueprints and module hacking from research.
Then I made part of them known to the player at start (mk1 and amk2), through a script. Up to here no problem.
I wanted to make part of the blueprint only available if you buy a special package (let's call it upgrade_mod_mk3) from a pirate trader.

So wrote a simple condition, that the ware is present in player's inventory and it is at least one.
The ware is added to wares and stock and the traders do sell it. Also tried adding the ware in the inventory from the start.
But that does not trigger the blueprint's unlock either (while those I add from the start, mk1 and mk2, are normally unlocked and available at the modding bench)

this is the code:

Code: Select all

<set_value name="$ModsMk3" exact="
              [ware.mod_engine_boostthrust_01_mk3,
              ware.mod_engine_forwardthrust_01_mk3,
              ware.mod_engine_rotationthrust_01_mk3,
              ware.mod_engine_travelthrust_01_mk3,
              ware.mod_shield_capacity_01_mk3,
              ware.mod_shield_capacity_02_mk3,
              ware.mod_shield_rechargerate_01_mk3,
              ware.mod_weapon_damage_01_mk3,
              ware.mod_weapon_damage_02_mk3,
             ware.mod_weapon_speed_01_mk3,
              ware.mod_weapon_surfaceelement_01_mk3,
              ware.mod_ship_mass_01_mk3]"/>
              
				<do_if value="player.entity.inventory.{ware.upgrade_mod_mk3}.exists and player.entity.inventory.{ware.upgrade_mod_mk3} ge 1">
				
                    <do_all exact="$ModsMk3.count" counter="$i">
                        <add_encyclopedia_entry item="$ModsMk3.{$i}.id" type="equipmentmods"/>
                        <add_blueprints wares="$ModsMk3.{$i}"/>
                    </do_all>
              </do_if>
Maybe I wrote the wrong conditions at the cue? This is the conditions:

Code: Select all

            <conditions>
                <check_any>
                    <event_cue_signalled cue="md.Setup.GameStart"/>
                    <event_player_created/>
                    <event_game_loaded/>
                </check_any>
            </conditions>
I tried both do_if alone, i.e. player.entity.inventory.{ware.upgrade_mod_mk3}.exists and then player.entity.inventory.{ware.upgrade_mod_mk3} ge 1
They don't work, if you have the package in the inventory the blueprint are not unlocked.

User avatar
Dj_FRedy
Posts: 237
Joined: Mon, 27. Jun 11, 05:58
x4

Re: (help) md script to set a condition to unlock blueprints

Post by Dj_FRedy » Mon, 6. May 24, 20:12

Look at the data types for entity.inventory:

Code: Select all

<datatype name="entity" type="component">
  --
  <property name="inventory" result="Wares currently in entity's inventory" type="wareamountlist" />
  --
</datatype>

<datatype name="wareamountlist" pseudo="true">
  --
  <property name="{$ware}.exists" result="true iff there is a non-zero amount of $ware" type="boolean" />
  <property name="{$ware}.count" result="Number of wares of type $ware" type="integer" />
</datatype>

Code: Select all

<do_if value="player.entity.inventory.{ware.upgrade_mod_mk3}.exists and player.entity.inventory.{ware.upgrade_mod_mk3}.count ge 1">
The 'wares' attribute for 'add_blueprints' accepts lists so place it outside the loop:

Code: Select all

<add_blueprints wares="$ModsMk3"/>
Regarding the conditions, this should be enough to ensure that your cue is listened to when loading a saved game:

Code: Select all

<conditions>
    <!--
    This cue sets up global variables that can be used by other MD scripts.
    To wait for the setup to be complete, use the following condition:
        <event_cue_signalled cue="md.Setup.Start" />
    Unlike md.Setup.GameStart, the signal is also sent when loading a savegame,
    so also newly added cues can get the signal.
    -->
  <event_cue_signalled cue="md.Setup.Start"/>
</conditions>
Edited:
I reformulate to show you a structure and a condition 'event_inventory_added' that can help you

Code: Select all

<?xml version="1.0" encoding="utf-8"?>
<mdscript name="DebugHelp" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="md.xsd">
    <cues>
        <cue name="Cue">
            <conditions>
                <event_cue_signalled cue="md.Setup.Start"/>
            </conditions>
            <actions>
                --
            </actions>
            <cues>
                <cue name="Sub_Cue" instantiate="true">
                    <conditions>
                    	<!-- Event for when inventory wares were added to entity (object = entity, param = table of wares with corresponding amounts) -->
                        <event_inventory_added object="player.entity"/>
                    </conditions>
                    <actions>
                        ---
                    </actions>
                </cue>
            </cues>
        </cue>
    </cues>
</mdscript>
Something like this to retrieve the added/bought item/items:

Code: Select all

<cue name="Sub_Cue" instantiate="true">
    <conditions>
        <!-- Event for when inventory wares were added to entity (object = entity, param = table of wares with corresponding amounts) -->
        <event_inventory_added object="player.entity"/>
    </conditions>
    <actions>
        <set_value name="$ItemsAdded" exact="event.param"/>
        <set_value name="$itemtosearch" exact="ware.upgrade_mod_mk3.id"/>

        <do_all exact="$ItemsAdded.keys.count" counter="$i">
            <set_value name="$Item" exact="$ItemsAdded.keys.{$i}"/>
            <set_value name="$Amount" exact="$ItemsAdded.{$Item}"/>
            <debug_text text="'Added ' + $Amount + ' ' + $Item.name" chance="100"/>

            <do_if value="$Item.id == $itemtosearch">
                <debug_text text="'Item found: ' + $Item.id" chance="100"/>

                <do_for_each name="$ware" in="$ModsMk3">
                    <add_encyclopedia_entry item="$ware.id" type="equipmentmods"/>
                </do_for_each>

                <add_blueprints wares="$ModsMk3"/>

                <break/>
            </do_if>
        </do_all>
    </actions>
</cue>
"All my contributions to the Technical Support and Public Beta Feedback sections will be concise and to the point, no diatribes, that's what the other sections are for".
Thank you for your efforts.

Realspace
Posts: 1400
Joined: Wed, 15. Nov 06, 10:21
x4

Re: (help) md script to set a condition to unlock blueprints

Post by Realspace » Tue, 7. May 24, 13:36

First of all, thank you very much! It works now...

So to understand better, is it the new cue with <event_inventory_added object="player.entity"/> that makes the signal right?

I made this subcue:

Code: Select all

<cue name="MK1_Unlock" instantiate="true">
    <conditions>
        <!-- Event for when inventory wares were added to entity (object = entity, param = table of wares with corresponding amounts) -->
        <event_inventory_added object="player.entity"/>
    </conditions>
    <actions>
        <set_value name="$ItemsAdded" exact="event.param"/>
        <set_value name="$itemtosearch" exact="ware.upgrade_mod_MK1.id"/>
		
		<set_value name="$ModsMK1" exact="
              [ware.mod_engine_boostthrust_02_mk1,
			   ware.mod_engine_forwardthrust_02_mk1,
			   ware.mod_engine_strafethrust_02_mk1,
			   ware.mod_engine_travelthrust_02_mk1,
			   ware.mod_weapon_cooling_02_mk1,
               ware.mod_weapon_cooling_03_mk1,
			   ware.mod_weapon_damage_02_mk1,
               ware.mod_weapon_damage_03_mk1,]"/>

        <do_all exact="$ItemsAdded.keys.count" counter="$i">
            <set_value name="$Item" exact="$ItemsAdded.keys.{$i}"/>
            <set_value name="$Amount" exact="$ItemsAdded.{$Item}"/>
            <debug_text text="'Added ' + $Amount + ' ' + $Item.name" chance="100"/>

            <do_if value="$Item.id == $itemtosearch">
                <debug_text text="'Item found: ' + $Item.id" chance="100"/>

                <do_for_each name="$ware" in="$ModsMK1">
                    <add_encyclopedia_entry item="$ware.id" type="equipmentmods"/>
                </do_for_each>

                <add_blueprints wares="$ModsMK1"/>

                <break/>
            </do_if>
        </do_all>
    </actions>
</cue>
And so on, Mk2 and Mk3 and added each tool for sale to the shopper. I works perfectly.
Of course once the blueprints are acquired the tool can be removed and they remain. So I made that the ware can only be bought (can not be sold).
This works perfectly.

I'd profit of your expertise, I had done also a similar condition for acquiring the advanced module hacking and it seemed to work without doing a new cue, just the do_if condition.

Code: Select all

 <!--enhanced hacker add -->
				<do_if value="player.entity.inventory.{ware.research_module_hack}.exists">
					<add_research ware="ware.research_module_habitation"/>
					  <add_research ware="ware.research_module_defence"/>
					  <add_research ware="ware.research_module_production"/>
				</do_if>
Should I instead do another cue for it too?

Finally, I partially understand the more complicated but probably necessary way you used to create the list of blueprints as dependant from the ware.id, creating the $ItemsAdded and $itemtosearch..
Would you explain why this is necessary and not just a <do_if value="player.entity.inventory.{ware.research_module_mk3}.exists"> ?
Thank you so much

User avatar
Dj_FRedy
Posts: 237
Joined: Mon, 27. Jun 11, 05:58
x4

Re: (help) md script to set a condition to unlock blueprints

Post by Dj_FRedy » Tue, 7. May 24, 17:38

Hey, I'm glad my example works for you. Remember, it's just an example regarding the event relevant to your needs and a possible execution of how to retrieve the inventory items bought by the player from the trader, adapting it to your needs is up to you.
It could also be something like this if we just want to check a specific inventory item every time the player buys an item, this would be enough.

Code: Select all

<do_if value="player.entity.inventory.{ware.x}.exists">
    <set_value name="$ModsMK1" exact="[1,2,3]"/>

    <do_for_each name="$ware" in="$ModsMK1">
        <add_encyclopedia_entry item="$ware.id" type="equipmentmods"/>
    </do_for_each>

    <add_blueprints wares="$ModsMK1"/>
</do_if>
Player buys an item, event is triggered, check if a certain item is in the player's inventory, if true execute the scheduled actions.
But if you want to check amounts you will have to iterate with inventory items or newly added items, which is the example I originally showed you.

Anyway, the important thing is to find an event or condition that adapts to your needs and ‘instantiate’ the cue so that it persists in each execution or check it every x time. In the md.xsd file in the ‘Cue definition’ section you will find definitions to the possible attributes and if you haven't read it I leave you the link to the ‘Mission Director Guide’: https://wiki.egosoft.com:1337/X%20Rebir ... r%20Guide/ Not everything is there but it is a good basis.
"All my contributions to the Technical Support and Public Beta Feedback sections will be concise and to the point, no diatribes, that's what the other sections are for".
Thank you for your efforts.

Post Reply

Return to “X4: Foundations - Scripts and Modding”