In the USB thread, I made a feature suggestion for SMM that would allow USB to be able to not have to be a standalone mod. Basically, I proposed an additional attribute invert="true" which could be added to findName (and findLike/findComposite, I suppose) to say "if the find failed, then do the following with the existing context node as the context node for the expression.
Well, just for grins, I took a whack at trying out my idea in the SMM code. I added the following code to XMLPatcher.java:handleModFind (line 125):
Code: Select all
List<Element> matchedNodes = new ArrayList<Element>( contextNode.getContent( searchFilter ) );
boolean invertSearch = getAttributeBooleanValue( node, "invert", false );
if ( invertSearch ) {
if ( matchedNodes.size() == 0 ) {
matchedNodes.add( contextNode );
}
else {
matchedNodes.clear();
}
}
if ( searchReverse ) Collections.reverse( matchedNodes );
The first and last lines are the original code just to give some context.
It uses my syntax proposed in the other thread, which I'm not in love with but might be fine. Basically, invert="true" says that if it does NOT find a match, then it should use the contextNode as the result. Here's an example:
Code: Select all
<mod:findName type="event" name="APPEND_TEST">
<mod-append:event name="APPEND_TEST">
<text>If #1 comes first, it will win!</text>
<choice>
<text>Continue...</text>
</choice>
</mod-append:event>
<mod-append:event name="APPEND_TEST_FRIEND">
<text>And here is #1's friend.</text>
</mod-append>
</mod:findName>
<mod:findName type="event" name="APPEND_TEST" invert="true">
<mod-append:event name="APPEND_TEST">
<text>If #2 comes first, it will be the winner.</text>
<choice>
<text>Continue...</text>
</choice>
</mod-append:event>
<mod-append:event name="APPEND_TEST_FRIEND">
<text>And here is #2's friend.</text>
</mod-append>
</mod:findName>
In this example, only the #1 APPEND_TEST will wind up getting added as a top level event. It would also add #1's APPEND_TEST_FRIEND. If you swapped the two arround, you'd get #2 and #2's friend. I tested this out with my code and it works like a charm.
This change would allow USB to turn into the following boilerplate code that you insert into your own events.xml.append (in addition to the existing USB sector_data.xml.append boilerplate):
Code: Select all
<!-- USB Boilerplate starts here -->
<mod:findName invert="true" type="event" name="START_GAME_BEACON">
<mod-append:event name="START_GAME_BEACON">
<choice>
<text>Continue...</text>
<event load="START_GAME_CHOICES" />
</choice>
</mod-append:event>
<!-- Append your start game <choices> or optional actions to this event -->
<mod-append:event name="START_GAME_CHOICES">
<text>You are about to set out on your journey.</text>
</mod-append:event>
</mod:findName>
<!-- My extension for my mod goes here -->
<mod:findName type="event" name="START_GAME_CHOICES">
<mod-append:choice>
<text>Go about your business</text>
<event>
<text>Suddenly, someone appears on your ship and demands to join your crew!</text>
<crewMember amount="1" />
</event>
</mod-append:choice>
</mod:findName>
What do you think? I think it's cool not just for USB but for having other mods that can add stuff while still avoiding clobbering existing. And I think the change I proposed wouldn't break any old USB installations (as long as they had USB first like they were supposed to anyway).