Tutorial - Conditional Arguments

From FreeSpace Wiki
Revision as of 16:52, 1 March 2014 by Axem (talk | contribs) (This is a tutorial, it belongs in the tutorial category!)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

So you're here to have an argument? That's just down the hall. Room 12A.

And you're here to learn about conditional arguments? Well just sit right down!

ARGUMENTS!

God's gift to FREDders everywhere.

So just what is an conditional argument? Basically it is a type of sexp that allows the game to choose from a list of pre-defined arguments and use one, a few, or all of them like a normal sexp. Still confused? Well let's fix that.

We're going to make a quick scenario that will let us showcase every type of conditional argument.

  • FYI: I'm just going to call them arguments from this point. It's just easier for me.

Base Scenario:

We have 5 ships! Alpha Wing, comprised of 4 Perseus-class fighters and an Elysium transport, named Omega 1. No hostiles or anything. This is just our sandbox right now.

Axm argtut1.jpg

So we're going to set up a sexp system that will make each of these fighters warp out if they get below 30% health. Normally this would require 4 very similar sexps. But we're going to do it in ONE. First though, let's set up some events to make all of our ships go to 25% health.

Axm argtut2.png

Simple huh?

  • Key-pressed is in the training category.

Ok, let's make this work.

any-of (and the basics of arguments)

Any-of is the simplest argument conditional and probably the most common one you will use. Like the name suggests, the sexp will be evaluated once ANY of the arguments can pass the conditions we set.

So first, let's change this when to a when-argument. Right click on the "when", go to "Replace Operator", then "Conditionals", and finally "when-argument". You can see there's some other operators such as "everytime-argument" and a bunch of grayed out operators. We will get to those later. So now you should have something like the below.

Axm argtut3.png Axm argtut3a.png

Let's change the event name to "Retreat when hurt". Now click on "<any data>" and edit it to be Alpha 2. Then right click on "any-of" and go to "add data" and then "string". Make this new entry, Alpha 3. Repeat this process to enter Alpha 4 and Omega 1. It looks like the below, right? Right?

Axm argtut4.png

Good! Now lets make our trigger condition. We want it to trigger when hull is less than 30%. So that's just < hits-left 30! Wait, what do I put as the ship? Is it this <argument> thingy that appeared out of nowhere? Why yes! You're smart, buddy.

Axm argtut5.png

Let's extend this train of thought to our action. For warping out.

Axm argtut6.png

To give this a bit of flair. Let's make a message that plays when someone needs to warp out. No need for a head ani or anything right now. We're keeping it simple, smart guy. (On a side note, I was denied the trademark for KISSG, and I can't figure out why).

Axm argtut7.png

Lastly, let us ensure this sexp will repeat a suitable amount of times. 4 possible arguments, so lets set trigger count to 4.

Axm argtut8.png

Time to RUN THE MISSION.

Lets press the 1 key to hurt Alpha 2 enough to run like the baby he is.

Axm argtut9.jpg

Hey it works!

Axm argtut10.jpg

Wait, that message replayed a few times... I'm sure its a simple bug we can fix later. Let's make Alpha 3 cry more.

Axm argtut11.jpg

Hey! What's going on here! He didn't run, but his health is below the threshold we set.

Does this have to do with those multiple messages? Did we forget one last step? By asking these oddly specific questions, am I implying that this is indeed the case?

YES!

invalidate-argument

When an argument can pass the condition we set, it doesn't vanish. It stays there unless we remove it. Now, the sexp looks for a ship in our argument list with less than 30% hull. If it finds one, it gives the ship (let's say Alpha 2) an order to warp out and to send a message. But the next time the sexp checks everything, Alpha 2 still has less than 30% hull. So it runs through the actions again. And again. And again.

Luckily we have a sexp that can remove an argument from the list. And that sexp is... invalidate-argument! Wait, how did you know that already?

So let's just tack this on at the end of our sexp. 99.999% of the time, the sexp will be invalidate-argument <argument>. So that's nice.

Axm argtut12.png

Let's run this mission again.

Pressing 1!

Axm argtut13.jpg

Hooray! The message was sent once. Pressing 2!

Axm argtut14.jpg

Yayifications! Pressing 3 and 4!

Axm argtut15.jpg

Look at that. Cool, isn't it? Let's go on to the other types and... oh- yes you in the back. You have a question?

A very common misconception

Axem, I have a rather complex mission and I want to use this sexp. Could I take a shortcut and just replace Alpha 2, Alpha 3, Alpha 4 with just Alpha? Or maybe just go any-of GTF Perseus?

Short answer, no. Long answer, noooooooooooooooooo.

When you are using arguments, be aware of type mismatching. The type of arguments in your list should be able to be used in the sexps you want to use them in.

Example:

Axm argtut16.png

Oh, this will check any of the ships that are a GTF Perseus, right? No. Because if we substitute <argument> with GTF Perseus we get a sexp that checks to see if a ship NAMED GTF Perseus is under 30% hull. There's no one like that, so the sexp will never trigger.

Arguments are very powerful because they will accept ANY type of data. FRED is blind to what you put in the argument list, so its up to YOU to ensure that they are correct and valid.

Anyway, on to every-of.

every-of

Similar to any-of, except that using this will only trigger when EVERY item on the list can pass the condition. For our sexp, that means our wingmen will only run away when everyone is below 30% hull. Give it a quick try. Just replace the any-of with every-of, save and run.

Axm argtut17.png

I'll wait.

Neat, huh? You'll notice that everyone sent their message at the same time, so everyone's actions happen at the same time. This is the case with most conditional arguments. If there's multiple arguments that can be passed through, the game will use them all.

random-of/random-multiple-of

  • FYI: The difference between random-of and random-multiple-of is the same as the random number system. Where random will generate the same random number throughout repeats, while random-multiple will generate different results for every repeat.

Random-of isn't a good choice for this situation, but we'll use it anyway for the purposes of showing you the sexp. The conditionals will choose a random item on the list and check that argument against the condition. The issue with this is that the random argument chosen is only chosen on the merit that it is on the list, not that it can pass the condition, but the sexp will try to trigger once if any of the arguments can complete the condition. Sounds complicated? Let's break it down.

Change the argument conditional to random-of. Save, and run the mission. Run through it a few times.

Axm argtut18.png

If you were proactive enough to, you would discover that the results are pretty inconsistent. Sometimes the key you press will cause the ship you want to retreat, sometimes it does nothing. But why?

Let's go through the game's thought process.

"Alpha 2 has 25% hull. Hey, there's a sexp that related to him being under 30% hull. Oh but, this sexp is asking for a random item on the list. Let's roll the dice! I choose... Alpha 4. Does Alpha 4 have under 30% hull? No. Okay, I'll skip this then."

Kind of weird, isn't it? Well the real action you are undertaking here is "Randomly pick someone to see if they should leave."

If you use just random-of, you will guarantee yourself a single random ship retreating.

number-of

Number-of will only begin once a specified number of list items can pass the condition. A number-of with a 1 will act as an any-of. A number-of with the number of items you have in the list (in our case 4) will act as an every-of. So the real stuff it can do is in between. Change the argument conditional to number-of. But be warned, you will have to reenter the argument list. That's because the first argument now is a number, not a string. Set our number argument to 2.

Axm argtut19.png

Let's run the mission!

Axm argtut20.jpg

As you probably saw, it took hurting Alpha 2 and Alpha 3 to make them warp out. And then it took hurting both Alpha 4 and Omega 1 to warp them out. What happens if we bump it the number argument to 3?

Axm argtut21.png

Well, I hurt Alpha 2, Alpha 3 and Alpha 4 and they all warped out.

Axm argtut22.jpg

But now I hurt Omega 1 and he just stays there.

Axm argtut23.jpg

Sort of predictable, I guess. We're looking for 3 items on the list to be true, but there's only 1 item left!

Hmm... But what if we have everyone hurt at the SAME time? Who gets chosen then?

...Let's find out...

Let's make everyone's health start off at 25%.

Axm argtut24.jpg

Now let's run the mission...

Axm argtut25.jpg

Wait, so before we had 3 ships leave, but now we had everyone leave! Why? The sexp actually looks for at least a number of arguments that can pass the condition. But that doesn't explain why Omega 1 didn't leave when we were hurting them one a a time. Actually, it does. When we invalidate an argument, we remove it from the list. So hurting them one by one will make the list get cut short, excluding the last ship. But hurting them all at once (in the same frame!) will make the game include the whole list.

Still confused? Here, let me explain with a bit of game thought process.

Hurting one-by-one: "I need to wait until I have at least 3 of these ships go below 30% hull before I tell them to warp out. Oh hey, Alpha 2, Alpha 3 and Alpha 4 all have hulls below 30%. I better tell them to leave. Also I will remove them from the list so they won't be evaluated again. Now I'm waiting to get at least another 3 ships to go below 30% hull... but there's only 1 ship left on the list. Oh well, the FREDder knows best!"

Hurting all at once: "I need to wait until I have at least 3 of these ships go below 30% hull before I tell them to warp out. Oh hey, Alpha 2, Alpha 3, Alpha 4 and Omega 1 all have hulls below 30%. I better tell them to leave. Also I will remove them from the list so they won't be evaluated again. Now I'm waiting to get at least another 3 ships to go below 30% hull... oh hey, the list is empty now. Whatever."

Well, that was fun. Lets give everyone 100% health again.

in-sequence

In-sequence is very interesting. All of these conditionals before either began as soon as someone could fufill the conditions, or randomly chose one. But in-sequence is very rigid, it will only evaluate the top item. So let us set up the argument list for in-sequence... (yes we need to redo it again)

Axm argtut26.png

Now let's go in game.

I'm gonna make Alpha 3 get hurt first... Oh. Nothing happens. Maybe Alpha 4? No?! Okay. Let's hurt Alpha 2 now.

Axm argtut27.jpg

He leaves, and then Alpha 3 leaves shortly after. Then Alpha 4.

Axm argtut28.jpg

So when Alpha 3 got hurt, the game didn't care, because Alpha 2 was in the top position. But once Alpha 2 got hurt, the game gave him the order, then invalidated Alpha 2 from the list. This now made Alpha 3 the top item on the list. And since Alpha 3 was hurt, the game saw it needed to make him leave too and take him off the list. Now Alpha 4 is at the top! For one second anyway. Because I'm sure you can guess what happens next.

for-counter

This is kind of advanced and isn't applicable to this situation. If you are familiar with programming, for-counter is like a for-loop. Read the help description, that's the best you're going to get from this tutorial!


Advanced Conditional Sexps

These are for advanced FREDders only. Don't worry about these if you don't understand them.

invalidate-all-arguments

If you want to remove the argument list, perhaps because you want it to stop midway through, you can use this sexp. It's probably wise to use this in an branching when conditional. If, for whatever reason, you don't want anyone to run away after Omega 1 was hurt, you could do this...

Axm argtut29.png

validate-argument/validate-all-arguments

These sexps are the only way to add arguments to an argument list. Since arguments are local to their sexp tree level, this might be a little tricky to use. This probably best used with another when conditional. VALIDATE-ALL-ARGUMENTS will restore all arguments that were originally in the list. An example on this will follow shortly.


num-valid-arguments

A valid item is an item that is on the list and ready to be evaluated by a possible trigger condition check. So num-valid-arguments basically returns the size of the argument list. With this you can tell how large the list is. If you can tell the size of the list, you can see if it's empty or not. So you can do something like this...

Axm argtut31.png

The result!

Axm argtut32.jpg

This will detect if there's no more arguments left on the list. If there's none left, it will restore all the default arguments, making this sexp, good as new! Using this with in-sequence, like I just did, will let you start from the beginning again once you finish.


do-for-valid-arguments

  • WARNING This Valid is not the Valid from the previous sexps. This should probably be named...

do-for-valid-arguments-that-can-pass-the-trigger-condition

But that's too long for FRED.

Anyway, this is a special conditional. Basically for each valid argument that can //pass// the trigger condition, the sexp action will repeat what you put inside.

Let's say we want to track the number of hurt ships in the area. I've taken out the warp out order, so everyone will stick around. Then I crated a new variable, numHurtShips. Obviously we just set this to increment by one, right?

Well, technically yes... But no. What happens if the game has two arguments it can pass through on the same frame? We can easily see this with number-of 2.

Axm argtut33.png

Lets try this in-game.

Axm argtut35.jpg

Obviously that's not right. There's 2 hurt ships! So let's add this do-for-valid-arguments on top of the modify-variable sexp.

Axm argtut36.png

Ingame time.

Axm argtut37.jpg

2 hurt ships!

Axm argtut38.jpg

4 hurt ships!

It works!

UNDER THE HOOD

(For FREDders with extremely high IQs)

Here's an extremely simplified explanation on how the conditional argument system works.

We have 2 main lists. The VALID list, the list that you enter into FRED. And the ACTIVE list, the list that the game is using to replace <argument> with real data types. (These names invented by Axem, coders won't know what you're talking about).

If the game sees that items on the VALID list can pass the condition trigger, it will copy them to the ACTIVE list. The game will then replace every instance of <argument> with the items in the ACTIVE list. If the ACTIVE list has more than one item, the sexps with <argument> in them will be repeated for each item in the ACTIVE list. If you want ALL sexps (and not just the ones with <argument> to be repeated for each item on the ACTIVE list, make them a child of a do-for-valid-argument sexp.

*By design, the random conditionals and in-sequence can only pass one argument at a time. The rest can pass as many arguments as you like

If the game encounters an invalidate-argument, it will remove the entry from the VALID list, but the ACTIVE list will remain intact (Ditto for the other types of (in)validation sexps). So in theory, you can invalidate the current argument and go and use <argument> after and still get the same result. In general though, it makes it easier to read when invalidate-argument is at the end.