Auss 208 Posted July 16, 2010 I've been using the random script from Mr-Murrays excellent bible. if (notisServer) exitWith {start = random 4 ?start < 1 : goto "north"; ?start < 2 : goto "east"; ?start < 3 : goto "south"; ?start < 4 : goto "west"; exit #north hint "north"; exit #east hint "east"; exit #south hint "south"; exit #west hint "west"; exit }; But when I host it up on my machine it seems to generate different values for each client. I am using a trigger at the start of the game with Bluefor present calling it via "this exec "random.sqf". Anyone have any ideas? Cheers Share this post Link to post Share on other sites
kylania 568 Posted July 16, 2010 You have a strange mix of SQS (obsolete) and SQF (preferred) in there... A few notes, random returns a float, as in 0.12312 instead of a whole number. To get 1-4 type results use round(random 4) for example. Also, goto is the devil. :) Here's that same script rewritten in SQF: if (isServer) then { dirNum = round(random 3); // results in 0, 1, 2 or 3 switch (dirNum) do { case 0: {hint "North"}; case 1: {hint "East"}; case 2: {hint "South"}; case 3: {hint "West"}; }; }; Share this post Link to post Share on other sites
Murklor 10 Posted July 16, 2010 Sure you use if (notisServer) exitWith ? Because that tests a global variable called notisServer, it doesnt check if its not the server :) Try if(!isServer) instead. And dont use an SQS either. How about something similar to this as an SQF, calling it from the trigger with [this]: if (!isServer) exitWith {}; _trigger = _this select 0; _hintArray = ["North","East","South","West"]; _trigger setVariable ["randomDir",(_hintArray select (round (random 3))),true]; hint format ["Direction: %1",_trigger getVariable "randomDir"]; UNTESTED, just made it up. Note that the randomization is flawed, its a higher chance that it becomes 1 or 2 than it is 0 and 3. I keep forgetting the best math way to fix it, lol. If you want the clients to know what the server value is, just do *triggername* getVariable "randomDir" and you should read it. Share this post Link to post Share on other sites
shuko 59 Posted July 16, 2010 Note that the randomization is flawed, its a higher chance that it becomes 1 or 2 than it is 0 and 3. I keep forgetting the best math way to fix it, lol. Using "round" doesnt give equal probabilities to all cases. round(random 3) case 0: 0-0.49 => 16% case 1: 0.5-1.49 => 33% case 2: 1.5-2.49 => 33% case 3: 2.5-2.99 = > 16% floor(random 4) case 0: 0-0.99 => 25% case 1: 1-1.99 => 25% case 2: 2-2.99 => 25% case 3: 3-3.99 => 25% Share this post Link to post Share on other sites
Auss 208 Posted July 16, 2010 if (isServer) then { dirNum = round(random 3); // results in 0, 1, 2 or 3 switch (dirNum) do { case 0: {hint "North"}; case 1: {hint "East"}; case 2: {hint "South"}; case 3: {hint "West"}; }; }; Couldnt seem to get this one to work? Share this post Link to post Share on other sites
shuko 59 Posted July 16, 2010 It uses "isserver", thus it will only show hints in SP or to the host in hosted/listen MP. Share this post Link to post Share on other sites
Auss 208 Posted July 17, 2010 (edited) Thanks for the replies and explinations Shk and others. I tested it in MP mode (me as the server) and nobody saw the hints. Anyone have any ideas of how I can generate random values? I want to spawn enemy in a random location around a base. Edited July 17, 2010 by Aussie Share this post Link to post Share on other sites
kylania 568 Posted July 17, 2010 Either method works. dirNum = floor(random 4); // results in 0, 1, 2 or 3 switch (dirNum) do { case 0: {hint "North"}; case 1: {hint "East"}; case 2: {hint "South"}; case 3: {hint "West"}; }; Try that. Share this post Link to post Share on other sites
Auss 208 Posted July 17, 2010 Ok I put dirNum = floor(random 4); // results in 0, 1, 2 or 3switch (dirNum) do { case 0: {hint "North"}; case 1: {hint "East"}; case 2: {hint "South"}; case 3: {hint "West"}; }; Into random.sqf file then launched it via a bluefor present trigger, [] exec "random.sqf" on activation line, still not getting any hints in the editor? Share this post Link to post Share on other sites
kylania 568 Posted July 17, 2010 exec is used to call SQS scripts, you need to use this for SQF: rndDir = [] execVM "random.sqf"; Share this post Link to post Share on other sites
Auss 208 Posted July 17, 2010 Thanks for your patience Kylania I've just tried that in the editor and its working, I'll test in MP with some clients and let you know, thanks again!! Share this post Link to post Share on other sites
kylania 568 Posted July 17, 2010 (edited) No problem at all. For multiplayer you probably want to have it like this. Note that it requires you to have placed the Functions module first since it uses the Multiplayer Framework function. // Place the Functions module on your map first! // Initialize Functions waitUntil{!(isNil "BIS_fnc_init")}; waitUntil{!(isNil "BIS_MPF_InitDone")}; // Run from a trigger it will activate on all clients, by making // it check for isServer this will only run on the server. The // rHINT function will broadcast the direction to all clients. // This way we only get one direction instead of everyone getting // a different direction. if (isServer) then { _dirNum = floor(random 4); // results in 0, 1, 2 or 3 _dirChoices = ["North","East","South","West"]; _rndDir = _dirChoices select _dirNum; _rndDirhint = [nil,nil,"per",rHINT,_rndDir] call RE; }; Update: Confirmed this works in MP on an Dedicated server, everyone gets the same hint. Use this. :) Edited July 17, 2010 by kylania Test confirmed. Share this post Link to post Share on other sites
Auss 208 Posted July 17, 2010 (edited) I can confirm its working in MP. Thanks Kylania I'm almost there. 2 questions, 1) Can you explain please how the script works (so I understand better) :) 2) Whats the best way for me to now use that script in my mission to call other scripts based on what direction it calls? for example I have north.sqf which spawns inf if North is called. Edited July 17, 2010 by Aussie Share this post Link to post Share on other sites
kylania 568 Posted July 17, 2010 This section make the script wait for the Functions module to be ready to work. Once the module is loaded it sets variables for BIS_fnc_init and BIS_MPF_InitDone saying it's ready. We're just waiting for it to say that. :) // Initialize Functions waitUntil{!(isNil "BIS_fnc_init")}; waitUntil{!(isNil "BIS_MPF_InitDone")}; Since you're running this from a Trigger, that means that all clients connected to the server will run the script. We use the isServer check and the { } block so that only the server does the check for direction. Otherwise every client would get their own random direction. if (isServer) then { ... }; This line picks a random number from 0 to 3. Random starts counting from 0 and since we're using "floor" to round down the numbers we tell it to pick 4 numbers and get 0, 1, 2 and 3. Using floor, as shk pointed out, gives us an even distribution than we could have gotten using round. We save this number as _dirNum, a variable name we made up. _dirNum = floor(random 4); // results in 0, 1, 2 or 3 Here we declare an array of possible locations. [ ] indicate that it's an array. _dirChoices = ["North","East","South","West"]; Here we use the _dirNum from before to select a value from the _dirChoices array we just declared. Handily enough arrays start to count from 0 too, so our 0-3 number nicely matches up with 0-3 values in the array. 0 = North, 1 = East.. and so on. We'll set a variable we made up called _rndDir. So if _dirNum was 3, the last spot in the array then _rndDir would be "West". _rndDir = _dirChoices select _dirNum; This is the tricky part. It's relying on something called the Multiplayer Framework system BIS has provided us with. Basically this is a long complicated line that will sent a Hint to all clients connected (and anyone joining later will get it too once they log in, hence the "per" section there) with the text from _rndDir. _rndDirhint = [nil,nil,"per",rHINT,[b][color="REd"]_rndDir[/color][/b]] call RE; Now, to expand on this we could make the direction available globally by setting a publicVariable to the value of _rndDir. We'll assign it to a new global variable. To make things easier I'd probably change your 4 scripts to be one script that looks for a value to determine what to do. That way you can do something like this: // Place the Functions module on your map first! // Initialize Functions waitUntil{!(isNil "BIS_fnc_init")}; waitUntil{!(isNil "BIS_MPF_InitDone")}; // Run from a trigger it will activate on all clients, by making // it check for isServer this will only run on the server. The // rHINT function will broadcast the direction to all clients. // This way we only get one direction instead of everyone getting // a different direction. if (isServer) then { _dirNum = floor(random 4); // results in 0, 1, 2 or 3 _dirChoices = ["North","East","South","West"]; _rndDir = _dirChoices select _dirNum; _rndDirhint = [nil,nil,"per",rHINT,_rndDir] call RE; [color="RED"] currentDirection = _rndDir; publicVariable "currentDirection";[/color] }; By calling publicVariable on our new currentDirection value it will update it across all the clients, so everyone has the same direction remembered. Now you can have another trigger running your directionAction.sqf or whatever like this: nul = [currentDirection] execVM "directionAction.sqf"; So in our example where we "rolled" a 3, that would mean that currentDirection would be equal to "West", so in directionAction.sqf you'd say: _dir = _this select 0; and _dir inside your action script would be "West". It's like 8am and I'm exhausted, so this probably didn't make any sense, so let me know if it didn't. :) Share this post Link to post Share on other sites
shuko 59 Posted July 17, 2010 You really do not need to load the whole MP framework for something like this. init.sqf if isServer then { curDir = ["North","East","South","West"] select floor(random 4); publicVariable "curDir"; }; if !isdedicated then { [] spawn { waituntil {!isnil "curDir"}; hint curDir; }; }; Share this post Link to post Share on other sites
Auss 208 Posted July 17, 2010 Gents I appreciate the help here but I cant seem to get my head around it. Kylania I followed your post up till the last section, I cant seem to work out how to call my spawning scripts after we have generated a bearing. Now you can have another trigger running your directionAction.sqf or whatever like this:Code: nul = [currentDirection] execVM "directionAction.sqf";So in our example where we "rolled" a 3, that would mean that currentDirection would be equal to "West", so in directionAction.sqf you'd say: Code: _dir = _this select 0;and _dir inside your action script would be "West". I understand how its calling "west" but I'm not sure on getting it to call my "westspawn.sqf" Share this post Link to post Share on other sites
kylania 568 Posted July 17, 2010 I understand how its calling "west" but I'm not sure on getting it to call my "westspawn.sqf" The point is that it's possibly difficult to get "west" to call "westspawn.sqf", it's much easier to make a script called "spawn.sqf" that has instructions for each direction and feed it "west" to tell it what to do. Share this post Link to post Share on other sites