[Dev Team] 2.1.0 Documentation: if/else_if/else

  • We have updated our Community Code of Conduct. Please read through the new rules for the forum that are an integral part of Paradox Interactive’s User Agreement.

LordMune

Content Design Lead
26 Badges
Mar 15, 2015
142
941
  • Europa Universalis IV
  • IPO Investor
  • Stellaris: Galaxy Edition
  • Crusader Kings II
Hello everyone!

We completely neglected to properly document a back-end feature in 2.1 that's been part of our internal workflow for months now. In Swedish there's a term for this kind of oversight -- being hemmablind -- and it's been causing some consternation. We dropped the ball, and it's time to pick it back up.

Changelog
  • Added else_if for instances where an else only contains another if
  • if/else_if/else syntax is now sequential rather than nested

else now behaves more or less like it does in every other programming or scripting language ever, and comes after an if rather than being nested inside it.

If you've ever written if statements of middling-and-up complexity for Stellaris, you've likely encountered nonsensical monstrosities like this one:

old_elseif.png


Which in the new syntax would be a much sleeker, gentler monstrosity:
(Colored lines not included, they're just to show if/else relationships!)

new_elseif.png


FAQ

My mod still seems to work, am I in the clear?

Yes and no. 2.1.0 retains some legacy functionality so simple if/else statements in the old syntax still work, but more complex ones might start producing unintended results. We will phase out support for the old syntax over time, so update your mods now.

Can we keep the old syntax?

No. On the code side there are maintenance and stability issues with supporting legacy syntax, and on the script side having one optimal and one sub-optimal system running in parallel is likely to cause errors and confuse. The old syntax will be phased out over the next update(s) to reduce ambiguity, save for an edge case detailed below.

What about elses inside ifs inside switches?

Funny you should ask that very specific question! Due to reasons our programmers won't fully explain but tell me are 100% legit, you will still have to nest elses inside ifs if the if is inside the effect of a switch, e.g.
Code:
switch = {
    trigger = Q
    a = {}
    b = {}
    c = {
        if = {
            limit = { trigger x }
            effect y
            else = { effect z }
        }
    }
}

But I have hundreds of if/else statements in my mod :(

Yes, so did vanilla Stellaris and I feel your pain. Updating your mod is a one-time investment, and it will greatly improve the readability and maintainability of your script in the long run!
 
So that's how if as an effect works now / will work in the future.
How about if as a trigger? Any change?
For example, how to interpret this vanilla game_rule (I assume if there is used as a trigger)
Code:
#Root = country, us
#This = country, them
#This rule is a condition for determining if a country is hostile towards another. not to be confused with can_take_hostile_action
can_be_hostile_towards = {
 if = {
  limit = { is_primitive = yes }
  ROOT = {
   NOT = { has_policy_flag = interference_passive }
  }
 
  else = {
   if = {
    limit = { ROOT = { is_primitive = yes } }
    NOT = { has_policy_flag = interference_passive }
   }
  }
  else = {
   if = {
    limit = { is_country_type = ratlings }
    always = yes
   }
  }
 }
}
 
can i ask that you guys clarify when an if can be used in triggers? It doesn't appear you can use this everywhere. Perhaps it would be best you find an alternative syntax for this - or offer a different way to work with if that checks triggers.
 
Oooooh! Thank you so much for this change! Debugging typos, missing/extra brackets and structuring within nests was the biggest pain in the world. I'll have to go over my events and adapt them but that's a minor inconvenience that's far outweighed by the long-term preservation of my sanity <3
 
For anyone wanting help finding effects they need to update, I've added a warning to CWTools that'll point out any old-style nested if/else.

Yes, so did vanilla Stellaris and I feel your pain. Updating your mod is a one-time investment, and it will greatly improve the readability and maintainability of your script in the long run!

You've got a fair few to go :)
 
What about elses inside ifs inside switches?

Funny you should ask that very specific question! Due to reasons our programmers won't fully explain but tell me are 100% legit, you will still have to nest elses inside ifs if the if is inside the effect of a switch, e.g.
Code:
switch = {
    trigger = Q
    a = {}
    b = {}
    c = {
        if = {
            limit = { trigger x }
            effect y
            else = { effect z }
        }
    }
}

I'd guess that switches get transformed into if, else_if, else chains leading to a dangling else issue, which is a common and old issue. Do you run into similar issues nesting if statements inside else statements?
 
On principle happy to have the system improved. However it will be an internal mess to re-make all the binary search systems I have implemented by hand using if/else statements...

Edit: Would it be possible to create a script that went through .txt files and auto-changed it? I do not think it would be to hard to do, and I would imagine that there are a significant amount of moders who would benefit greatly from this (not directing this request at the devs directly, mostly putting it up here).
 
Last edited:
On principle happy to have the system improved. However it will be an internal mess to re-make all the binary search systems I have implemented by hand using if/else statements...

Edit: Would it be possible to create a script that went through .txt files and auto-changed it? I do not think it would be to hard to do, and I would imagine that there are a significant amount of moders who would benefit greatly from this (not directing this request at the devs directly, mostly putting it up here).

Yea, I see where your pain comes from... since there are few actual language tools available, the only way to search for specific values (especially on range/economy/etc..) is manual binary search...

I guess since Vanilla doesn't really use any "complex" structures like that (most of it would be moved to hard-code, or directly created as an effect / condition / etc.. if a content dev on the team needs it), it was *relatively* painless to go through and update.

Feel your pain man.
 
That change reminds me of the addition of Pattern matching to switch blocks in C# 7.0:
https://visualstudiomagazine.com/articles/2017/02/01/pattern-matching.aspx

Originally switch case was "match a specific type against a constant". But with C# 7.0 pattern matching, the target could be any complex check.
This kind of allows the same thing.

Wait wait wait.. so for If <trigger> we still need to nest, but it's going to be changed "some day in the future" so we are going to have to recode it in a few months anyways??

Uh??

On principle happy to have the system improved. However it will be an internal mess to re-make all the binary search systems I have implemented by hand using if/else statements...
You could use scripted triggers to at least gather them in one spot. That way repalcing them will be less of an issue. You could easily spot any oversights.
 
You could use scripted triggers to at least gather them in one spot. That way repalcing them will be less of an issue. You could easily spot any oversights.
Unsure what you mean, could you explain further?
 
Unsure what you mean, could you explain further?
Stellaris\common\scripted_triggers\00_scripted_triggers.txt
Contains a number of checks in a central location.

For example there were two places where you wanted to know if the AIa rights policy was availible:
The Faction System (to enable/disable Spiritualist and Materialist issues)
The Policy System

It used to be that those were seperate piece of code. And due to humans being faulty, they were of course different. In part drastically so (as in they did not behave remotely the same).

That no longer applies. There is now one scripted trigger:
Code:
can_set_ai_policy = {
    is_mechanical_empire = no
    OR = {
        has_technology = tech_synthetic_workers
        has_technology = tech_sapient_ai
        any_relation = {
            has_communications = prev
            OR = {
                has_technology = tech_synthetic_workers
                has_technology = tech_sapient_ai
                has_authority = auth_machine_intelligence
            }
            OR = {
                is_country_type = default
                has_ai_personality_behaviour = robot_exploiter
                has_ai_personality_behaviour = robot_liberator
            }
        }
    }
}
Both the Policy System and the Faction issues (all 3 of them) now use that scripted trigger. You have one place to change the code and it will affect all uses of the trigger equally. There is no more likelyhood to forget to change one piece of checks.
 
Ok, however I am a bit unsure how you meant to play this to if/else logic, especially how to use it to make binary searches better (would be very interested to know though, if you had any ideas).
What is there to be unsure about? ScriptedTriggers fill the same niche that a function like "bool isNullOrWhiteSpace(string input)" does.

I never claimed it would be no issues changing to this new style. I said:
You could use scripted triggers to at least gather them in one spot. That way repalcing them will be less of an issue. You could easily spot any oversights.
 
Hi Paradox! Wanted to ask about scrollbars. What the hell happened with them? Tryed to fix species_mod_window for more traits but it crashes when I add scrollbars. Verticalscrollbar doesn't work now. Is there a chance to make a normal scrollbar?