Mod spawned NPC bug - loading a save causes conversation spam

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

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

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

Mod spawned NPC bug - loading a save causes conversation spam

Post by user1679 » Mon, 9. Aug 21, 04:42

My mod spawns an NPC in the manager's office. She has a branching conversation that works fine on the first run. The problem is when you save your game
and reload it, her conversation branch is duplicated.

For example, when she first spawns and you talk to her she will say one of the following:

"Hello"
"Hello there"
"Hi, how are you?"

and her conversation dialog will say:

"I want to hire specialists"
"I have to go, bye"

When you load a save, her conversation dialog now looks like this:

"I want to hire specialists"
"I want to hire specialists"
"I want to hire specialists"
"I have to go, bye"
"I want to hire specialists"

and if you talk to her she spams you with all three greetings repeated 5 times.

I've tried many different ways to fix this but nothing works. When you leave a sector or dock at a different station, the NPC is despawned and a new one is spawned. This
works fine with no duplication. I've tried to despawn and respawn the NPC on save load but it doesn't work.

If anyone has any advice it would be appreciated.

https://www.nexusmods.com/x4foundations ... ?tab=files

arshiba
Posts: 48
Joined: Thu, 1. Jul 04, 15:30
x4

Re: Mod spawned NPC bug - loading a save causes conversation spam

Post by arshiba » Mon, 9. Aug 21, 15:02

user1679 wrote:
Mon, 9. Aug 21, 04:42
If anyone has any advice it would be appreciated.
The first weird thing I noticed is

Code: Select all

<!-- user2046 2021-03-13 - Cleanup instantiated cue to avoid memory leaks. Calling from within the cue to reset still allows all actions to complete -->
<reset_cue cue="this" />
Ironically, this could have led to a leak. But after testing, the result is no, just Undefined Behavior. And actually without consequences.
Resetting an instantiated cue will stop it forever, because it is not supposed to be in the waiting state (only its static cue is).
user1679 wrote:
Mon, 9. Aug 21, 04:42
When you leave a sector or dock at a different station, the NPC is despawned and a new one is spawned. This
works fine with no duplication. I've tried to despawn and respawn the NPC on save load but it doesn't work.
The main problem is that the NPC actor is deleted, but the cue chain is not.
Every instance of "rse_place_officer" has 2 subcues in waiting state "rse_start_conversation", "rse_conversation" which prevents normal completion. All your cues work in a single namespace, so the extra instances are invisible. Every time the game is reloaded, the condition for starting the cue "rse_start_conversation" is reevaluated with the same $ROfficer variable. When you start a conversation you get a line multiplied by the number of instances of "rse_place_officer".

PS: Better to completely redesign the cue structure and refactor the code. The current code has already resulted in noticable littering of game saves:

Code: Select all

<cue id="73268" name="rse_place_officer" version="400" state="waiting">
  <cue id="73269" name="rse_start_conversation" version="400" />
  <cue id="73270" name="rse_conversation" version="400" />
  <instances>
    <cue id="73271" state="complete" time="75935.644">	<!-- THIS IS TRASH -->
      <actors>
        <actor>
          <component class="npc" macro="character_recruitment_svc_recruiter_cau_macro" name="Xandra Danar" code="YCX-707" known="1" read="0" page="9992046" id="[0x101ceb4]">
            <traits flags="mission|remotecommable|customconversation">
              <skill type="boarding" value="15" />
              <skill type="engineering" value="15" />
              <skill type="management" value="15" />
              <skill type="morale" value="11" />
              <skill type="piloting" value="15" />
            </traits>
            <entity type="recruitingofficer" />
            <npcseed seed="3568111646" />
          </component>
        </actor>
      </actors>
      <cue id="73272" base="73269" state="waiting" />
      <cue id="73273" base="73270" state="waiting" />
    </cue>
    ...
    <cue id="73277" state="complete" time="76270.233">	<!-- LAST ONE, the only expected -->
      <actors>
        <actor id="[0x1033afb]" />
      </actors>
      <cue id="73278" base="73269" state="waiting" />
      <cue id="73279" base="73270" state="waiting" />
    </cue>
  </instances>
</cue>

arshiba
Posts: 48
Joined: Thu, 1. Jul 04, 15:30
x4

Re: Mod spawned NPC bug - loading a save causes conversation spam

Post by arshiba » Tue, 10. Aug 21, 21:09

At first I wanted to make a simple example of how the cue structure could be redesigned to avoid leaks. But then, gradually optimizing other code parts, I refactored the whole script.
And made some improvements:
* The conversations "choose ship" and "choose amount" are swapped and the 5th option is replaced with the current maximum (for free space or available money) that can be recruited
* Marines are assigned as marines, not service crew
* New crew NPC are immediately created from templates (as in the appropriate logic in conversations.xml "NPCAssigned_Transfer")
^ An attempt to make a workaround for the critical issue stated in the readme.txt. Are there still troubles with the crew tab?

Maybe this is inappropriate, but I want to highlight some issues in the previous code. Just in case, many of them are described here (MD Guide).
* Cue and script names should starts with uppercase letter
* The conditions of "rse_new_game_started", "rse_start", "rse_save_loaded" are a complete mess and should be optimized out
* Patching logic of "rse_save_loaded", "rse_remove_rofficer" is broken (can't be from 400 to 400)
* reset_cue of instantiated cue is undefined behaviour
* Cue "rse_genNPCMacro" is better to reimplement as <library purpose="run_actions">
* The instances of "rse_place_officer" can't be wiped out except explicitly with cancel_cue
* Lots of temporary variables without remove_value (every byte matter in game save files!)
* There is strict dependency for split DLC (no traces of this content found) (maybe optional=true?)
* No need for "new game" restriction to use (install or uninstall) this mod

New version:

Code: Select all

<?xml version="1.0" encoding="utf-8"?>
<mdscript name="RecruitmentServiceExtended" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="md.xsd">
  <cues>
    <library name="DynamicSettings" purpose="include_actions">
      <actions>
        <set_value name="$npcPrices" exact="table[
          $engineer = 50000Cr,
          $pilot    = 100000Cr,
          $manager  = 150000Cr,
          $marine   = 90000Cr
        ]" />
        <set_value name="$npcMacros" exact="table[
          $engineer = table[$male = [macro.character_recruitment_svc_arg_m_engineer_macro], $female = [macro.character_recruitment_svc_arg_f_engineer1_macro, macro.character_recruitment_svc_arg_f_engineer2_macro]],
          $pilot    = table[$male = [macro.character_recruitment_svc_arg_m_pilot_macro],    $female = [macro.character_recruitment_svc_arg_f_pilot1_macro, macro.character_recruitment_svc_arg_f_pilot2_macro]],
          $manager  = table[$male = [macro.character_recruitment_svc_arg_m_manager_macro],  $female = [macro.character_recruitment_svc_arg_f_manager1_macro, macro.character_recruitment_svc_arg_f_manager2_macro]],
          $marine   = table[$male = [macro.character_recruitment_svc_arg_m_marine_macro],   $female = [macro.character_recruitment_svc_arg_f_marine1_macro, macro.character_recruitment_svc_arg_f_marine2_macro]],
        ]" />
        <set_value name="$npcSkills" exact="table[
          $engineer = [[skilltype.engineering, 3, 9], [skilltype.piloting, 1, 3], [skilltype.management, 1, 3], [skilltype.boarding, 1, 3], [skilltype.morale, 1, 6]],
          $pilot    = [[skilltype.engineering, 1, 3], [skilltype.piloting, 3, 9], [skilltype.management, 1, 3], [skilltype.boarding, 1, 3], [skilltype.morale, 1, 6]],
          $manager  = [[skilltype.engineering, 1, 3], [skilltype.piloting, 1, 3], [skilltype.management, 3, 9], [skilltype.boarding, 1, 3], [skilltype.morale, 1, 6]],
          $marine   = [[skilltype.engineering, 1, 3], [skilltype.piloting, 1, 3], [skilltype.management, 1, 3], [skilltype.boarding, 3, 9], [skilltype.morale, 1, 6]],
        ]" />
      </actions>
    </library>

    <cue name="Setup">
      <actions>
        <set_value name="$debugFile" exact="'log_' + md.$SystemTimeAtGamestart + '.txt'" />
        <set_value name="$debugDir" exact="'rse'" />

        <set_value name="$convLinesGreeting" exact="[2001, 2002, 2012, 12101, 12102, 30223004, 30226222]" />
        <set_value name="$convLinesBye" exact="[2007, 2008, 2011, 2013, 1000207, 30223006]" />
        <set_value name="$convLinesExpensive" exact="[5036, 9004, 10069]" />
        <set_value name="$convLinesMore" exact="[1504, 5003, 10302]" />

        <include_actions ref="DynamicSettings" />

        <create_group groupname="$settledStations" />
        <debug_to_file directory="$debugDir" name="$debugFile" text="'%.3s, Setup done.'.[player.age]" />
      </actions>
      <delay exact="1ms" />
      <actions>
        <!-- First time settle (already docked) -->
        <signal_cue cue="MoveHandler" />
      </actions>
      <cues>
        <cue name="UpdateSettings" instantiate="true">
          <conditions>
            <event_cue_signalled cue="md.Setup.Start" />
          </conditions>
          <actions>
            <include_actions ref="DynamicSettings" />
            <debug_to_file directory="$debugDir" name="$debugFile" text="'%.3s, Settings updated.'.[player.age]" />
          </actions>
        </cue>

        <cue name="MoveHandler" instantiate="true">
          <conditions>
            <check_any>
              <event_object_changed_object object="player.entity" />
              <event_cue_signalled />
            </check_any>
          </conditions>
          <actions>
            <do_if value="player.station.exists">
              <debug_to_file directory="$debugDir" name="$debugFile" text="'%.3s, Player moved to station %s (%s).'.[player.age, player.station.knownname, player.station.idcode]" />
              <do_if value="not $settledStations.indexof.{player.station}">
                <signal_cue_instantly cue="SettleStation" param="player.station" />
              </do_if>
            </do_if>
          </actions>
        </cue>

        <cue name="SettleStation" instantiate="true" namespace="this">
          <conditions>
            <event_cue_signalled />
          </conditions>
          <actions>
            <set_value name="$station" exact="event.param" />
            <assert value="$station.exists" />
            <!-- Attempt to locate the manager's office and spawn the R.Officer -->
            <set_value name="$room" exact="$station.controlentity.{controlpost.manager}.room" />
            <do_if value="$room">
              <find_npc_slot name="$slot" object="$room" tags="tag.rofficer" />
              <do_if value="$slot">
                <create_cue_actor name="$actor" cue="this" macro="character_recruitment_svc_recruiter_cau_macro">
                    <page exact="9992046"/>
                    <!-- So the spawned NPC and station aren't hostile to each other -->
                    <owner exact="$station.owner"/>
                    <skills>
                        <skill type="management" exact="15"/>
                        <skill type="morale" min="6" max="15"/>
                        <skill type="piloting" exact="15"/>
                        <skill type="engineering" min="6" max="15"/>
                        <skill type="boarding" min="6" max="15"/>
                    </skills>
                </create_cue_actor>
                <assert value="$actor" />
                <set_entity_traits entity="$actor" missionactor="true" customhandler="true"/>
                <set_entity_type entity="$actor" type="entitytype.recruitingofficer"/>
                <add_actor_to_room actor="$actor" slot="$slot" />

                <add_to_group groupname="Setup.$settledStations" object="$station" />
                <debug_to_file directory="Setup.$debugDir" name="Setup.$debugFile" text="'%.3s, Settle station %s (%s) with %s.'.[player.age, $station.knownname, $station.idcode, $actor.name]" />
              </do_if>
            </do_if>
            <do_if value="not $actor?">
              <debug_to_file directory="Setup.$debugDir" name="Setup.$debugFile" text="'%.3s, Cannot settle station %s (%s).'.[player.age, $station.knownname, $station.idcode]" />
              <cancel_cue cue="namespace" />
            </do_if>
            <remove_value name="$room" />
            <remove_value name="$slot" />
          </actions>
          <cues>
            <cue name="UnsettleStation">
              <conditions>
                <check_any>
                  <check_all>
                    <event_object_changed_attention object="$station" />
                    <check_value value="event.param lt attention.nearby"/>
                  </check_all>
                  <event_object_destroyed object="$station" />
                </check_any>
              </conditions>
              <actions>
                <clear_actor_roomslot actor="$actor" />
                <remove_actor_from_room actor="$actor" />
                <destroy_object object="$actor" />
                <remove_from_group group="Setup.$settledStations" object="$station" />
                <debug_to_file directory="Setup.$debugDir" name="Setup.$debugFile" text="'%.3s, Unsettle station %s (%s).'.[player.age, $station.knownname, $station.idcode]" />
                <cancel_cue cue="namespace" />
              </actions>
            </cue>

            <cue name="ConversationStart" instantiate="true">
              <conditions>
                  <check_any>
                    <event_conversation_started actor="$actor" />
                    <event_conversation_returned_to_section actor="$actor" section="default"/>
                  </check_any>
              </conditions>
              <actions>
                <add_npc_line speaker="$actor" line="Setup.$convLinesGreeting.random" />
                <add_player_choice_sub text="{9992046,1010}" section="start" />
                <add_player_choice_sub text="{9992046,1011}" section="bye" position="bottom_right" />
              </actions>
            </cue>

            <cue name="ConversationNext" instantiate="true">
              <conditions>
                <event_conversation_next_section actor="$actor" />
              </conditions>
              <actions>
                <set_value name="$nextConv" exact="'no'" />

                <do_if value="event.param == 'bye' or event.param == 'g_cancel'">
                  <add_npc_line speaker="$actor" line="Setup.$convLinesBye.random" />
                  <include_actions ref="ClearTemporaries" />
                </do_if>
                <do_elseif value="event.param == 'expensive'">
                  <add_npc_line speaker="$actor" line="Setup.$convLinesExpensive.random" />
                  <include_actions ref="ClearTemporaries" />
                </do_elseif>

                <do_elseif value="event.param == 'start'">
                  <set_value name="$nextConv" exact="'choose_npc_type'" />
                </do_elseif>

                <do_elseif value="event.param == 'choosen_npc_type'">
                  <set_value name="$npcType" exact="event.param2" />
                  <set_value name="$npcPrice" exact="Setup.$npcPrices.{$npcType}" />
                  <set_value name="$nextConv" exact="'choose_npc_gender'" />
                </do_elseif>

                <do_elseif value="event.param == 'choosen_npc_gender'">
                  <set_value name="$npcGender" exact="if event.param2 == 'any' then ['$male', '$female'].random else event.param2" />
                  <set_value name="$nextConv" exact="'choose_ship'" />
                </do_elseif>

                <do_elseif value="event.param == 'choosen_ship'">
                  <set_value name="$selectedShip" exact="event.param2" />
                  <set_value name="$npcMaxCount" exact="[$selectedShip.people.free, player.money / $npcPrice].min" />
                  <do_if value="$npcMaxCount gt 0">
                    <set_value name="$nextConv" exact="'choose_amount'" />
                  </do_if>
                  <do_else>
                    <do_if value="$selectedShip.people.free gt 0">
                      <add_npc_line speaker="$actor" line="1503" hidechoices="true" /> 
                      <add_player_choice_sub text="{9992046,1015}" section="start" />
                    </do_if>
                    <do_else>
                      <add_npc_line speaker="$actor" line="11803" hidechoices="true" />
                      <set_value name="$nextConv" exact="'choose_ship'" />
                    </do_else>
                  </do_else>
                </do_elseif>

                <do_elseif value="event.param == 'choosen_amount'">
                  <set_value name="$npcCount" exact="event.param2" />
                  <set_value name="$npcCost" exact="$npcPrice * $npcCount" />
                  <set_value name="$doRecruit" />
                </do_elseif>

                <do_else>
                  <add_conversation_view />
                  <include_actions ref="ClearTemporaries" />
                </do_else>

                <do_if value="$nextConv == 'choose_npc_type'">
                  <add_player_choice_sub text="'%s (%s Cr)'.[{9992046,1002}, Setup.$npcPrices.$engineer.formatted.default]" section="choosen_npc_type" choiceparam="'$engineer'" />
                  <add_player_choice_sub text="'%s (%s Cr)'.[{9992046,1003}, Setup.$npcPrices.$pilot.formatted.default]" section="choosen_npc_type" choiceparam="'$pilot'" />
                  <add_player_choice_sub text="'%s (%s Cr)'.[{9992046,1004}, Setup.$npcPrices.$manager.formatted.default]" section="choosen_npc_type" choiceparam="'$manager'" />
                  <add_player_choice_sub text="'%s (%s Cr)'.[{9992046,1005}, Setup.$npcPrices.$marine.formatted.default]" section="choosen_npc_type" choiceparam="'$marine'" />
                  <add_player_choice_sub text="{9992046,1012}" section="expensive" />
                  <add_player_choice_sub text="{9992046,1013}" section="bye" position="bottom_right" />
                </do_if>

                <do_elseif value="$nextConv == 'choose_npc_gender'">
                  <!-- Allow player to select gender when hiring. See 0001.xml for correcponding entries (1002,1003...) -->
                  <add_player_choice_sub text="{9992046,1006}" section="choosen_npc_gender" choiceparam="'$male'" />
                  <add_player_choice_sub text="{9992046,1007}" section="choosen_npc_gender" choiceparam="'$female'" />
                  <add_player_choice_sub text="{9992046,1008}" section="choosen_npc_gender" choiceparam="'any'" />
                  <add_player_choice_sub text="{9992046,1013}" section="bye" position="bottom_right" />
                </do_elseif>

                <do_elseif value="$nextConv == 'choose_ship'">
                  <!-- Find docked ships on the station -->
                  <find_object_component name="$ships" object="$station" class="class.ship" owner="faction.player" docked="true" checkoperational="true" multiple="true" includeobjects="true" />
                  <do_all counter="$i" exact="$ships.count">
                    <set_value name="$ship" exact="$ships.{$i}" />
                    <add_player_choice_sub text="'%s (%s) [%s]'.[$ship.name, $ship.idcode, $ship.people.free]" section="choosen_ship" choiceparam="$ship" /> 
                    <!-- TODO - only first 5 ships, need to create additional menu pages -->
                    <do_if value="$i ge 5">
                      <break />
                    </do_if>
                  </do_all>
                  <remove_value name="$ships" />
                  <remove_value name="$ship" />
                  <add_player_choice_sub text="{9992046,1014}" section="start" position="bottom_right" />
                </do_elseif>

                <do_elseif value="$nextConv == 'choose_amount'">
                  <do_for_each name="$n" in="[1, 5, 10, 25]">
                    <add_player_choice_sub text="'%s (%s Cr)'.[$n, ($npcPrice * $n).formatted.default]" section="choosen_amount" choiceparam="$n" selectable="$npcMaxCount ge $n" />
                  </do_for_each>
                  <add_player_choice_sub text="'%s (%s Cr)'.[$npcMaxCount, ($npcPrice * $npcMaxCount).formatted.default]" section="choosen_amount" choiceparam="$npcMaxCount" />
                  <add_player_choice_sub text="{9992046,1014}" section="bye" position="bottom_right" />
                </do_elseif>

                <do_if value="$doRecruit?">
                  <remove_value name="$doRecruit" />
                  <debug_to_file directory="Setup.$debugDir" name="Setup.$debugFile" text="'%.3s, Recruit %s %s (%s) to %s (%s) for %s Cr.'.[player.age, $npcCount, $npcType, $npcGender, $selectedShip.name, $selectedShip.idcode, $npcCost.formatted.default]" />
                  <!-- Create and add NPCs -->
                  <set_value name="$role" exact="if $npcType == '$marine' then entityrole.marine else entityrole.service" />
                  <do_all exact="$npcCount">
                    <create_npc_template name="$crewTemplate" object="$selectedShip" macro="Setup.$npcMacros.{$npcType}.{$npcGender}.random" role="$role" force="false" />
                    <do_if value="$crewTemplate">
                      <!-- Setup crew skills -->
                      <do_for_each name="$v" in="Setup.$npcSkills.{$npcType}">
                        <set_skill object="$selectedShip" template="$crewTemplate" type="$v.{1}" min="$v.{2}" max="$v.{3}" />
                      </do_for_each>
                      <do_if value="$selectedShip.attention ge attention.visible">
                        <!-- The player is in visible attention to the ship, so create new NPC -->
                        <find_npc_waypoint name="$slot" object="$selectedShip" tags="tag.npctransport"/>
                        <do_if value="$slot">
                          <create_npc_from_template name="$crew" object="$selectedShip" template="$crewTemplate" slot="$slot" owner="faction.player" />
                          <do_if value="$crew">
                            <set_entity_traits entity="$crew" hidden="true" />
                          </do_if>
                          <remove_value name="$crew" />
                        </do_if>
                        <remove_value name="$slot" />
                      </do_if>
                    </do_if>
                    <do_else>
                      <set_value name="$npcCost" operation="subtract" exact="$npcPrice" />
                    </do_else>
                    <remove_value name="$crewTemplate" />
                  </do_all>
                  <remove_value name="$role" />
                  <!-- Deduct money if successful -->
                  <reward_player money="-$npcCost" />

                  <!-- Transaction completed -->
                  <add_npc_line speaker="$actor" line="Setup.$convLinesMore.random" />
                  <add_player_choice_sub text="{9992046,1016}" section="start" />
                  <add_player_choice_sub text="{9992046,1017}" section="bye" position="bottom_right" />
                </do_if>

                <remove_value name="$nextConv" />
              </actions>
            </cue>

            <library name="ClearTemporaries" purpose="include_actions">
              <actions>
                <remove_value name="$npcType" />
                <remove_value name="$npcPrice" />
                <remove_value name="$npcGender" />
                <remove_value name="$npcMaxCount" />
                <remove_value name="$npcCount" />
                <remove_value name="$npcCost" />
                <remove_value name="$selectedShip" />
              </actions>
            </library>

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

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

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

Re: Mod spawned NPC bug - loading a save causes conversation spam

Post by user1679 » Thu, 12. Aug 21, 00:35

arshiba wrote:
Tue, 10. Aug 21, 21:09
At first I wanted to make a simple example of how the cue structure could be redesigned to avoid leaks. But then, gradually optimizing other code parts, I refactored the whole script.
And made some improvements:
* The conversations "choose ship" and "choose amount" are swapped and the 5th option is replaced with the current maximum (for free space or available money) that can be recruited
* Marines are assigned as marines, not service crew
* New crew NPC are immediately created from templates (as in the appropriate logic in conversations.xml "NPCAssigned_Transfer")
^ An attempt to make a workaround for the critical issue stated in the readme.txt. Are there still troubles with the crew tab?

Maybe this is inappropriate, but I want to highlight some issues in the previous code. Just in case, many of them are described here (MD Guide).
* Cue and script names should starts with uppercase letter
* The conditions of "rse_new_game_started", "rse_start", "rse_save_loaded" are a complete mess and should be optimized out
* Patching logic of "rse_save_loaded", "rse_remove_rofficer" is broken (can't be from 400 to 400)
* reset_cue of instantiated cue is undefined behaviour
* Cue "rse_genNPCMacro" is better to reimplement as <library purpose="run_actions">
* The instances of "rse_place_officer" can't be wiped out except explicitly with cancel_cue
* Lots of temporary variables without remove_value (every byte matter in game save files!)
* There is strict dependency for split DLC (no traces of this content found) (maybe optional=true?)
* No need for "new game" restriction to use (install or uninstall) this mod
Not inappropriate at all. I don't know how to thank you, other than crediting you on the download page.

I honestly have been struggling with this for a while. I got permission to modify someon else's mod while having zero knowledge of X4 scripting. After reading the MD guide and getting tips from Kuertee, I was able to at least get it to do what I wanted as far as spawning the NPC on any station.

But I knew there was something wrong (and by that I mean many things), I had an idea that the subcues were still in waiting state but I didn't know how to fix that. I really appreciate your refactoring and explanation. I will be able to compare it to my original and see where I went wrong.



To address some of your points:



* Cue and script names should starts with uppercase letter

This seems like a coder's preference. I've had many debates over the years coding C++ wether to use camel case, snake casem etc. I prefer camel case myself but used snake because many examples I saw used that

* The conditions of "rse_new_game_started", "rse_start", "rse_save_loaded" are a complete mess and should be optimized out

Yes, that was a "todo" of mine after I figured out why the script wasn't terminating

* The instances of "rse_place_officer" can't be wiped out except explicitly with cancel_cue

Right, which is what I was struggling with. I tried cancel_cue but it ended up breaking the mod entirely, so obviously I used it incorrectly

* There is strict dependency for split DLC (no traces of this content found) (maybe optional=true?)

This was an oversight. Only Terran DLC has explicit use due to the character macro but I did provide users a way to "fix" that,

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

Re: Mod spawned NPC bug - loading a save causes conversation spam

Post by user1679 » Fri, 10. Sep 21, 04:52

I noticed a slight inconsistency with the random choice of character macro. If I hire 10 female crew at once, often 9 of them will have the same macro. Even if I hire 10 female one at a time, often more than 50% use the same macro. Most often it's my custom macro: character_recruitment_svc_arg_f_engineer2_macro (which creates a CAU female). Is there any other method of generating a random choice that would provide a little more randomness?

Code: Select all

$engineer = table[$male = [macro.character_recruitment_svc_arg_m_engineer_macro], $female = [macro.character_recruitment_svc_arg_f_engineer1_macro, macro.character_recruitment_svc_arg_f_engineer2_macro]],

<create_npc_template name="$crewTemplate" object="$selectedShip" macro="Setup.$npcMacros.{$npcType}.{$npcGender}.random" role="$role" force="false" />
Example: I bought a Manorina Mineral Miner with a crew capacity of 10. I went to the recruiter and hired 10 at once. I had 9 CAU females and 1 AFR. I fired them all and repeated. This time I got 7 CAU and 3 AFR (two of which also had the same facial features). I fired them all again and hired one at a time until I reached 10. This time I got 5 CAU, 3 identical AFR, 1 unique AFR and 1 ASN.


Thanks!

Post Reply

Return to “X4: Foundations - Scripts and Modding”