Lucky44 13 Posted October 17, 2009 (edited) I'm trying to do a randomizing thing. I want to have five or six groups of enemies (AI). At a certain time, a random number will pick one group and trigger them to move to their next waypoint, assaulting the players' position. EDIT: I realize now that the best way to do this is with arrays, and with dengibtsschon's help (see below) I'm working on that. But here's one way to do it in a single script. A trigger calls this, but you could set it up in an init.sqf file or a trigger with a radio call to start it, etc. The script is handy for generating random numbers in a group, keeping track of which have been used, and generating more from the ones that remain. MUCH EDITED CODE below. Now all in one script: // Random Number selection // Picks random number from one to six, then picks from remaining, etc., etc. // let's you set time between number "rolls" using "sleep" & "random" calls. // By Lucky44 if (! isServer) exitwith {}; // NOTE: in multiplayer, only server should create random numbers. n1=0; // if you want to make this repeatable (like by radio calls) n2=0; // these will reset values of the variables n3=0; n4=0; n5=0; n6=0; // first roll /////////////////////////////////////////////////////////////// n1 = round ((random 6) + 0.5); x=n1; // I'm passing the value found in n1 to x for use in triggers, etc. sleep (random 10); // to alter time between "rolls", change this sleep value // ////////////////////////////////////////////////////////////////////////// // 2nd roll: start n2 /////////////////////////////////////////////////////// n2 = round ((random 6) + 0.5); while {n2==n1} do { n2 = round ((random 6) + 0.5); }; x=n2; sleep (random 10); // to alter time between "rolls", change this sleep value // ////////////////////////////////////////////////////////////////////////// // 3rd roll: start n3 /////////////////////////////////////////////////////// n3 = round ((random 6) + 0.5); while {(n3==n1) or (n3==n2)} do { n3 = round ((random 6) + 0.5); }; x=n3; sleep (random 10); // to alter time between "rolls", change this sleep value // //////////////////////////////////////////////////////////////////////////// // 4th roll: start n4 ///////////////////////////////////////////////////////// n4 = round ((random 6) + 0.5); while {(n4==n1) or (n4==n2) or (n4==n3)} do { n4 = round ((random 6) + 0.5); }; x=n4; sleep (random 10); // to alter time between "rolls", change this sleep value // //////////////////////////////////////////////////////////////////////////// // 5th roll: start n5 ///////////////////////////////////////////////////////// n5 = round ((random 6) + 0.5); while {(n5==n1) or (n5==n2) or (n5==n3)or (n5==n4)} do { n5 = round ((random 6) + 0.5); }; x=n5; sleep (random 10); // //////////////////////////////////////////////////////////////////////////// // 6th roll: start n6 ///////////////////////////////////////////////////////// n6 = round ((random 6) + 0.5); while {(n6==n1) or (n6==n2) or (n6==n3) or (n6==n4) or (n6==n5)} do { n6 = round ((random 6) + 0.5); }; x=n6; // //////////////////////////////////////////////////////////////////////////// Thanks in advance for any help! Edited October 19, 2009 by Lucky44 Share this post Link to post Share on other sites
Big_Daddy 10 Posted October 17, 2009 looks like your mixing sqs and sqf. Share this post Link to post Share on other sites
Lucky44 13 Posted October 17, 2009 (edited) looks like your mixing sqs and sqf. OK, thanks. Any idea how to make it all .sqs? Or should it be .sqf (for Arma2) ? And while I'm at it, what's the difference between .sqf and .sqs? EDIT: I see that SQS is the older format, and it uses single line structure (vs. a command spread over multiple lines) Edited October 17, 2009 by Lucky44 Share this post Link to post Share on other sites
Murklor 10 Posted October 17, 2009 Doesnt look like the scripts doesnt actually do anything? Oh and one critical error is using "if ( b = c )". You need to use == or its a variable assingment insteas. Share this post Link to post Share on other sites
blakeace 11 Posted October 17, 2009 @Lucky44 I have found the BIS Wiki to be very helpful when it comes to confirming the syntax of your scripts. http://community.bistudio.com/wiki/sqs http://community.bistudio.com/wiki/sqf http://community.bistudio.com/wiki/Control_Structures Share this post Link to post Share on other sites
poweruser 10 Posted October 17, 2009 (edited) You can do this a lot easier and with only one script, instead of one for each draw. In the mission init script, define an array containing your five squads, like: squadarray = [1,2,3,4,5]; Instead of the numbers you can also store the groups directly, then you don't have to translate from the number to the group later. (l1 be the leader of squad1, l2 be the leader of squad2, and so on...) squadarray = [group l1, group l2, group l3, group l4, group l5]; then thats the whole sqf script: EDITED: fixed a typo, updated entry selection private["_array","_rnd"];_array = _this select 0; _rnd = _array select (floor(random(count _array))); // picks a random entry of the array 'squadarray' _array = _array - [_rnd]; // removes the picked entry from the array executed with: [squadarray] execVm "scriptname.sqf"; The clue here is to memorize the set of entries that are valid to pick, and after you picked something you remove the picked one from the set. That avoids writing extra scripts for each time. The local variable _rnd is the selected entry from the set, it corresponds to the variable 'x' in your scripts ADDED: Multiplayer notes: Make sure that you run this script only on the server as otherwise every connected machine would generate a different random number. Edited October 18, 2009 by dengibtsschon fixed a typo, added mp notes Share this post Link to post Share on other sites
Lucky44 13 Posted October 18, 2009 (edited) Deng, I *think* I (roughly) follow you. But I'm not sure how to then implement the script with the two variables _array and _rnd. How do I use the script and array to choose which group should move beyond its current waypoint? In a trigger at the waypoints where they wait, I have a condition like "X == 1" for one group and "X == 2" for another group. How would I change those conditions to use the _rnd? (And I tried putting _rnd into the trigger, but it complained about a local variable in a global space.) Sorry to be so clueless! Edited October 18, 2009 by Lucky44 Share this post Link to post Share on other sites
tcp 10 Posted October 18, 2009 (edited) Just a correction on the random select (you don't want to end up with negative numbers): floor(random(count _array)) You either to need to integrate the selection into your script, pass _array and _rnd to the next script, or update squadarray otherwise you will lose which squads are still left. _rnd doesn't hold a number, it holds the actual value from squadarray which contains the group object. group L1 is the group of the unit named L1. If you are still confused, you should post your whole script, so we can show you were to integrate it. Also, goto isn't used in SQF. Edited October 18, 2009 by tcp Share this post Link to post Share on other sites
Lucky44 13 Posted October 18, 2009 (edited) You either to need to integrate the selection into your script, pass _array and _rnd to the next script, or update squadarray otherwise you will lose which squads are still left. _rnd doesn't hold a number, it holds the actual value from squadarray which contains the group object. group L1 is the group of the unit named L1. OK, thanks. Where I'm stuck is HOW to pass _array and _rnd to anything else. If you are still confused, you should post your whole script, so we can show you were to integrate it. I'm still confused, but I don't have any script. Now I'm trying to use what Deng posted above (with your change noted) and integrate that into the mission. What I'm trying to do is have roughly five groups waiting near the place the players are defending. At a interval of about 100 seconds each (with some random variance to it) a random group will head into the players' area and attack. I've been using triggers and waypoints to hold the groups at their first waypoints. My thought was to have a simple "die roll" effect: roll a die and if 1 comes up, then the first group's trigger will fire and have them continue on their path. Then wait from 80-110 seconds and roll again. (And if I roll a 1 the second time, I have to roll again till I get something else, etc. That's not real efficient, but in computer flops, and given the small numbers I'm dealing with, it seemed OK. But I get the basic concept of creating an array, pulling one from it and then lowering the members of the array, etc. Just not sure how to implement it.) Also, goto isn't used in SQF. So how DO you replace the goto idea in a SQF? Do you just say "#continue" instead of "goto 'continue' "? Edited October 18, 2009 by Lucky44 Share this post Link to post Share on other sites
tcp 10 Posted October 18, 2009 It's not supported. SQF has a linear flow for a single script. For loops: for, while, and forEach is used. If you need to do something in parallel, you spawn a new process. If you need to do something repeatedly, you call a previously define function. It's rare that you can't do everything you need to in one script, though. There happens to be a command http://community.bistudio.com/wiki/breakTo that will exit to that point in the script, but its different from goto. You can't go back in the script. It will just skip everything until it's back in the outer scope. I'll try to come up with a example script to do what you want, when I have time. Share this post Link to post Share on other sites
Lucky44 13 Posted October 18, 2009 (edited) (see below) Edited October 18, 2009 by Lucky44 Share this post Link to post Share on other sites
poweruser 10 Posted October 18, 2009 (edited) Ok, here's one way to implement it then: A waypoint has a condition, when it's false the group perfroms that waypoints (the one with condition being 'false') orders but then waits for the condition to become 'true' before performing the next waypoint. Give those waypoints that send the groups at the place where they shall wait first, before being sent to attack, following conditions: for the 1st group: 1 in attackorders for the 2nd group: 2 in attackorders and so on.. In the mission init script, define this: squadarray = [1,2,3,4,5]; attackorders = []; And this is the complete script. Only execute it once, at the time you want the groups to start attacking. if(isServer) then { [] execvm "scriptname.sqf"; }; scriptname.sqf: private["_rnd"]; while {count squadarray > 0} do { [indent]_rnd = squadarray select (floor(random(count squadarray))); squadarray = squadarray - [_rnd]; attackorders = attackorders + [_rnd]; sleep (90 + random 20);[/indent] }; ================================================ @while loop in first post script example: you have to use the double equals sign == ,when you want to check whether two values are equal. Single equal signs = are used for assignments. The OR is correct there, I usually use ||, it does the same thing. Additionally the syntax of your 2nd while loop is wrong. And you need to define the variable 'c' first, before you use it. (same goes for the other while loop) c = round ((random 4) + 0.5); while {c==a OR c==b} do { c = random 4; c = c + 0.5; c = round c; }; Edited October 19, 2009 by dengibtsschon changed the attackorder concept a bit, as the previous one was not bullet-proof Share this post Link to post Share on other sites
Lucky44 13 Posted October 18, 2009 (edited) OK, I'm trying to use a WHILE loop. I posted the code at the first post. It's no longer crashing to desktop, but it's not picking a number and implementing it either. Hmm... I've just found Cheetah's "Basics of SQF" which I'll look at now. ---------- Post added at 11:08 PM ---------- Previous post was at 09:27 PM ---------- Wow, thanks so much for taking the time to write that up, Deng. that was generous of you. I've put it together in a little demo mission to test. I'm not sure I'm doing one thing right. You wrote: And this is the complete script. Only execute it once, at the time you want the groups to start attacking. if(isServer) then { [] execvm "scriptname.sqf"; }; scriptname.sqf: private["_rnd"]; while (count squadarray > 0) do { [indent]_rnd = squadarray select (floor(random(count _array))); squadarray = squadarray - [_rnd]; attackorders = attackorders + [_rnd]; sleep (90 + random 20);[/indent] }; And I'm not clear on that first line. Does this part: if(isServer) then { [] execvm "scriptname.sqf"; }; go in a trigger, and if so, is the "isServer" in the Condition and the {execVM...} in the Activation? Or should another script be used to fire that line? I tried it using a trigger to test for server and call for the script. It's firing the script, but it's not moving the groups. Could that be because the groups (or the group leaders) need to have certain names? If so, what would they need to be? I know it's firing because I have some debugging text in there, but no one is moving. btw, here's the code as I've set it up in a script called 'random_go.sqf' titletext ["Starting 'random_go.sqf' script.", "PLAIN"]; private["_rnd"]; while (count squadarray > 0) do { hint "Calling first group..."; _rnd = squadarray select (floor(random(count _array))); squadarray = squadarray - [_rnd]; attackorders = attackorders + [_rnd]; sleep (1 + random 15); }; Edited October 18, 2009 by Lucky44 Share this post Link to post Share on other sites
poweruser 10 Posted October 18, 2009 Does this part: if(isServer) then { [] execvm "scriptname.sqf"; };go in a trigger, and if so, is the "isServer" in the Condition and the {execVM...} in the Activation? Or should another script be used to fire that line? When you use a trigger, all of it goes into the 'On Activation' field. You can also use another script to do it, whatever you like. Like I said, run it at the time you want the groups to start attacking, where you do it is up to you. I tried it using a trigger to test for server and call for the script. It's firing the script, but it's not moving the groups. Then you haven't either defined the two arrays in the init.sqf. Or you didn't set up the waypoints of the groups, the way I suggested it at the beginning of my last post. Share this post Link to post Share on other sites
Lucky44 13 Posted October 18, 2009 Then you haven't either defined the two arrays in the init.sqf. Or you didn't set up the waypoints of the groups, the way I suggested it at the beginning of my last post. First, I did my best to set up the waypoints as you described, but it wasn't 100% clear to me. Here's what I did: I have each group moving to a first waypoint. That waypoint's condition box now has "1 in attackorders" (and the 2nd group's says "2 in attackorders"). So they wait at that first waypoint. Then they each have a succeeding waypoint to move to, eventually. I know the script is firing, as I said, because the text messages are appearing. But I put a final hint text to fire when it was all over, at the end, and it never fires. Also, I'm wondering if the line _rnd = squadarray select (floor(random(count _array))); should rather be _rnd = squadarray select (floor(random(count squadarray))); since I didn't see any reference to "_array" anywhere else??? Could there be a typo in there? And I guess I'm not understanding how the "1 in attackorders" in the waypoints' conditions gets told that the condition is true. And yes, I have the init.sqf looking like this: squadarray = [1,2,3,4,5]; attackorders = []; Share this post Link to post Share on other sites
poweruser 10 Posted October 19, 2009 Also, I'm wondering if the line _rnd = squadarray select (floor(random(count _array))); should rather be _rnd = squadarray select (floor(random(count squadarray))); Oh well, that's my error. Change it, then it should work. Share this post Link to post Share on other sites
Lucky44 13 Posted October 19, 2009 Well, I'm not sure what's wrong, but something is not working. I appreciate your help, though. I do understand that arrays would be a better way to do this kind of thing. (I could upload the mission where it's not working, if anyone wants to see it and take a shot at troubleshooting.) Share this post Link to post Share on other sites