Strange MD error log: isplayerowned property lookup failed for component

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

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

Post Reply
user1679
Posts: 789
Joined: Fri, 20. Jul 18, 23:20

Strange MD error log: isplayerowned property lookup failed for component

Post by user1679 » Fri, 3. Jun 22, 09:22

I was looking through my debug log before finalizing my mod and I noticed this strange error:
[=ERROR=] 168.83 Error in MD cue md.PlayerFactionTagExt.OnPlayerOwnedObjectDeployed<inst:15946e>: Property lookup failed: event.param2.isplayerowned
* event.param2 == component.{0x159465L} (invalid)
* Expression: event.param2 and event.param2.isplayerowned
* Action: <do_if>, line 298
Is this error saying the property lookup failed because the object is invalid or that it isn't a valid property of the object?

It doesn't make much sense either way because I just started the game and hadn't deployed anything. None of those events (see below) should have even been triggered
unless they're triggered every time you enter the game with probes / satellites in your cargo hold? Also, scriptproperties.xml says different (see below).



The code in question:

Code: Select all

<do_if value="event.param2 and event.param2.isplayerowned">

in a cue triggered by the following events:

Code: Select all

<check_any>
	<event_satellite_launched space="player.galaxy"/>
	<event_lasertower_launched space="player.galaxy" />
	<event_mine_launched space="player.galaxy" />
	<event_navbeacon_launched space="player.galaxy" />
	<event_resourceprobe_launched space="player.galaxy" />
</check_any>

The problem is, even if those objects are considered components, the property isplayerowned is valid according to scriptproperties.xml:

** See last line in spoiler
Spoiler
Show

Code: Select all

  <datatype name="component">
    <property name="exists"         result="true iff the component exists in the game graph" type="boolean" />
    <property name="isoperational"  result="true iff the component exists in the game graph and is operational" type="boolean" />
    <property name="iswreck"        result="true iff the component exists in the game graph and is wrecked" type="boolean" />
    <property name="isconstruction" result="true iff the component exists in the game graph and is in construction state" type="boolean" />
    <property name="issurfaceelement" result="true iff the component is a surface element" type="boolean" />
    <property name="isclass.{$class}" result="true iff the component exists and is of the given class" type="boolean" />
    <property name="isclass.&lt;classname&gt;" result="Shortcut for isclass.{class.&lt;classname&gt;}" type="boolean" />
    <property name="isclass.{$list}" result="true iff the component exists and is of one of the classes in the list" type="boolean" />
    <property name="isrealclass.{$class}" result="true iff the component exists and is really of the given class, regardless of current state" type="boolean" />
    <property name="isrealclass.&lt;classname&gt;" result="Shortcut for isrealclass.{class.&lt;classname&gt;}" type="boolean" />
    <property name="isrealclass.{$list}" result="true iff the component exists and is really of one of the classes in the list, regardless of current state" type="boolean" />
    <property name="canbeattacked"  result="true iff the component exists in the game graph, is not a wreck, and is either operational, is of real class station, or is a child of a station" type="boolean" />
    <property name="extension" result="Source extension id" type="string" />
    <property name="isextensionpersonal" result="true iff the source extension is personal" type="boolean" />
    <property name="class" result="Component class" type="class" />
    <property name="realclass" result="Real component class, regardless of current state" type="class" />
    <property name="state" result="Component state" type="componentstate" />
    <property name="macro" result="Component macro" type="macro" />
    <property name="grouptag" result="Parent group tag" type="tag" />
    <property name="parent" result="Parent component" type="component" />
    <property name="container" result="Container context" type="container" />
    <property name="controllable" result="Controllable context" type="controllable" />
    <property name="defensible" result="Defensible context" type="defensible" />
    <property name="object" result="Object context" type="object" />
    <property name="ship" result="Ship context" type="ship" />
    <property name="station" result="Station context" type="station" />
    <property name="cluster" result="Cluster context" type="cluster" />
    <property name="sector" result="Sector context" type="sector" />
    <property name="zone" result="Zone context" type="zone" />
    <property name="room" result="Room context" type="room" />
    <property name="module" result="Module context" type="module" />
    <property name="hascontext.{$component}" result="true iff this is in the context of the other component" type="boolean" />
    <property name="commoncontext.{$component}" result="The common context between two components" type="component" />
    <property name="seed" result="Persistent pseudo-random seed (highest level of randomness supported for classes npc and dockingbay)" type="largeint" />
    <property name="name" result="Display name" type="string" />
    <property name="rawname" result="Raw display name, as text entry reference unless renamed manually" type="string" />
    <property name="knownname" result="Display name, ignoring the unknown-status" type="string" />
    <property name="hasbeenrenamed" result="true iff the component has been renamed" type="boolean" />
    <property name="position" result="Position relative to parent" type="position" />
    <property name="relativeposition.{$component}" result="Position relative to $component" type="position" />
    <property name="relativeposition.{$componentslot}" result="Position relative to $componentslot" type="position" />
    <property name="rotation" result="Rotation relative to parent" type="rotation" />
    <property name="relativerotation.{$component}" result="Rotation relative to $component" type="rotation" />
    <property name="relativerotation.{$componentslot}" result="Rotation relative to $componentslot" type="rotation" />
    <property name="velocity" result="Linear velocity relative to the cluster, but relative to the component's rotation (in m/s)" type="vector" />
    <property name="speed" result="Speed relative to the cluster (in m/s)" type="length" />
    <property name="relvelocity" result="Linear velocity relative to the component's parent, but relative to the component's rotation (in m/s)" type="vector" />
    <property name="relspeed" result="Speed relative to the component's parent (in m/s)" type="length" />
    <property name="attention" result="Attention level" type="attention" />
    <property name="size" result="Size (based on bounding box)" type="length" />
    <property name="length" result="Length (size in Z dimension, based on bounding box)" type="length" />
    <property name="height" result="Height (size in Y dimension, based on bounding box)" type="length" />
    <property name="width" result="Width (size in X dimension, based on bounding box)" type="length" />
    <property name="owner" result="Owner faction (cover owner if set, otherwise true owner)" type="faction" />
    <property name="coverowner" result="Cover Owner faction" type="faction" />
    <property name="trueowner" result="True Owner faction" type="faction" />
    <property name="isplayerowned" result="true iff owned by player (true owner)" type="boolean" />

Xenon_Slayer
EGOSOFT
EGOSOFT
Posts: 13093
Joined: Sat, 9. Nov 02, 11:45
x4

Re: Strange MD error log: isplayerowned property lookup failed for component

Post by Xenon_Slayer » Fri, 3. Jun 22, 11:39

Is there a delay between the event and the do_if action checking the ownership? If there is a component ID but it resolves to <invalid> then that means it no longer exists in the game, so it may have been destroyed and cleaned up.
Come watch me on Twitch where I occasionally play several of the X games

DeadAirRT
Posts: 1022
Joined: Fri, 25. Jan 19, 03:26
x4

Re: Strange MD error log: isplayerowned property lookup failed for component

Post by DeadAirRT » Fri, 3. Jun 22, 17:21

You don't always get the object returned, to check for exists without error use
event.param2? and @event.param2.isplayerowned

user1679
Posts: 789
Joined: Fri, 20. Jul 18, 23:20

Re: Strange MD error log: isplayerowned property lookup failed for component

Post by user1679 » Sat, 4. Jun 22, 04:59

Xenon_Slayer wrote:
Fri, 3. Jun 22, 11:39
Is there a delay between the event and the do_if action checking the ownership? If there is a component ID but it resolves to <invalid> then that means it no longer exists in the game, so it may have been destroyed and cleaned up.
Yes, I had to add a 5s delay to account for objects deployed for missions. For example, if I deploy a satellite for the Argon and don't have the delay, the mod
will add the player's faction tag but then the object will switch ownership to Argon but still have the player's tag on it.

user1679
Posts: 789
Joined: Fri, 20. Jul 18, 23:20

Re: Strange MD error log: isplayerowned property lookup failed for component

Post by user1679 » Sat, 4. Jun 22, 05:02

DeadAirRT wrote:
Fri, 3. Jun 22, 17:21
You don't always get the object returned, to check for exists without error use
event.param2? and @event.param2.isplayerowned
Interesting, thanks. Could you elaborate on what the ? and @ do compared to my original code without them? Be as technical as needed,
I code in C++ and I see some similarities in the X4 api, but of course it isn't that simple. (I just wish documentation was more complete).

user1679
Posts: 789
Joined: Fri, 20. Jul 18, 23:20

Re: Strange MD error log: isplayerowned property lookup failed for component

Post by user1679 » Sat, 4. Jun 22, 05:06

I don't know if this is appropriate but it is easier to get help debugging if people can see your code. Also note, I used Notepad++
to write this and tabs are "4 spaces" so formatting may not carry over to the forums very well.

And forgive the "wall of text" comments. I wrote this with the idea that new modders (like me) could use it as reference material.



** Mods: Please remove the code block if not allowed, thanks.


Spoiler
Show

Code: Select all

<?xml version="1.0" encoding="utf-8" ?>
<mdscript name="PlayerFactionTagExt" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="md.xsd">

    <!-- CHANGELOG

		2022-06-02 - user2046 - * Completely refactored script to utilize libraries
								* Added faction suffix option
								
        2021-05-13 - user2046 - * Fixed an issue where faction tag was added to mission deployed objects such as satellites.
                                  There is a minor drawback that if you have the ship tab or deployable tab open when this
                                  mod adds your tag, it will not appear until you close and reopen the tab.

                                  Still looking for a fix for this cosmetic issue.
    -->

	<cues>

		<library name="DynSettings" purpose="include_actions" version="200">
			<actions>
			
				<!-- ##############################################
						
					 CHANGE ONLY THE FOLLOWING VALUES BELOW
					 
					 runAtStartup
					 playerFactionPrefix
					 playerFactionSuffix
					 
				############################################### -->
				
				<!--
				
					Set $runAtStartup to true if you want the mod to apply tags to all owned property when you start/load your game

					Recommended: For first time installation only.
					
						This will rename any object you own that doesn't have your tags, including objects that you manually removed
						the tag from (maintaining an exempt list is too complicated and beyond the scope of this mod).
				-->
				
				<set_value name="$runAtStartup" exact="'false'" /> <!-- Remember to set back to 'false' after you exit the game -->

				
				<!--
					Change the prefix and suffix below to whatever you want added to new ships, stations, and deployables.
					Make sure to keep the single and double quotes. Tag doesn't have to be a three letter tag
					
					You MUST use '' if you want to skip either option. For example, to sikp playerFactionSuffix use:
					
						exact="''"
						
					Example naming result:

					
						If you buy a ship: Elite Sentinel (RND-123)
						
							* The (RND-123) is auto-assigned by the base game
							
						If your faction prefix is: [NCC]
						
							* Your ship will be renamed to: [NCC] Elite Sentinel (RND-123)
						
						If your faction suffix is: *!!!NPC KILLER!!!*
						
							* Your ship (with prefix) will be renamed to: [NCC] Elite Sentinel *!!!NPC KILLER!!!* (RND-123)
							* Your ship (without prefix) will be renamed to: Elite Sentinel *!!!NPC KILLER!!!* (RND-123)

				-->
				
				<set_value name="$playerFactionPrefix" exact="'[NCC]'" />	<!-- Gets applied to the beginning of the object name -->
				<set_value name="$playerFactionSuffix" exact="''" />		<!-- If defined, gets applied to the end of the object name but before the auto-assigned ID tag -->
								
			</actions>
			
		</library> <!-- DynSettings -->
		
		<library name="AddPlayerFactionTags" purpose="run_actions" version="200">

			<!-- ##############################################
					
				 DO NOT CHANGE ANYTHING IN THIS LIBRARY
					 
			############################################### -->
		
			<!--
				
				This library adds a user defined faction prefix/suffix to a player owned object. Its
				purpose is to reduce code repetition. It behaves like a CUE but allows the caller to
				set parameters and receive a result.
				
				Result is returned as a table in the following format:
				
					cueResult[$res = number, $desc = description]
					
						* number can be -1 for fail, 0 for success with no rename, 1 for success with rename
						* description is just a bit of detail, not necessarily useful unless caller wants to log it					
			-->
			
			<params>
				<param name="targetObject"/>
				<param name="prefix"/>
				<param name="suffix"/>
				<param name="doWriteLog"/>
			</params>
			<actions>

				<!-- Description
				
					Since the X4 API doesn't support the XML Contains() method, we will be using a REPLACE
					to see if our substring exists. If the substring exists, it will be replaced with our
					random string and stored in a temporary variable. This variable can be compared to the
					original:
					
						(original = temp) indicates the substring DID NOT EXIST
						(original != temp) indicates the substring DOES EXIST
					
					Thanks to kuertee (egosoft forums) for passing this on from unitrader (discord). I have
					slightly modified it for my use case.
				-->
				
				<do_if value="$targetObject">
				
					<set_value name="$wasRenamed" exact="0"/>
					<set_value name="$origName" exact="$targetObject.name"/>
					
					<!-- Use system time in format YYYY-MM-DD_HH-MM-SS as temp replacement to avoid collision with player/object names and descriptions -->
					<set_value name="$tmpString" exact="player.systemtime.{'%Y-%m-%d_%H-%M-%S'}" />
					
					<!-- Test for empty string instead of null because player may actually want to use the word null... -->
					<do_if value="$prefix != ''">

						<!-- Cache original name for future comparison -->
						<set_value name="$currentObjName" exact = "$targetObject.name" />						
						<set_value name="$tmpName" exact="$currentObjName" />
						
						<!-- Check for existing faction prefix by attempting to replace it with something else -->
						<substitute_text text="$tmpName">
							<replace string="$prefix" with="$tmpString" />
						</substitute_text>

						<!-- If equal, substitute failed and prefix did not exist so we need to add it -->
						<do_if value="$tmpName == $currentObjName">
						
							<set_object_name object="$targetObject" name="$prefix + ' ' + $currentObjName" comment=""/>
							<set_value name="$wasRenamed" exact="1" />
							
							<do_if value="$doWriteLog == 1">
								<write_to_logbook category="upkeep" title="Setup.$logBookTitle" text="Setup.$logTextDidTag + ' to: ' + $currentObjName + ' ' + $targetObject.idcode" />
							</do_if>
							
						</do_if>

					</do_if>
					
					<do_if value="$suffix != ''">
					
						<!-- Cache name again because it may have changed by adding the prefix -->
						<set_value name="$currentObjName" exact = "$targetObject.name" />
						<set_value name="$tmpName" exact="$currentObjName" />
						
						<!-- Check for our faction suffix -->
						<substitute_text text="$tmpName">
							<replace string="$suffix" with="$tmpString" />
						</substitute_text>

						<!-- If equal, substitute failed and suffix did not exist so we need to add it -->
						<do_if value="$tmpName == $currentObjName">
							<set_object_name object="$targetObject" name="$currentObjName + ' ' + $suffix" comment=""/>
							<set_value name="$wasRenamed" exact="1" />
							
							<do_if value="$doWriteLog == 1">
								<write_to_logbook category="upkeep" title="Setup.$logBookTitle" text="Setup.$logTextDidTag + ' to: ' + $currentObjName + ' ' + $targetObject.idcode" />
							</do_if>
							
						</do_if>
					</do_if>
					
					<!-- Set the result -->
					<do_if value="$wasRenamed gt 0">
						<set_value name="$cueResult" exact="table[$res = 1, $desc = 'Successfully renamed: ' + $origName]"/>
					</do_if>
					<do_else>
						<set_value name="$cueResult" exact="table[$res = 0, $desc = 'Skipped rename: ' + $origName]"/>
					</do_else>

					
				</do_if> <!-- $targetObject -->
				<do_else>
					<set_value name="$cueResult" exact="table[$res = '-1', $desc = '$targetObject cannot be NULL']"/>
				</do_else> <!-- $targetObject -->

				<remove_value name="$wasRenamed"/>
				<remove_value name="$origName"/>
				<remove_value name="$currentObjName"/>
				<remove_value name="$tmpName"/>
				<remove_value name="$tmpString"/>
				
				<return value="$cueResult" />
				
			</actions>
			
		</library> <!-- AddPlayerFactionTags -->
		
		<!-- ##############################################

			 DO NOT CHANGE ANYTHING BETWEEN THIS COMMENT
			 AND THE </mdscript> TAG AT THE END OF THE
			 DOCUMENT
			 
		############################################### -->
				
		<cue name="Setup" version="200">
			<conditions>
                <check_any>
                    <event_game_started />  <!-- new game -->
                    <event_game_loaded/>    <!-- load save -->
                </check_any>
			</conditions>
			<delay exact="1s"/>
			<actions>
			
				<!-- Include all the constants from DynSettings library above. They can be accessed by subcues / libraries in the following manner: Setup.$logBookTitle -->
				<include_actions ref="DynSettings"/>
				
				<set_value name="$logBookTitle" exact="'Player Faction Tag - Extended (mod)'" />
				<set_value name="$logTextDoTag" exact="'Adding player faction tag(s)'" />
				<set_value name="$logTextDidTag" exact="'Added player faction tag(s)'" />
				
				<write_to_logbook category="upkeep" title="$logBookTitle" text="'Mod loaded.\nPlayer faction prefix set to: ' + $playerFactionPrefix + '\nPlayer faction suffix set to: ' + $playerFactionSuffix"/>
				
				<do_if value="$runAtStartup == 'true'">
					<!-- Update existing objects from before mod was installed -->
					<signal_cue_instantly cue="TagOwnedObjectsAtGameStart" />
				</do_if>
				
			</actions>
			<cues>

				<cue name="OnPlayerOwnedObjectBuilt" instantiate="true" namespace="default" version="200">
					<conditions>
						<check_all>
							<check_any>
								<event_player_built_ship/>
								<event_player_built_station/>
							</check_any>
						</check_all>
					</conditions>
                    <delay exact="5s" /> <!-- user2046 - Wait 5 seconds before performing ACTIONS -->
					<actions>

                        <!-- user2046

                             If the object was build for a mission, the delay above should have allowed the game to change the owner
                             to that of the faction that offered the mission. In this case, we don't want to add the player tag
                        -->

                        <!-- <do_if value=" $event.param.isclass.station or $event.param.isclass.ship "> -->
						<do_if value="event.param and event.param.isplayerowned">
							<run_actions ref="AddPlayerFactionTags" result="$cueResult">
								<param name="targetObject" value="event.param"/>
								<param name="prefix" value="Setup.$playerFactionPrefix"/>
								<param name="suffix" value="Setup.$playerFactionSuffix"/>
								<param name="doWriteLog" value="1"/>
							</run_actions>
						</do_if>
						
					</actions>
				</cue>

				<cue name="OnPlayerOwnedObjectDeployed" instantiate="true" namespace="default" version="200">
					<conditions>
						<check_all>
							<check_any>
								<event_satellite_launched space="player.sector"/>
								<event_lasertower_launched space="player.sector" />
								<event_mine_launched space="player.sector" />
								<event_navbeacon_launched space="player.sector" />
								<event_resourceprobe_launched space="player.sector" />
							</check_any>
						</check_all>
                        <!-- <check_value value="event.param2.isplayerowned" />  user2046 - TODO: Unreliable? Deployed objects take a few seconds to assign owner -->						
					</conditions>
                    <delay exact="5s" /> <!-- user2046 - Wait 5 seconds before performing ACTIONS -->
					<actions>

                        <!-- user2046

                             If the object was deployed for a mission, the delay above should have allowed the game to change the owner
                             to that of the faction that offered the mission. In this case, we don't want to add the player tag
                        -->

						<!-- TODO: isplayerowned doesn't work if object is destroyed. Need better check for valid object. Also, these objects are considered components and the 'owner' property is a 'true faction' -->
						<do_if value="event.param2 and (event.param2.isplayerowned)">
							<run_actions ref="AddPlayerFactionTags" result="$cueResult">
								<param name="targetObject" value="event.param2"/>
								<param name="prefix" value="Setup.$playerFactionPrefix"/>
								<param name="suffix" value="Setup.$playerFactionSuffix"/>
								<param name="doWriteLog" value="1"/>
							</run_actions>						
						</do_if>
						
						<remove_value name="$cueResult" />
					</actions>
				</cue>

				<cue name="TagOwnedObjectsAtGameStart" instantiate="false" namespace="default" version="200">
					<conditions>
						<event_cue_signalled />
					</conditions>
					<delay exact="10s" />
					<actions>
					
						<create_group groupname="$ownedObjects"/>
						<find_object owner="faction.player" groupname="$ownedObjects" space="player.galaxy" multiple="true" recursive="true" checkoperational="false" />
						
						<write_to_logbook category="upkeep" title="Setup.$logBookTitle" text="'Startup begin, checking ' + $ownedObjects.count + ' player owned objects for missing faction tag.\n\nRecommend to disable after first run by setting runAtStartup to FALSE'"/>
						
						<set_value name="$renamedCount" exact="0" />
						
						<do_all exact="$ownedObjects.count" counter="$i">
						
							<run_actions ref="AddPlayerFactionTags" result="$cueResult">
								<param name="targetObject" value="$ownedObjects.{$i}"/>
								<param name="prefix" value="Setup.$playerFactionPrefix"/>
								<param name="suffix" value="Setup.$playerFactionSuffix"/>							  
								<param name="doWriteLog" value="0"/>
							</run_actions>
							
							<do_if value="$cueResult.$res gt -1">
								<!-- If something was renamed, increment counter -->
								<set_value name="$renamedCount" operation="add" exact="$cueResult.$res"/>
							</do_if>
							
						</do_all>
						
						<write_to_logbook category="upkeep" title="Setup.$logBookTitle" text="'Startup complete, renamed ' + $renamedCount + ' objects'"/>
						
						<remove_value name="$ownedObjects" />
						<remove_value name="$renamedCount" />
						<remove_value name="$cueResult" />						
					</actions>
				</cue>

				<cue name="RenameClaimedShip" instantiate="true" namespace="default" version="200">
					<conditions>
						<event_player_owned_claimed_object />
					</conditions>
					<actions>
						<do_if value="event.param and event.param.isplayerowned">
							<run_actions ref="AddPlayerFactionTags" result="$cueResult">
								<param name="targetObject" value="event.param"/>
								<param name="prefix" value="Setup.$playerFactionPrefix"/>
								<param name="suffix" value="Setup.$playerFactionSuffix"/>							  
								<param name="doWriteLog" value="1"/>
							</run_actions>
						</do_if>
						
						<remove_value name="$cueResult" />						
					</actions>
				</cue>

				<cue name="RenameClaimedShipTwo" instantiate="true" namespace="default" version="200">
					<conditions>
						<event_player_signal_unlock_finished />
					</conditions>
					<actions>
						<do_if value="event.param and event.param.type == signalleaktype.claim">
							<write_to_logbook category="upkeep" title="Setup.$logBookTitle" text="$logTextDoTag + ' to scanned object: ' + event.param.object.name + ' ' + event.param.type"/>
							<run_actions ref="AddPlayerFactionTags" result="$cueResult">
								<param name="targetObject" value="event.param"/>
								<param name="prefix" value="Setup.$playerFactionPrefix"/>
								<param name="suffix" value="Setup.$playerFactionSuffix"/>							  
								<param name="doWriteLog" value="1"/>
							</run_actions>						
						</do_if>
						
						<remove_value name="$cueResult" />
					</actions>
				</cue>

				<cue name="RenameBoardedObject" instantiate="true" namespace="default" version="200">
					<conditions>
						<event_cue_signalled />
					</conditions>
					<actions>
						<run_actions ref="AddPlayerFactionTags" result="$cueResult">
							<param name="targetObject" value="event.param"/>
							<param name="prefix" value="Setup.$playerFactionPrefix"/>
							<param name="suffix" value="Setup.$playerFactionSuffix"/>						  
							<param name="doWriteLog" value="1"/>
						</run_actions>
						
						<remove_value name="$cueResult" />						
					</actions>
				</cue>

			</cues>
		</cue>
	</cues>
</mdscript>

User avatar
euclid
Moderator (Script&Mod)
Moderator (Script&Mod)
Posts: 13292
Joined: Sun, 15. Feb 04, 20:12
x4

Re: Strange MD error log: isplayerowned property lookup failed for component

Post by euclid » Sat, 4. Jun 22, 11:50

Could you elaborate on what the ? and @ do compared to my original code without them? Be as technical as needed,

Have a look here, in particular on page 19, top. ;-)

Cheers Euclid
"In any special doctrine of nature there can be only as much proper science as there is mathematics therein.”
- Immanuel Kant (1724-1804), Metaphysical Foundations of the Science of Nature, 4:470, 1786

DeadAirRT
Posts: 1022
Joined: Fri, 25. Jan 19, 03:26
x4

Re: Strange MD error log: isplayerowned property lookup failed for component

Post by DeadAirRT » Sat, 4. Jun 22, 15:33

Euclid linked the info but
? Is for checking if something exists, returns a bool instead of a possible null and doesn't cause debug errors

@ is for suppressing property lookup errors, you will still either get the regular output but null won't cause an error.

Edit: i only use @ on things i know may not always exist.

Xenon_Slayer
EGOSOFT
EGOSOFT
Posts: 13093
Joined: Sat, 9. Nov 02, 11:45
x4

Re: Strange MD error log: isplayerowned property lookup failed for component

Post by Xenon_Slayer » Sun, 5. Jun 22, 00:37

For lookups of event.param properties the ? operator doesn't really do much. I believe that if a cue/ai-script section can potentially have an event.param/2/3 then ? will return true regardless, even if that param is null. The ? operator is more checking if for variable existence, not keyword existence.

The @ operator is useful for simply suppressing errors if you're fine with all possible causes of a 'false'. In the case of "@event.param2.isplayerowned", should that return false without an error that means that either a) The object is not player owned OR b) the object is invalid. It's essentially shorthand for "event.param2.exists and event.param2.isplayerowned". Hope that clears it up.
Come watch me on Twitch where I occasionally play several of the X games

user1679
Posts: 789
Joined: Fri, 20. Jul 18, 23:20

Re: Strange MD error log: isplayerowned property lookup failed for component

Post by user1679 » Sun, 5. Jun 22, 02:52

Thanks Euclid for the documentation, DeadAirRT for the breakdown and Xenon_Slayer for further explanation.
Xenon_Slayer wrote:
Sun, 5. Jun 22, 00:37
The @ operator is useful for simply suppressing errors if you're fine with all possible causes of a 'false'. In the case of "@event.param2.isplayerowned", should that return false without an error that means that either a) The object is not player owned OR b) the object is invalid. It's essentially shorthand for "event.param2.exists and event.param2.isplayerowned". Hope that clears it up.
So I gather then if I only care to rename something that exists and is player owned, this should suffice:

<do_if value="@event.param2.isplayerowned">
</do_if>

because I don't really care why it failed only if it should be renamed or not.

Xenon_Slayer
EGOSOFT
EGOSOFT
Posts: 13093
Joined: Sat, 9. Nov 02, 11:45
x4

Re: Strange MD error log: isplayerowned property lookup failed for component

Post by Xenon_Slayer » Mon, 6. Jun 22, 23:55

Yep, that'll do it. @ is very convenient to reduce complex expressions, but it can hide legitimate errors if you don't understand all possible fail cases.
Come watch me on Twitch where I occasionally play several of the X games

Post Reply

Return to “X4: Foundations - Scripts and Modding”