How do I use <do_for_each> and <continue /> properly? [SOLVED]

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

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

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

How do I use <do_for_each> and <continue /> properly? [SOLVED]

Post by user1679 »

I have been working on a dynamic conversation system for my mod where I store the conversation options in a table and then
iterate through them when the player starts a conversation with the NPC.

The problem is, I want to be able to skip certain rows depending on some criteria but the <continue /> statement seems
to cause errors:

Opening and ending tag mismatch: do_if line 668 and continue do_ifcontinue

Here is the code block in question:
Spoiler
Show

Code: Select all

<do_for_each name="$key" in="Setup.$factionConvTable.$pages.{$pNum}">

	<do_if value="$key == 'info'">
	
		<!-- Check if this page has any information for the current conversation type (edit order or normal) -->
		<do_if value="$isEditing">
			<do_if value="$key.$editCnt == 0">
				<continue />
			</do_if>
		</do_if>
		<do_else>
			<do_if value="$key.$normalCnt == 0">
				<continue />
			</do_if>
		</do_else>
		
	</do_if>
	
</do_for_each>
Using <debug_to_file>, I know that all the $ variables have correct values and the lookup $key.$editCnt, $key.$normalCnt are also
retrieving the proper data from the table.

The table $factionConv is probably too large to post but here is the first record. It is full of several records which are used
to fill out the conversation options as the player uses the "next" and "previous" options:
Spoiler
Show

Code: Select all

<set_value name="$factionConvTable" exact="table[

	$pages = table[
	
		$1 = table[
			$info = table[$normalCnt = [4], $editCnt = [4]],
			$opt1 = table[$normalCaption = ['Any'], $editOrderCaption = ['Any'], $choice = ['faction.any'], $enabled = [true]],
			$opt2 = table[$normalCaption = ['Argon'], $editOrderCaption = ['Argon'], $choice = ['faction.argon'], $enabled = [faction.player.relationto.{faction.argon]],
			$opt3 = table[$normalCaption = ['Paranid'], $editOrderCaption = ['Paranid'], $choice = ['faction.paranid'], $enabled = [faction.player.relationto.{faction.paranid]],
			$opt4 = table[$normalCaption = ['Split'], $editOrderCaption = ['Split'], $choice = ['faction.split'], $enabled = [faction.player.relationto.{faction.split]],
			$opt5 = table[$normalCaption = ['More...'], $editOrderCaption = ['More...'], $choice = ['faction.none'], $enabled = [true]],
			$opt6 = table[$normalCaption = ['I changed my mind.'], $editOrderCaption = ['Cancel'], $choice = ['faction.none'], $enabled = [true]],
		],
Thanks!

GO TO SOLUTION
Last edited by user1679 on Wed, 29. Jun 22, 07:29, edited 4 times in total.
kuertee
EGOSOFT
EGOSOFT
Posts: 818
Joined: Sun, 14. Dec 03, 13:05
x4

Re: How do I use <do_for_each> and <continue /> properly?

Post by kuertee »

that block of code looks fine.
is line 668 in that block of code? which line in that block is 668?
user1679
Posts: 1088
Joined: Fri, 20. Jul 18, 23:20

Re: How do I use <do_for_each> and <continue /> properly?

Post by user1679 »

kuertee wrote: Tue, 28. Jun 22, 07:46 that block of code looks fine.
is line 668 in that block of code? which line in that block is 668?
Hi Kuertee,

the error is pointing to the blank line between the /do_else and /do_if after the second <continue />. I marked it in the code below with <!-- This is line 668 where the erorr is being reported -->


This is the whole method, it is lines 625 to 684

Code: Select all

<do_elseif value="$nextConv == 'conv_choose_npc_faction'">

	<!-- 2022-06-20
	
		Added new dynamic menu for faction choice

		From libraries/factions.xml
		
		Default Relation Ranges:
			  self:          1.0  to  1.0
			  ally:          0.5  to  1.0
			  member:        0.1  to  1.0
			  friend:        0.01 to  1.0
			  neutral:      -0.01 to  0.01
			  enemy:        -1.0  to -0.01
			  killmilitary: -1.0  to -0.1
			  kill:         -1.0  to -0.32
			  nemesis:      -1.0  to -1.0
			  
		We have to check if each faction exists (faction.argon?), player may not have expansion or faction was destroyed. Also check player reputation if needed
		
	-->

	<debug_to_file directory="Setup.$debugDir" name="Setup.$debugFile" text="'%s::%s = %s'.['conv_choose_npc_faction','$convPageNum', $convPageNum]" />
	
	<set_value name="$isEditing" exact="$isEditOrder? and ($isEditOrder == 'true')" />
	<set_value name="$pNum" exact="'$' + $convPageNum" /> <!-- because $convPageNum is numeric, we need to append the $ in order to use it as a key lookup in our table -->
	
	<do_for_each name="$key" in="Setup.$factionConvTable.$pages.{$pNum}">
	
		<do_if value="$key == 'info'">
		
			<!-- Check if this page has any information for the current conversation (edit or normal) -->
			<do_if value="$isEditing">
				<do_if value="$key.$editCnt == 0">
					<continue />
				</do_if>
			</do_if>
			<do_else>
				<do_if value="$key.$normalCnt == 0">
					<continue />
				</do_if>
			</do_else>
<!-- This is line 668 where the erorr is being reported -->
		</do_if>
		
		<!-- Add the options for this page -->
		
		<do_if value="$isEditing">
			<set_value name="$caption" exact="$key.$editOrderCaption" />
		</do_if>
		<do_else>
			<set_value name="$caption" exact="$key.$normalCaption" />
		</do_else>
		
		<add_player_choice_sub text="$caption" section="conv_handle_choose_npc_faction" choiceparam="$key.$factionName" selectable="(Setup.$useFactionRelations == 0) or ($key.$factionName == 'faction.none') or ($key.$enabled gt 0)" /> <!-- key.enabled is numeric faction relation value -->

	</do_for_each>
	
</do_elseif>
DeadAirRT
Posts: 1124
Joined: Fri, 25. Jan 19, 03:26
x4

Re: How do I use <do_for_each> and <continue /> properly?

Post by DeadAirRT »

Everything looks fine to me but I've only ever used <continue/> with do_all personally.
User avatar
euclid
Moderator (Script&Mod)
Moderator (Script&Mod)
Posts: 13485
Joined: Sun, 15. Feb 04, 20:12
x4

Re: How do I use <do_for_each> and <continue /> properly?

Post by euclid »

I'm guessing here but for testing purpose remove the <do_else>, i.e. just use

Code: Select all

			<do_if value="$key.$normalCnt == 0">
				<continue />
			</do_if>
Does it still gives the debug error? Also is the above debug error message complete/correct?

Cheers Euclid

Edit: Also worth mention that the line number of the debug messages do not always match the line numbers of your code (depends on editor).E.
"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
user1679
Posts: 1088
Joined: Fri, 20. Jul 18, 23:20

Re: How do I use <do_for_each> and <continue /> properly?

Post by user1679 »

Thanks kuertee, DearAirRT and euclid.

The suggestion by euclid worked, I ended up using two <do_if> statements instead of the <do_else>. A bit strange but I'm glad it worked out. Now I have the ability
to easily modify my conversations by simply editing the table in the library instead of the CUE. I also donn't have to have hundreds of <do_if> statements to handle
the logic of adding the options and handling the "next / back" buttons. NOTE: I'd like to move the <library> to its own file but I'm not sure how to include it in my
cue. Do I need to refer to it by the filename as well as the library name?


Of course it still needs refining but this new code block:
Spoiler
Show

Code: Select all


<!--
    The following table allows for easy modification of a conversation. If a GUI element should have more than one possible option, use [,] and then {1}, {2} to refer to them
-->

<!-- Table snippet for forums -->
<set_value name="$factionConvTable" exact="table[

	$pages = table[
	
		$1 = table[
			$info = table[$entryCount = [4, 4]],
			$opt0 = table[$caption = ['Any', 'Any'], $choice = 'faction.any'],
			$opt1 = table[$caption = ['Argon', 'Argon'], $choice = 'faction.argon'],
			$opt2 = table[$caption = ['Paranid', 'Paranid'], $choice = 'faction.paranid'],
			$opt3 = table[$caption = ['Split', 'Split'], $choice = 'faction.split'],
		],
	],
]" />

<do_elseif value="$nextConv == 'conv_choose_npc_faction'">

	<set_value name="$isEditing" exact="$isEditOrder? and ($isEditOrder == 'true')" />
	<set_value name="$pNum" exact="'$' + $convPageNum" /> <!-- because $convPageNum is numeric, we need to append the $ to the value it holds in order to use it as a key lookup in our table -->
	<set_value name="$tbl" exact="Setup.$factionConvTable.$pages.{$pNum}" /> <!-- temp table reference for less typing -->
	
	<do_for_each name="$row" in="$tbl">
	
		<do_if value="$row == '$info'">
		
			<!-- Check if this page has any information for the current conversation (edit or normal) -->
			
			<do_if value="$isEditing">
				<do_if value="$tbl.{$row}.{'$entryCount'}.{1} == 0">
					<continue />
				</do_if>
			</do_if>
			
			<do_if value="not $isEditing">
				<do_if value="$tbl.{$row}.{'$entryCount'}.{2} == 0">
					<continue />
				</do_if>
			</do_if>
			
		</do_if>
		<do_else>
		
			<!-- Add the options for this page -->
					
			<do_if value="$isEditing">
				<add_player_choice_sub text="'%s'.[$tbl.{$row}.{'$caption'}.{1}]" section="conv_handle_choose_npc_type" choiceparam="$tbl.{$row}.{'$choice'}" />
			</do_if>
			<do_else>
				<add_player_choice_sub text="'%s'.[$tbl.{$row}.{'$caption'}.{2}]" section="conv_handle_choose_npc_type" choiceparam="$tbl.{$row}.{'$choice'}" />
			</do_else>
			
		</do_else>

	</do_for_each>
	
</do_elseif>

Resulted in this "dynamic" conversation:
(dynamic in quotes because the button handler isn't programmed yet so you can't see page 2)

Spoiler
Show
Image

Edit: Replaced image with smaller 640x390 35.63 KB version per moderator note below
Last edited by Terre on Wed, 29. Jun 22, 08:06, edited 1 time in total.
Reason: Images posted directly to the forums should not be greater than 640x480 or 100kb, oversize image now linked

Return to “X4: Foundations - Scripts and Modding”