Jump to content
Sign in to follow this  
Lucky44

Simple scripting? Something's going wrong

Recommended Posts

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 by Lucky44

Share this post


Link to post
Share on other sites
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 by Lucky44

Share this post


Link to post
Share on other sites

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

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 by dengibtsschon
fixed a typo, added mp notes

Share this post


Link to post
Share on other sites

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 by Lucky44

Share this post


Link to post
Share on other sites

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 by tcp

Share this post


Link to post
Share on other sites

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 by Lucky44

Share this post


Link to post
Share on other sites

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

(see below)

Edited by Lucky44

Share this post


Link to post
Share on other sites

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 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

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 by Lucky44

Share this post


Link to post
Share on other sites
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

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
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

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

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
Sign in to follow this  

×