Hard Light Productions Forums
Modding, Mission Design, and Coding => The FRED Workshop => Topic started by: CommanderDJ on November 07, 2010, 07:59:22 pm
-
Dear HLP,
I've run into a bit of trouble with SEXPing here. Here's the situation: the player and a wingman are raiding a bunch of cargo containers guarded by sentry guns. There are nine cargo containers there, and the player must scan them. Containers 1 and 3 are crucial to the mission and must not be destroyed, whilst the others are expendable. I'm trying to FRED two events: one which checks if the player has scanned all the cargo (ie none of it is destroyed, which yields a bonus objective) and gives the directive "scan all cargo" . That's easy enough, and works fine. The other event only triggers if the first one is false, that is, if some of the cargo has been destroyed. I want this event to give the directive "scan remaining cargo", and to return true using a huge bunch of ands and ors when a) containers 2 and 4-9 are either destroyed or scanned and b) when containers 1 and 3 are scanned. Now the problem is not the event itself as I think I've FREDded it correctly. The problem is the little numbers next to directives. For the first event the directive initially reads "Scan all cargo [9]" and the number decreases as cargo is scanned. Now if any of the cargo is destroyed this directive becomes false (turns red) and the second directive "Scan remaining cargo" comes up. However, the number next to this second directive starts at 14! This is definitely not the number of cargo containers remaining. I assume this is because the system treats both branches of each or as one number. Now, I am almost 100% certain there is a much more efficient way of FREDding these events, (when-argument, maybe?), so if someone has either a solution to the number problem or a better way of FREDding it, then please share.
Thank you,
A Concerned FREDder
EDIT
Disclaimer: The reason I haven't used when-argument (if that's the way to go) is because I don't understand how it works. So if someone could explain, that would be awesome.
See latest post for current questions.
-
When-argument is really easy.
It works exactly like a normal SEXP. Except.
Instead of specifying an exact ship in, say, 'is-destroyed-delay', you can say <argument> instead.
What you do is fill in the argument list (the thing that goes under every-of, or any-of, or whatever you pick, by hitting 'add data' a few times and manually typing in the arguments you want. For example, if you want 'is-destroyed-delay <argument>' to be true when Sathanas 1, 2 or 3, blows up, you would write:
when
any-of: Sathanas 1, Sathanas 2, Sathanas 3 (each as its own data entry)
is-destroyed-delay <argument>
thank-battuta
You could change the any-of to an every-of and it would become true (I believe) when all three have been destroyed.
Does that make sense?
-
Let me see if I understand you correctly.
So, using the cargo container example in my first post, say I wanted to FRED an event which checks if containers 2 and 4-9 have either been destroyed or scanned, I would use:
when-argument
every-of
Cargo 2
Cargo 4
...
Cargo 9
-or
--is-destroyed-delay
-----<argument>
--is-cargo-known-delay
-----<argument>
-do-stuff-here
Does that sound roughly right? Thanks for explaining, it makes a lot more sense now.
...and I've just thought of a complete restructuring of the mission in question, so the problems in the OP no longer apply. Thanks all.
-
That would almost work, except that it could become true if, say, several of the containers were scanned but the rest destroyed - it wouldn't only satisfy with 100% scanned or 100% destroyed. If that's what you want, good.
-
That's exactly what I want. :D
-
Question:
Say I have this:
when-argument
random-of Cargo 1, Cargo 2, Cargo 3, Cargo 4
has-arrived-delay Freighter
add-goal Freighter
ai-dock
<argument>
cargo dockpoint
cargo dockpoint
89
This gives Freighter a goal to dock with a random choice out of the 4 containers. However, if, say Cargo 1 is destroyed (or has been taken away by another transport) before Freighter arrives, will when-argument still consider it a valid option? At times I get my Freighter not doing anything after it warps in when one or more of the containers have been destroyed. Is this because when-argument is trying to get it to dock with a container that isn't there?
-
Yes. You need to use invalidate-argument to remove the container from the argument list. This may get a little tricky.
-
So if I create another event that does this:
every-time-argument
any-of Cargo 1, Cargo 2, Cargo 3, Cargo 4
is-destroyed-delay <argument>
invalidate-argument <argument>
Would that work? I'll test it now.
-
The question is not whether when-argument does, but rather whether ai-goal does this correctly. In this case, if a container is destroyed, no goal will be added (thus you get your freighter doing nothing).
What you should do is this:
( when-argument
(random-of
Cargo 1
Cargo 2
Cargo 3
Cargo 4
)
(and
(has-arrived-delay Freighter 0)
(not
(is-destroyed-delay <argument> 0)
)
(not
(=
1
@variable
)
)
)
(add-goal Freighter
ai-dock
<argument>
cargo dockpoint
cargo dockpoint
89
)
(modify-variable
@variable
1
)
)
With a repeat count of 2 or 3, and the variable set to 0 initially.
So if I create another event that does this:
every-time-argument
any-of Cargo 1, Cargo 2, Cargo 3, Cargo 4
is-destroyed-delay <argument>
invalidate-argument <argument>
Would that work? I'll test it now.
No, won't work, as argument lists are only valid in the sexp they're defined in.
-
So if I create another event that does this:
every-time-argument
any-of Cargo 1, Cargo 2, Cargo 3, Cargo 4
is-destroyed-delay <argument>
invalidate-argument <argument>
Would that work? I'll test it now.
As The_E said, argument lists are only valid within a single event. Can't be passed between events without storing to a var.
The_E's example uses a very handy technique called (maybe?) a stop variable. I like them.
-
*solution*
Could you (or someone else) perhaps explain that solution? I don't think I understand what it does.
-
It's going to pick randomly from the list of cargo items, and, so long as the cargo item selected has not been destroyed, it will order a dock with it. It will then set a var called 'variable' to 1, which prevents the SEXP from triggering again.
You'll note that if the cargo item picked has been destroyed it'll simply randomly select another argument.
You will want to use rand-multiple-of, though, and give the event a very high trigger count (I believe). Also an invalidate-all-arguments could be used instead of the var.
-
Well, basically, the problem is that if random-of chooses a cargo container that has been destroyed, ai-goal will simply exit without adding a new goal (as a freighter can't dock with something that doesn't exist).
The solution I posted simply runs the sexp until a valid target has been found using a variable to mark success.
(and
(has-arrived-delay Freighter 0)
(not
(is-destroyed-delay <argument> 0)
)
(not
(=
1
@variable
)
)
This is where the magic happens. This makes sure that the sexp only runs if
- The Freighter has arrived
- The Container chosen by random-of still exists
- The Variable has a value != 1
Now, the actual event code is nothing special; the ai goal is assigned and (crucially), the check variable is set to 1 (thus ensuring that this sexp will not run again).
It's going to pick randomly from the list of cargo items, and, so long as the cargo item selected has not been destroyed, it will order a dock with it. It will then set a var called 'variable' to 1, which prevents the SEXP from triggering again.
You'll note that if the cargo item picked has been destroyed it'll simply randomly select another argument.
You will want to use rand-multiple-of, though, and give the event a very high trigger count (I believe). Also an invalidate-all-arguments could be used instead of the var.
Yes, but it doesn't make a difference, really.
-
The invalidate-all-arguments doesn't (though it saves you a var slot and is slightly easier), but if you use rand-of instead of rand-multiple-of, won't it not work since it'll check the same argument every single time?
-
Yes, I believe so.
-
Thank you for your help so far!
I'm getting a slight problem. Basically, I'm using The_E's method for two Elysium transports (designated Transport 1 and 2), and I want each of them to pick up a random cargo container from a selection of six. Obviously the cargo container cannot be destroyed or be docked to the other transport. Transport 1 works fine, selecting a random one each time. Transport 2, however, does nothing each time I test it (it arrives after Transport 1 has departed). I've copied The_E's solution to the letter with three small modifications: there are six cargo containers instead of four, I'm using random-multiple-of rather than random-of as per General Battuta's suggestion, and the event checks both whether <argument> has been destroyed or has departed using an or statement rather just checking for destruction. The event has a repeat count of 6 and a trigger count of 99999 (also per Battuta's suggestion).
Any idea what I might be doing wrong here? If you want me to post the full event, I'll do so.
-
I did something that may relate to this in the third mission of DEM 1.5. It ensured that a certain cargo was always in the very last container you scanned. :nervous:
I did something even more similar to this, complete with AI goals and docking, in the fourth mission of the Scroll demo, but that isn't released yet...
-
Thank you for your help so far!
I'm getting a slight problem. Basically, I'm using The_E's method for two Elysium transports (designated Transport 1 and 2), and I want each of them to pick up a random cargo container from a selection of six. Obviously the cargo container cannot be destroyed or be docked to the other transport. Transport 1 works fine, selecting a random one each time. Transport 2, however, does nothing each time I test it (it arrives after Transport 1 has departed). I've copied The_E's solution to the letter with three small modifications: there are six cargo containers instead of four, I'm using random-multiple-of rather than random-of as per General Battuta's suggestion, and the event checks both whether <argument> has been destroyed or has departed using an or statement rather just checking for destruction. The event has a repeat count of 6 and a trigger count of 99999 (also per Battuta's suggestion).
Any idea what I might be doing wrong here? If you want me to post the full event, I'll do so.
Well for one thing, take away the repeat count, it's useless here.
-
I thought that was necessary for the event to run more than once? Hmm, I obviously don't fully understand the solution I'm using.
-
Trigger count and repeat count are another common point of confusion. Trigger count will alone do everything you need.
Trigger count says: 'This is the number of times the event can become true. It will become incomplete (and ready to trigger) again after it has become true.' Think of it as a semi-automatic gun; you're determining how many bullets there are in the clip but the trigger still needs to be pulled each time.
Repeat count says: 'Once the event becomes true, repeat its effects this number of times, at this fixed interval.' Think of it as a burst fire weapon that will fire X number of times each time the trigger is pulled once.
-
I see. Thanks for explaining that. I removed the repeat count and now it works! Don't know if they were related or whether it was an isolated anomaly, but it works now!
I will now list the pros and cons of what has happened so far:
Pros:
- I now have impressive-looking events that add a random element to my mission, making it more interesting and fun
- I have learned a lot about FREDding today
- I am one step closer to a demo release
- General Battuta and The_E are very helpful
Cons:
N/A
Thank you so much for your help, guys.
-
There is an issue with The E's solution which is relatively minor here but in other circumstances you could have a problem. You've kind of tripped over it with the repeat count. The issue is that you can't guarantee a maximum amount of time for the game to actually find a valid cargo. If you have 4 items of cargo you should be able to pick one after 4 loops at most. The solution here however only picks one of the options at random and there is no reason why it can't simply keep picking the 3 destroyed cargoes and ignoring the one that is intact.
For that reason I'd use this version instead. Notice this is all one event. I included the spaces for clarity.
when-argument
-random-multiple-of
Cargo 1
Cargo 2
Cargo 3
Cargo 4
-true
-when
--is-destroyed-delay
---<argument>
---0
--invalidate-argument
-when
--and
---has-arrived-delay
----Freighter
----0
---not
----is-destroyed-delay
-----<argument>
-----0
--add-goal
---Freighter
---ai-dock
---<argument>
---cargo dockpoint
---cargo dockpoint
---89
--invalidate-all-arguments
Unlike The E's solution (which it's heavily based on) this version only requires 4 repeats. Which means that after 4 * repeat delay you are guaranteed to have either picked something or had the event failed to find a cargo.
Trigger count and repeat count are another common point of confusion. Trigger count will alone do everything you need.
Trigger count says: 'This is the number of times the event can become true. It will become incomplete (and ready to trigger) again after it has become true.' Think of it as a semi-automatic gun; you're determining how many bullets there are in the clip but the trigger still needs to be pulled each time.
Repeat count says: 'Once the event becomes true, repeat its effects this number of times, at this fixed interval.' Think of it as a burst fire weapon that will fire X number of times each time the trigger is pulled once.
You're close but not quite correct. Both of them become incomplete and ready to trigger again. What is different between then is WHEN they will trigger again.
Repeat Count = Wait until the delay is over than then test again immediately. Then wait again. Do not trigger during the waiting time.
Trigger Count = Wait until the delay is over than then test again immediately. Then test every frame same as a normal event.
Both = Wait until the delay is over than then test again immediately. Then wait again. Do not trigger during the waiting time. If you run out of repeats, stop testing. If the event triggers a number of times equal to the trigger count, stop testing.
It's a small enough difference that with a 1 second delay most people don't notice that they aren't doing the same thing. Make the delay 10-20 seconds and use something like the Distance SEXPs as the trigger and you will very quickly see exactly how they differ.
Both counts actually have the correct name. The Repeat count is the number of times the game will test to see if an event has happened again before it will stop testing. The Trigger count is the number of times that test can actually come true before the game will stop testing.
-
Oh, thanks so much, karajorma! I'd actually run into the problem again where one of my transports just sits there with no orders. It might be because of what you pointed out. I'll go test it now.
-
Double post. Oh well.
Um, is there an invalidate-all-arguments SEXP? If there is, I can't seem to find it. I can get around it by simply copying the list, but yeah.
Also, for your solution, karajorma, should I set the repeat count to 4 and leave the trigger count at 1?
EDIT:
Hmmm, just tried kara's solution, and it doesn't seem to be working (and this is when none of the cargo has been destroyed). Like, my transports warp in and just sit there. :( I'm not sure what could be causing the problem, but just on a guess, in this part
-when
--is-destroyed-delay
---<argument>
---0
--invalidate-argument
Should that not be an every-time? Or am I completely misreading it?
Please help me almighty HLP.
-
Um, is there an invalidate-all-arguments SEXP? If there is, I can't seem to find it. I can get around it by simply copying the list, but yeah.
I'm sure I added one. Probably only in 3.6.13 builds only. As you say, copying the list will work too.
Also, for your solution, karajorma, should I set the repeat count to 4 and leave the trigger count at 1?
Doesn't matter in the least which one you change to 4 as long as you set the delay to 0.
Hmmm, just tried kara's solution, and it doesn't seem to be working (and this is when none of the cargo has been destroyed). I'm not sure what could be causing the problem, but just on a guess, in this part
-when
--is-destroyed-delay
---<argument>
---0
--invalidate-argument
Should that not be an every-time? Or am I completely misreading it?
Definitely shouldn't be an every-time. Every-time has absolutely no effect on is-destroyed-delay. Bear in mind that there is very little difference between what people think every-time is for and when if you have a delay of 0 in repeats.
I'm not certain why that wouldn't work (even if your delay wasn't 0). What exactly is happening? Try adding a message to both when parts of the event as well as the main body of the when-argument and tell me which messages get set off. i.e do this
when-argument
-random-multiple-of
Cargo 1
Cargo 2
Cargo 3
Cargo 4
-true
-send-message
--TESTMESSAGE1
-when
--is-destroyed-delay
---<argument>
---0
--invalidate-argument
--send-message
---TESTMESSAGE2
-when
--and
---has-arrived-delay
----Freighter
----0
---not
----is-destroyed-delay
-----<argument>
-----0
--add-goal
---Freighter
---ai-dock
---<argument>
---cargo dockpoint
---cargo dockpoint
---89
--invalidate-all-arguments
-send-message
--TESTMESSAGE3
-
Okay, just tested it. I'll post the event here just to make sure I've got it correct. (this is slightly different to the example we've used so far, but just in terms of the number of cargo containers (there's 6 instead of 4)):
-when-argument
--random-multiple-of
---Cargo 1
---Cargo 2
---Cargo 3
---Cargo 4
---Cargo 5
---Cargo 6
--true
--training-msg
---TEST 1
--when
---is-destroyed-delay
----0
----<argument>
---invalidate-argument
----<argument>
---training-msg
----TEST 2
--when
---and
----has-arrived-delay
-----0
-----Transport
----not
-----is-destroyed-delay
------0
------<argument>
---add-goal
----Transport
----ai-dock
-----<argument>
-----topside docking (it's an Elysium transport)
-----cargo dockpoint
-----89
---invalidate-argument
----Cargo 1
...
----Cargo 6
---training-msg
----TEST 3
I'm pretty sure I copied yours word for word and just changed the number of cargoes and the name of the Transport, but yeah, it's there for reference.
This event was set with a repeat count of 6, a trigger count of 1, and a delay of 0.
What happened was I only got the first test message, and that came up in the very first second of the mission. Nothing happened when the Transport arrived. :(
EDIT: Just tried it again with normal messages, and the first message triggers like six times right at the start of the mission with no break in between them. The second and third messages still don't come up.
-
Yeah, I just realised what the problem is and it should have been obvious. The event will trigger immediately upon the start of the mission and with a repeat/trigger count of 6 it will stop being checked after 6 frames.
Change the repeat count to as high as FRED will accept and it will work. Replacing the true at the top with the has-arrived-delay would also solve the problem.
-
Oh my God, thanks so much. It works. Hah, it only took three of HLP's top people, but eventually you guys got it. Thanks for helping out a lowly FREDder. Hopefully you will soon be able to play the mission this is used in.
Now (just as an aside) suppose I wanted the event to both check if the cargo has been destroyed and if it has departed (ie docked with something else and been taken away).
I assume I'd change
--when
---is-destroyed-delay
----0
----<argument>
---invalidate-argument
----<argument>
to
--when
---or
----is-destroyed-delay
-----0
-----<argument>
----has-departed-delay
-----0
-----<argument>
Right? And would I also change the not statement in the second when accordingly? Or would that require additional fiddling?
-
That should do it.
There is a departed or destroyed SEXP though that will check both for you. :D
-
****ingdammit
Something's still not right, the transport's still not docking! However, I have an exam tomorrow, so I'd better go now. I'll sleep on it and come back tomorrow with a fresh mind for a fresh start. If the problem appears again, I'll post here and let you know. Thanks so much for giving up your time for me (that goes for all three of you). Hopefully the problem will go away by itself tomorrow and I won't have to bother anyone. If I do have to bother you, hopefully we'll get this solved fairly soon.
-
Okay. This is working... mostly. 8 out of 10 times all my transports using this will dock successfully and leave (I have three transports doing this, one after the other, and I'll need to put in three more). The only difference between the events for the respective transports is that the first only checks if cargo is destroyed, and the other two check destroyed-or-departed. Now, the first one always works, the other two work most of the time, like I said. It seems maybe arguments aren't being invalidated properly or something. Do you want me to do the test message thing again?
-
It can't hurt. If you know how to output an argument in a message (via a variable) I'd suggest doing that in the test messages too.
Alternatively, just post the Event. I can often diagnose problems just looking at them.
-
Okay. This is going to be a long post. As I said, I have three events doing this for three transports. They only differ minorly, but I'll post them all here just in case
Event 1:
-when-argument
--random-multiple-of
---Cargo 1
---Cargo 2
---Cargo 3
---Cargo 4
---Cargo 5
---Cargo 6
--has-arrived-delay
---1
---Tugboat
--when
---is-destroyed-delay
----0
----<argument>
---invalidate-argument
----<argument>
--when
---and
----has-arrived-delay
-----1
-----Tugboat
----not
-----is-destroyed-delay
------0
------<argument>
---add-goal
----Tugboat
----ai-dock
-----<argument>
-----topside docking
-----cargo dockpoint
-----89
---invalidate-argument
----Cargo 1
----Cargo 2
----Cargo 3
----Cargo 4
----Cargo 5
----Cargo 6
Event 2 (this transport comes in after the first has docked, so it checks both if the cargo has been destroyed and if it has been docked with the first transport):
-when-argument
--random-multiple-of
---Cargo 1
---Cargo 2
---Cargo 3
---Cargo 4
---Cargo 5
---Cargo 6
--has-arrived-delay
---1
---Tugboat#2
--when
---or
----is-destroyed-delay
-----0
-----<argument>
----has-docked-delay
-----Tugboat
-----<argument>
-----1
-----0
---invalidate-argument
----<argument>
--when
---and
----has-arrived-delay
-----1
-----Tugboat#2
----not
-----or
------is-destroyed-delay
-------0
-------<argument>
------has-docked-delay
-------Tugboat
-------<argument>
-------1
-------0
---add-goal
----Tugboat#2
----ai-dock
-----<argument>
-----topside docking
-----cargo dockpoint
-----89
---invalidate-argument
----Cargo 1
----Cargo 2
----Cargo 3
----Cargo 4
----Cargo 5
----Cargo 6
Event 3 (this third transport comes in after both the earlier ones have departed, so this event checks destroyed-or-departed):
-when-argument
--random-multiple-of
---Cargo 1
---Cargo 2
---Cargo 3
---Cargo 4
---Cargo 5
---Cargo 6
--has-arrived-delay
---1
---Truck
--when
---destroyed-or-departed-delay
----0
----<argument>
---invalidate-argument
----<argument>
--when
---and
----has-arrived-delay
-----1
-----Truck
----not
-----destroyed-or-departed-delay
------0
------<argument>
---add-goal
----Truck
----ai-dock
-----<argument>
-----cargo dockpoint
-----cargo dockpoint
-----89
---invalidate-argument
----Cargo 1
----Cargo 2
----Cargo 3
----Cargo 4
----Cargo 5
----Cargo 6
Okay, there's those. Now, like I said before, I'm getting inconsistency with these events. Sometimes they work and sometimes they don't. I did some testing, and it may possibly be related to interval time for some obscure reason. Here's what I've got:
For all the events' interval time set to 0, the first always works, and the second never does. The third transport never arrives as the second one never leaves so I can't test that.
When the interval time for events 1 and 3 is set to 0 and for event 2 it's set to 1, the first and second transport worked three out of three times I tested, but the third only worked once.
When the interval time for events 2 and 3 is set to 1 and for event 1 its set to zero, the first transport worked three out of three times, and I got inconsistency with both the second and third transports.
Now I don't know if this is in any way related, but yeah... it's there just in case.
Thanks for looking at it, karajorma.
-
What repeat counts did you have for the events? What happens if you just stick the number of repeats to maximum. Also, what happens if you change the name of Tugboat#2 to something not using a '#'?
-
I removed the # from the Tugboat name, and set the repeats to maximum. They were initially at six. It's better now, only 1 time out of 8 the second transport didn't dock, and another time, the third transport didn't dock. Hmmm.
-
Do you use any mods? If not, I'd like to look at this mission.
-
I have some additional ships for the campaign, but they're not in use for this mission. I'll PM you the mission.
-
Haven't had much of a look at this but I have noticed that your interval time for the 2nd two ships is 1 second rather than 1 frame. Set the interval to 0 and you may have more luck with this.
I'd suggest making a test mission just involving the cargo and tugboats to see if that has the issue too.