Game XML Tips & Examples


  • Admin

    So after doing some work on TWW XML and seeing some of the other recent map XMLs, I thought it would be helpful to map makers to provide some examples on how to make their XML easier to write and maintain. Feel free to ask questions or provide examples of your own.

    1. Multiple when lines and how uses works
    2. Reusing conditions
    3. Complex trigger with multiple types of actions and multiple of each action
    4. Complex UserAction which activates multiple triggers and number of attempts depend on conditions

  • Admin

    1. Automatic unit placement when a territory is conquered in TWW
    • Places an infantry in Algeria once its captured by the Allies (Algeria is set to be given to ExiledAllies when captured). The placement happens after the Allied non-combat move who captures it.
    • Shows how multiple when lines can be used in the same trigger
    • Shows how uses works when using when

    Old XML

        <attachment name="conditionAttachmentUnitsEAAlgeria" attachTo="ExiledAllies" javaClass="games.strategy.triplea.attachments.RulesAttachment" type="player">
          <option name="directOwnershipTerritories" value="Algeria" count="1"/>
          <option name="switch" value="true"/>
        </attachment>
        
        <attachment name="triggerAttachmentUnitsEAAlgeria1" attachTo="ExiledAllies" javaClass="games.strategy.triplea.attachments.TriggerAttachment" type="player">
          <option name="conditions" value="conditionAttachmentUnitsEAAlgeria"/>
          <option name="placement" value="Algeria:britishInfantry"/>
          <option name="playerAttachmentName" value="RulesAttachment" count="conditionAttachmentUnitsEAAlgeria"/>
          <option name="playerProperty" value="switch" count="false"/>
          <option name="uses" value="1"/>
          <option name="when" value="after:britainNonCombatMove"/>
        </attachment>
        <attachment name="triggerAttachmentUnitsEAAlgeria2" attachTo="ExiledAllies" javaClass="games.strategy.triplea.attachments.TriggerAttachment" type="player">
          <option name="conditions" value="conditionAttachmentUnitsEAAlgeria"/>
          <option name="placement" value="Algeria:britishInfantry"/>
          <option name="playerAttachmentName" value="RulesAttachment" count="conditionAttachmentUnitsEAAlgeria"/>
          <option name="playerProperty" value="switch" count="false"/>
          <option name="uses" value="1"/>
          <option name="when" value="after:chinaNonCombatMove"/>
        </attachment>
        <attachment name="triggerAttachmentUnitsEAAlgeria3" attachTo="ExiledAllies" javaClass="games.strategy.triplea.attachments.TriggerAttachment" type="player">
          <option name="conditions" value="conditionAttachmentUnitsEAAlgeria"/>
          <option name="placement" value="Algeria:britishInfantry"/>
          <option name="playerAttachmentName" value="RulesAttachment" count="conditionAttachmentUnitsEAAlgeria"/>
          <option name="playerProperty" value="switch" count="false"/>
          <option name="uses" value="1"/>
          <option name="when" value="after:russiaNonCombatMove"/>
        </attachment>
        <attachment name="triggerAttachmentUnitsEAAlgeria4" attachTo="ExiledAllies" javaClass="games.strategy.triplea.attachments.TriggerAttachment" type="player">
          <option name="conditions" value="conditionAttachmentUnitsEAAlgeria"/>
          <option name="placement" value="Algeria:britishInfantry"/>
          <option name="playerAttachmentName" value="RulesAttachment" count="conditionAttachmentUnitsEAAlgeria"/>
          <option name="playerProperty" value="switch" count="false"/>
          <option name="uses" value="1"/>
          <option name="when" value="after:usaNonCombatMove"/>
        </attachment>
    

    Simplified XML

        <attachment name="conditionAttachmentUnitsEAAlgeria" attachTo="ExiledAllies" javaClass="games.strategy.triplea.attachments.RulesAttachment" type="player">
          <option name="directOwnershipTerritories" value="Algeria" count="1"/>
        </attachment>
        
        <attachment name="triggerAttachmentUnitsEAAlgeria" attachTo="ExiledAllies" javaClass="games.strategy.triplea.attachments.TriggerAttachment" type="player">
          <option name="conditions" value="conditionAttachmentUnitsEAAlgeria"/>
          <option name="placement" value="Algeria:britishInfantry"/>
          <option name="uses" value="1"/>
          <option name="when" value="after:britainNonCombatMove"/>
          <option name="when" value="after:chinaNonCombatMove"/>
          <option name="when" value="after:russiaNonCombatMove"/>
          <option name="when" value="after:usaNonCombatMove"/>
        </attachment>
    

    So the original XML was using 4 separate triggers for each of the 4 Allies that could capture Algeria and used setting the switch on the condition for those 4 triggers so that only the first of the triggers that fired would disable the rest. This can be simplified to use 1 trigger that has 4 when lines (1 for each of the 4 Allies) and relying on uses to ensure this trigger only fires for the first when it hits.

    Now this also gives some insight into the 2 ways the uses can work. If there is no when set on a trigger then instead of using up a use with every fire, it instead uses up a use if the trigger is fired during this round. This is in order to let a trigger that contains multiple actions, fire all of them in a single use. Otherwise if a trigger has 1 or more when lines set then it uses up a use every time it fires. This means that its generally better to set when on your triggers so its more clear when they fire and you have more control over uses.


  • Admin

    1. TWW Protectorates
    • Protectorate territories don't give any income to the owner but instead contribute to an objective which give free materials to certain nations.
    • Shows how conditions can be reused instead of duplicated

    Old XML

        <attachment name="conditionAttachmentBritishDutch1EA" attachTo="ExiledAllies" javaClass="games.strategy.triplea.attachments.RulesAttachment" type="player">
          <option name="directPresenceTerritories" value="Sumatra" count="1"/>
          <option name="unitPresence" value="Protectorate" count="1"/>
        </attachment>    
        <attachment name="objectiveAttachmentBritishDutch1" attachTo="ExiledAllies" javaClass="games.strategy.triplea.attachments.RulesAttachment" type="player">
          <option name="conditions" value="conditionAttachmentBritishDutch1EA:conditionAttachmentYes"/>
          <option name="conditionType" value="AND"/>
          <option name="objectiveValue" value="-2"/>
        </attachment>
               
        <attachment name="conditionAttachmentBritSum" attachTo="ExiledAllies" javaClass="games.strategy.triplea.attachments.RulesAttachment" type="player">
          <option name="directPresenceTerritories" value="Sumatra" count="1"/>
          <option name="unitPresence" value="Protectorate" count="1"/>
        </attachment>   
        <attachment name="conditionAttachmentAusMat" attachTo="Australia" javaClass="games.strategy.triplea.attachments.RulesAttachment" type="player">
          <option name="conditions" value="conditionAttachmentBritSum:conditionAttachmentBritBor:conditionAttachmentBritJav:conditionAttachmentBritDEI:conditionAttachmentBritCel:conditionAttachmentBritGui"/>
          <option name="conditionType" value="1-6"/>
        </attachment>
    

    Simplified XML

        <attachment name="conditionAttachmentBritishDutch1EA" attachTo="ExiledAllies" javaClass="games.strategy.triplea.attachments.RulesAttachment" type="player">
          <option name="directPresenceTerritories" value="Sumatra" count="1"/>
          <option name="unitPresence" value="Protectorate" count="1"/>
        </attachment>
        <attachment name="objectiveAttachmentBritishDutch1" attachTo="ExiledAllies" javaClass="games.strategy.triplea.attachments.RulesAttachment" type="player">
          <option name="conditions" value="conditionAttachmentBritishDutch1EA"/>
          <option name="objectiveValue" value="-2"/>
        </attachment>
        <attachment name="conditionAttachmentAusMat" attachTo="Australia" javaClass="games.strategy.triplea.attachments.RulesAttachment" type="player">
          <option name="conditions" value="conditionAttachmentBritishDutch1EA:conditionAttachmentBritishDutch2EA:conditionAttachmentBritishDutch3EA:conditionAttachmentBritishDutch4EA:conditionAttachmentBritishDutch5EA:conditionAttachmentBritishDutch6EA"/>
          <option name="conditionType" value="1-6"/>
        </attachment>
    

    Instead of having 2 separate conditions for checking if Sumatra has a Protectorate unit, these can be combined into a single condition that is used to both nullify the income from the territory owner and check for free material conditions.


  • Admin

    1. TWW Germany Takes Over Vichy North Africa
    • Once the Allies capture Morrocco or Algeria, the Vichy Protectorate no longer generates a free material and Germany takes over the North African Vichy territories
    • Show a complex triggers with multiple types of actions and multiple of each of those actions (removeUnits, placement, changeOwnership)
        <attachment name="conditionAttachmentVichyMat" attachTo="VichyFrance" javaClass="games.strategy.triplea.attachments.RulesAttachment" type="player">
          <option name="conditions" value="conditionAttachmentMorroccoVichy:conditionAttachmentAlgeriaVichy"/>
          <option name="conditionType" value="2"/>
        </attachment>
        <attachment name="conditionAttachmentVichyProtectorateLost" attachTo="VichyFrance" javaClass="games.strategy.triplea.attachments.RulesAttachment" type="player">
          <option name="conditions" value="conditionAttachmentVichyMat"/>
          <option name="invert" value="true"/>
        </attachment>  
        
        <attachment name="triggerAttachmentVichyMedTurnsGerman" attachTo="VichyFrance" javaClass="games.strategy.triplea.attachments.TriggerAttachment" type="player">
          <option name="conditions" value="conditionAttachmentVichyProtectorateLost"/>
          <option name="uses" value="1"/>
          <option name="removeUnits" value="Morrocco:Protectorate"/>
          <option name="removeUnits" value="Algeria:Protectorate"/>
          <option name="placement" value="Vichy France:Occupation"/>
          <option name="changeOwnership" value="Morrocco:VichyFrance:Germany:false"/>
          <option name="changeOwnership" value="Algeria:VichyFrance:Germany:false"/>
          <option name="changeOwnership" value="Tunisia:VichyFrance:Germany:false"/>
          <option name="changeOwnership" value="Southwestern Algeria:VichyFrance:Germany:false"/>
          <option name="changeOwnership" value="Southern Algeria:VichyFrance:Germany:false"/>
          <option name="when" value="after:russiaBattle"/>
          <option name="when" value="after:chinaBattle"/>
          <option name="when" value="after:britainBattle"/>
          <option name="when" value="after:usaBattle"/>
        </attachment>
    

    The trigger only fires after Morrocco or Algeria is captured by the Allies and only fires once. It uses multiple when so that it can fire after any of the 4 Allies capture on of them. Its does the following actions:

    • removeUnits - Removes any remaining Protectorate units from Morrocco or Algeria. Since one of them was conquered, it will already have removed one of the Protectorate units but its fine to still use removeUnits even if the unit isn't there.
    • placement - Adds an Occupation unit to VichyFrance territory so that Germany now collect the income from it.
    • changeOwnership - Changes ownership of any of the Vichy controlled North African territories to Germany (if they were conquered by the Allies then won't turn German since it specifies VichyFrance as the current owner)

  • Admin

    1. TWW Prevent Scuttling of Toulon Fleet
    • Use UserActions to give Germany the option to attempt to prevent scuttling of Toulon Fleet
    • Shows how to use UserActions which activate multiple triggers and number of attempts depend on conditions
        <attachment name="conditionAttachmentVichyMat" attachTo="VichyFrance" javaClass="games.strategy.triplea.attachments.RulesAttachment" type="player">
          <option name="conditions" value="conditionAttachmentMorroccoVichy:conditionAttachmentAlgeriaVichy"/>
          <option name="conditionType" value="2"/>
        </attachment>    
        <attachment name="conditionAttachmentVichyProtectorateLost" attachTo="VichyFrance" javaClass="games.strategy.triplea.attachments.RulesAttachment" type="player">
          <option name="conditions" value="conditionAttachmentVichyMat"/>
          <option name="invert" value="true"/>
        </attachment> 
        <attachment name="conditionAttachmentSZ44VichyBattleship" attachTo="Germany" javaClass="games.strategy.triplea.attachments.RulesAttachment" type="player">
          <option name="directPresenceTerritories" value="44 Sea Zone" count="1"/>
          <option name="unitPresence" value="vichyBattleship:vichyBattleship-damaged" count="1"/>
        </attachment>
        
        <attachment name="triggerAttachmentSZ44RemoveVichyBattleship" attachTo="Germany" javaClass="games.strategy.triplea.attachments.TriggerAttachment" type="player">
          <option name="removeUnits" value="44 Sea Zone:vichyBattleship"/>
          <option name="removeUnits" value="44 Sea Zone:vichyBattleship-damaged"/>
        </attachment>
        <attachment name="triggerAttachmentSZ44PlaceGermanBattleship" attachTo="Germany" javaClass="games.strategy.triplea.attachments.TriggerAttachment" type="player">
          <option name="chance" value="2:12"/>
          <option name="placement" value="44 Sea Zone:germanBattleship"/>
        </attachment>
        
        <attachment name="userActionAttachmentGermanySaveVichyBattleship" attachTo="Germany" javaClass="games.strategy.triplea.attachments.UserActionAttachment" type="player">
          <option name="conditions" value="conditionAttachmentVichyProtectorateLost:conditionAttachmentSZ44VichyBattleship"/>
          <option name="activateTrigger" value="triggerAttachmentSZ44RemoveVichyBattleship:1:false:false:false:false"/>
          <option name="activateTrigger" value="triggerAttachmentSZ44PlaceGermanBattleship:1:false:false:false:true"/>
          <option name="text" value="GERMANS_SAVE_BATTLESHIP"/>     
          <option name="costResources" value="1:PUs"/>
          <option name="attemptsPerTurn" value="99"/>
        </attachment>
    

    This UserAction which deals with the Toulon Fleet battleship uses conditions on the Vichy protectorate being lost and the battleship still existing in SZ44 (damaged or undamaged). The user is presented the user action only when those are true during Germany's UserAction phase and it cost them 1 PU to have a 2/12 chance of saving the battleship. If selected, it fires 2 triggers: 1 to remove the Vichy battleship which always fires and 1 to add a German battleship which uses chance to have a 2/12 chance of success. The UserAction has 99 attemptsPerTurn (essentially unlimited) so is really limited by the condition on there being a Vichy battleship in SZ44 so the option will appear to the user for as many battleships as are in the Toulon Fleet. Similar UserActions are used for each of the other type of ship in the Toulon Fleet.


  • Moderators

    This post is deleted!

  • Moderators

    Here's an example of a "custom gameProperty":

    gameProperty values: can be set equal to the exact string of any boolean game property option, including custom made up ones.

    ( Start of new stuff )
    Here is an example of a custom one:
    <attachment name="HitlerYouth" attachTo="Germans" javaClass="games.strategy.triplea.attachments.RulesAttachment" type="player">
    <option name="gameProperty" value="Hitler Youth Call Up"/>
    </attachment>
    <attachment name="conditionAttachmentGermansRounds3-+" attachTo="Germans" javaClass="games.strategy.triplea.attachments.RulesAttachment" type="player">
    <option name="rounds" value="3-+"/>
    </attachment>
    <attachment name="triggerAttachmentHitlerYouth" attachTo="Germans" javaClass="games.strategy.triplea.attachments.TriggerAttachment" type="player">
    <option name="conditions" value="HitlerYouth:conditionAttachmentGermansRounds3-+"/>
    <option name="placement" value="Germany:infantry" count="2"/>
    <option name="when" value="after:germanPlace"/>
    </attachment>

      This will place 2 infantry in Germany at the end of Germany's "germanPlace" phase beginning round 3 and will continue to place each round for the rest of the game.
    

    The "conditions" are placed above the trigger instead of in "Conditions" for simplicity. Not sure if I should point that out or not. I don't want to spam it out. Also, the new conditions and trigger are listed twice in the xml, but it didn't throw a error and works correctly, so I guess that should be ok.

    Here's the xml:

    pact_of_steel_2.xml

    Here's a saved game so you don't have to click through:

    Hitler Youth.tsvg

    Should I try and do a branch on Git so it's easier to see the changes ? Not sure where to do it at. I guess clone it and stick it where it shows up ? Idk, I always struggle with Git. Or is this good enough ?

    Also fixed a minor typo. Hmm...just thought of something, if the wording is deemed offensive, it could be changed to "Conscription". Idk. I'm not easily offended, although some are. Selectively so imo, but whatever, that's neither here nor there.

    At any rate
    Peace Out
    Rock On


  • Moderators

    This post is deleted!

  • Moderators

    This post is deleted!

  • Moderators

    This post is deleted!

  • Moderators Admin

    This post is deleted!

  • Admin

    @beelee Hey you have a lot here. Can you summarize what functionality you are trying to implement? I'm having a little trouble following it.


  • Moderators

    @prastle said in Game XML Tips & Examples:

    @beelee Was that the only one?

    The one above the deleted one too. Thanks.

    @redrum yea so two things. The one is a update to POS2 showing how to make a custom gameProperty.

    The other, are two xml questions. How to have a trigger only be checked once. So it won't continue to try and fire every turn until it succeeds. I thought I could do it with "turns" but it didn't work.

    The second is, I want a trigger to activate another trigger that has a notification. I only want that to fire twice ( two turns ), unless the condition is met which would prevent it from firing at all.


  • Moderators

    I have this trigger:

    <attachment name="triggerAttachment_Battleship_Ordered_to_Vichy_Port" attachTo="French" javaClass="games.strategy.triplea.attachments.TriggerAttachment" type="player">
    <option name="conditions" value="conditionAttachment_Axis_Conquer_All_France:Vichy_active:conditionAttachmentFrenchBB"/>
    <option name="chance" value="3:6"/>
    <option name="when" value="before:frenchCombatMove"/>
    <option name="uses" value="1"/>

    which if successful tells the BB to head to port. When it is unsuccessful it will try again the next turn. I don't want it to do that. Just a one time shot at success or failure.

    The second part is if it is successful, ordered to port, I want a trigger/notification to fire that reminds it that it has been ordered to port. This would happen at the start of the BBs next two turns. If the BB arrives in port it cancels the notification. If the BB hasn't arrived after two turns the notification cancels as well.

    I used this condition:

    <attachment name="conditionAttachmentFrenchBBAtVichyPort" attachTo="French" javaClass="games.strategy.triplea.attachments.RulesAttachment" type="player">
    <option name="directPresenceTerritories" value="93 Sea Zone" count="1"/>
    <option name="unitPresence" value="battleship" count="1"/>
    <option name="invert" value="true"/>
    </attachment>

    and this trigger to try and achieve it.

    <attachment name="triggerAttachment_Battleship_Must_Sail_to_Vichy_Port_93_Sea_Zone" attachTo="French" javaClass="games.strategy.triplea.attachments.TriggerAttachment" type="player">
    <option name="conditions" value="conditionAttachmentFrenchBBAtVichyPort"/>
    <option name="when" value="before:frenchCombatMove"/>
    <option name="uses" value="2"/>
    <option name="notification" value="Battleship_Must_Sail_to_Vichy_Port_93_Sea_Zone"/>
    </attachment>

    The first trigger would have "activateTrigger" for this one.


  • Moderators

    I've successfully confused myself once again. "turns" is now working, I think. I'll do so more testing and if continues to work I'll post the "how to have a trigger only fire once" again.

    Idk why I'm struggling so much. I was always good in math. Built multiple million dollar homes for decades, but i can't figure out basic computer stuff. I guess i just need to accept the fact that I'm not that smart 🙂

    Yea we can delete all the non pertinent stuff I posted so as not to spam this out


  • Admin

    @beelee So for the first one:

    <attachment name="triggerAttachment_Battleship_Ordered_to_Vichy_Port" attachTo="French" javaClass="games.strategy.triplea.attachments.TriggerAttachment" type="player">
      <option name="conditions" value="conditionAttachment_Axis_Conquer_All_France:Vichy_active:conditionAttachmentFrenchBB"/>
      <option name="chance" value="3:6"/>
      <option name="when" value="before:frenchCombatMove"/>
      <option name="uses" value="1"/>
    </attachment>
    

    I believe uses only is used up if it actually fires (you hit the chance) so you can't use that for what you are trying to do. You instead need to have another trigger that does fire after this one (say during after:frenchCombatMove) which sets a condition to false which is used in your trigger. As you also mention, if it only happens on a certain turn(s) then you could use the turns parameter instead.

    The second one looks correct except that if the BB would arrive before the 2 uses, it then fires once the BB leaves. So you would need to set a condition to be false once the BB returns so the notification doesn't show when it leaves.


  • Moderators Admin

    This post is deleted!

  • Moderators

    This post is deleted!

  • Moderators Admin

    This post is deleted!

  • Moderators

    This post is deleted!

Log in to reply